Java - Bouncy CaSTLe 中的椭圆曲线场元素算术

标签 java cryptography bouncycastle elliptic-curve

我一直认为使用 ECFieldElement 对象而不是 BigIntegers 对指数执行算术运算更合适,但根据我的测试,这样做会产生不正确的结果。

测试例程(JUnit):

class ArithmeticTest
{

  @Test
  public void testMultDistributativity_BigInteger()
  {
      ECPoint g = getG();

      for (int i=0; i<100; i++)
      {
        BigInteger a, b, c;

        a = randomIntInField(false);
        b = randomIntInField(false);
        c = a.add(b);

        ECPoint gA = g.multiply(a);
        ECPoint gB = g.multiply(b);
        ECPoint gC = g.multiply(c);
        ECPoint sum = gA.add(gB);

        assertEquals(gC, sum);
      }
  }

  @Test
  public void testMultDistributativity_ECFieldElement_SmallValues()
  {
      assertTrue(checkMultDistributativity_ECFieldElement(BigInteger.ONE, BigInteger.TEN));
  }

  @Test
  public void testMultDistributativity_ECFieldElement_RandomValues()
  {
      BigInteger a, b;
      int failureCount=0;

      for (int i=0; i<1000; i++)
      {
        a = randomIntInField(false);
        b = randomIntInField(false);

        if (!checkMultDistributativity_ECFieldElement(a, b))
            failureCount++;
      }

      assertTrue(failureCount==0, "Failed on " + Integer.toString(failureCount) + " out of 1000 runs.");
  }

  private boolean checkMultDistributativity_ECFieldElement(BigInteger a, BigInteger b)
  {
      ECFieldElement fA, fB, fC;
      ECPoint gA, gB, gC, sum;

      fA = getFieldElement(a);
      fB = getFieldElement(b);
      fC = fA.add(fB);

      gA = getG().multiply(a);
      gB = getG().multiply(b);
      gC = getG().multiply(fC.toBigInteger());
      sum = gA.add(gB);

      return gC.equals(sum);
  }

testMultDistributativity_BigIntegertestMultDistributativity_ECFieldElement_SmallValues 成功,但 testMultDistributativity_ECFieldElement_RandomValues 在一半的测试用例中失败。

顺便说一句,1/2 是两个随机场元素加起来大于场序的数字的概率。我不明白这怎么会把事情搞砸。

加载曲线:

  private java.security.spec.EllipticCurve curve;
  private org.bouncycastle.math.ec.ECCurve bcCurve;
  private ECNamedCurveParameterSpec spec;
  private final BigInteger fieldOrder;
  private static final int FIELD_ELEMENT_BIT_SIZE = 256;

  static {
    Security.insertProviderAt(new BouncyCastleProvider(), 1);
  }

  public ArithmeticTest()
  {
    spec= ECNamedCurveTable.getParameterSpec("secp256r1");
    bcCurve = spec.getCurve();

    ECNamedCurveSpec conversionSpec = new ECNamedCurveSpec(spec.getName(), spec.getCurve(), spec.getG(), spec.getN());
    curve = conversionSpec.getCurve();

    fieldOrder = new BigInteger ("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16);
  }

这些是辅助函数:

  private ECPoint getG()
  {
    return spec.getG();
  }

  private ECFieldElement getFieldElement(BigInteger i)
  {
    return bcCurve.fromBigInteger(i);
  }

  private randomIntInField(boolean nonzero)
  {
    final int ARGUMENT_IS_LARGER = -1;
    SecureRandom rand = new SecureRandom();
    BigInteger result;
    int watchDog = 1000;

    do {
        result = new BigInteger(FIELD_ELEMENT_BIT_SIZE, rand);

        if (--watchDog == 0)
            throw new RuntimeException("Damn what are the odds?");
    }
    while ( nonzero && result.equals(BigInteger.ZERO) || result.compareTo(fieldOrder)!= ARGUMENT_IS_LARGER);

    return result;

  }
}

问题可能是随机化造成的吗?

最佳答案

I have been under the impression that it is more proper to perform arithmetic operations on exponents using ECFieldElement objects instead of BigIntegers, but according to my tests, doing so yields incorrect results.

不!指数(ECPoint.multiply 的标量参数)绝对不能使用 ECFieldElement 处理。标量应以组阶数为模相互添加,可通过 ECCurve.getOrder 获得。

因此,只要 fC 总和相对于场模量减少(如您所说,约为 50%),您的测试就会失败。

关于Java - Bouncy CaSTLe 中的椭圆曲线场元素算术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45759586/

相关文章:

Java反向/反向引用

java - RSA,如何向后通信

java - 数据未在代码名称 BouncyCaSTLe 中对齐 block 大小(无填充)

c# - BouncyCaSTLe PrivateKey 到 X509Certificate2 PrivateKey

winapi - 使用 CryptUIWizDigitalSign API 签署 appxbundle

java - 向 X509 证书添加特定扩展名 (bouncyCaSTLe)

java - 使用jquery在jsp页面中接受http session 请求参数

java - 如何修复 getAge() 以获取代码中最大学生的年龄?

java - 从 Eclipse 生成可执行文件

android - 如何验证 Web 服务调用的来源