package org.bouncycastle.math.ec.custom.sec.test; import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.math.ec.ECFieldElement; import org.bouncycastle.math.raw.Nat; import junit.framework.TestCase; public class SecP384R1FieldTest extends TestCase { private static final SecureRandom RANDOM = new SecureRandom(); private static final X9ECParameters DP = CustomNamedCurves .getByOID(SECObjectIdentifiers.secp384r1); private static final BigInteger Q = DP.getCurve().getField().getCharacteristic(); public void testMultiply1() { int COUNT = 1000; for (int i = 0; i < COUNT; ++i) { ECFieldElement x = generateMultiplyInput_Random(); ECFieldElement y = generateMultiplyInput_Random(); BigInteger X = x.toBigInteger(), Y = y.toBigInteger(); BigInteger R = X.multiply(Y).mod(Q); ECFieldElement z = x.multiply(y); BigInteger Z = z.toBigInteger(); assertEquals(R, Z); } } public void testMultiply2() { int COUNT = 100; ECFieldElement[] inputs = new ECFieldElement[COUNT]; BigInteger[] INPUTS = new BigInteger[COUNT]; for (int i = 0; i < inputs.length; ++i) { inputs[i] = generateMultiplyInput_Random(); INPUTS[i] = inputs[i].toBigInteger(); } for (int j = 0; j < inputs.length; ++j) { for (int k = 0; k < inputs.length; ++k) { BigInteger R = INPUTS[j].multiply(INPUTS[k]).mod(Q); ECFieldElement z = inputs[j].multiply(inputs[k]); BigInteger Z = z.toBigInteger(); assertEquals(R, Z); } } } public void testSquare() { int COUNT = 1000; for (int i = 0; i < COUNT; ++i) { ECFieldElement x = generateMultiplyInput_Random(); BigInteger X = x.toBigInteger(); BigInteger R = X.multiply(X).mod(Q); ECFieldElement z = x.square(); BigInteger Z = z.toBigInteger(); assertEquals(R, Z); } } public void testSquare_CarryBug() { int COUNT = 100; for (int i = 0; i < COUNT; ++i) { ECFieldElement x = generateSquareInput_CarryBug(); BigInteger X = x.toBigInteger(); BigInteger R = X.multiply(X).mod(Q); ECFieldElement z = x.square(); BigInteger Z = z.toBigInteger(); assertEquals(R, Z); } } /* * Based on another example input demonstrating the carry propagation bug in Nat192.square, as * reported by Joseph Friel on dev-crypto. */ public void testSquare_CarryBug_Reported() { ECFieldElement x = fe(new BigInteger("2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", 16)); BigInteger X = x.toBigInteger(); BigInteger R = X.multiply(X).mod(Q); ECFieldElement z = x.square(); BigInteger Z = z.toBigInteger(); assertEquals(R, Z); } private ECFieldElement fe(BigInteger x) { return DP.getCurve().fromBigInteger(x); } private ECFieldElement generateMultiplyInput_Random() { return fe(new BigInteger(DP.getCurve().getFieldSize() + 32, RANDOM).mod(Q)); } private ECFieldElement generateSquareInput_CarryBug() { int[] x = Nat.create(12); x[0] = RANDOM.nextInt() >>> 1; x[6] = 2; x[10] = -1 << 16; x[11] = -1; return fe(Nat.toBigInteger(12, x)); } }