我一直认为使用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_BigInteger
和testMultDistributativity_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;
}
}
问题可能出自某种程度上的随机化吗?
最佳答案
我一直觉得执行起来更合适
使用ECFieldElement对象对指数进行算术运算
而不是BigIntegers,但是根据我的测试,这样做会产生
错误的结果。
没有!绝对不能使用ECFieldElement处理指数(ECPoint.multiply的标量参数)。标量应以组顺序为模彼此添加,可通过ECCurve.getOrder获得。
因此,只要总和fC相对于场模降低(如您所说的〜50%),您的测试就会失败。