我一直认为使用ECFieldElement对象而不是BigIntegers对exponents执行算术运算更合适,但根据我的测试,这样做会产生不正确的结果。
测试例程(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;
}
}
问题可能来自于某种程度的随机化吗?
答案 0 :(得分:2)
我一直认为表演更合适 使用ECFieldElement对象对指数进行算术运算 而不是BigIntegers,但根据我的测试,这样做会产生 结果不正确。
没有!指数(ECPoint.multiply的标量参数)绝对不能使用ECFieldElement处理。 Scalars应以模块组的顺序相互添加,可通过ECCurve.getOrder获得。
因此,无论何时总和fC相对于场模数降低(约50%,如你所说),你的测试就会失败。