diff options
author | bouncy <bouncy@deimos.tauceti.org.au> | 2014-01-05 10:46:22 +0400 |
---|---|---|
committer | bouncy <bouncy@deimos.tauceti.org.au> | 2014-01-05 10:46:22 +0400 |
commit | dd05b1353bef72fbd8823a6d85f7396aab968c39 (patch) | |
tree | 3d407934cc57b56b03387804cd948afe19053263 | |
parent | f98d829d3b5ecbe85d9a2113b8f7fac61b8eb77e (diff) | |
parent | 167f29d3c0ca707939759a94e0049b3a1ae12f33 (diff) |
Merge remote branch 'origin/master'
16 files changed, 385 insertions, 161 deletions
diff --git a/core/src/main/java/org/bouncycastle/asn1/sec/SECCustomNamedCurves.java b/core/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java index 6e85c012..96039c6c 100644 --- a/core/src/main/java/org/bouncycastle/asn1/sec/SECCustomNamedCurves.java +++ b/core/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java @@ -1,9 +1,10 @@ -package org.bouncycastle.asn1.sec; +package org.bouncycastle.crypto.ec; import java.util.Enumeration; import java.util.Hashtable; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ECParametersHolder; import org.bouncycastle.math.ec.ECCurve; @@ -13,7 +14,7 @@ import org.bouncycastle.math.ec.custom.sec.SecP256R1Curve; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; -public class SECCustomNamedCurves +public class CustomNamedCurves { private static ECCurve configureCurve(ECCurve curve) { diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java index e2a99d87..5adf06cf 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java @@ -8,11 +8,11 @@ import java.math.BigInteger; import java.security.SecureRandom; import java.util.Hashtable; -import org.bouncycastle.asn1.sec.SECCustomNamedCurves; import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; +import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECKeyGenerationParameters; @@ -153,7 +153,7 @@ public class TlsECCUtils // Parameters are lazily created the first time a particular curve is accessed - X9ECParameters ecP = SECCustomNamedCurves.getByName(curveName); + X9ECParameters ecP = CustomNamedCurves.getByName(curveName); if (ecP == null) { ecP = ECNamedCurveTable.getByName(curveName); diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java index 9cd51b6e..6b4ceae9 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java @@ -1562,9 +1562,27 @@ public abstract class ECPoint if (b.bitLength() < (curve.getFieldSize() >> 1)) { ECFieldElement t1 = L1.add(X1).square(); - ECFieldElement t2 = aZ1Sq.square(); - ECFieldElement t3 = curve.getB().multiply(Z1Sq.square()); - L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2.add(t3)).add(X3).add(a.addOne().multiply(Z3)); + ECFieldElement t4; + if (b.isOne()) + { + t4 = aZ1Sq.add(Z1Sq).square(); + } + else + { + // TODO t2/t3 can be calculated with one square if we pre-compute sqrt(b) + ECFieldElement t2 = aZ1Sq.square(); + ECFieldElement t3 = b.multiply(Z1Sq.square()); + t4 = t2.add(t3); + } + L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t4).add(X3); + if (a.isZero()) + { + L3 = L3.add(Z3); + } + else if (!a.isOne()) + { + L3 = L3.add(a.addOne().multiply(Z3)); + } } else { diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/Nat256.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/Nat256.java index 2ab81a70..18872410 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/Nat256.java +++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/Nat256.java @@ -38,18 +38,6 @@ public abstract class Nat256 return (int)c; } - public static int addExt(int[] xx, int[] yy, int[] zz) - { - long c = 0; - for (int i = 0; i < 16; ++i) - { - c += (xx[i] & M) + (yy[i] & M); - zz[i] = (int)c; - c >>>= 32; - } - return (int)c; - } - public static int addBothTo(int[] x, int[] y, int[] z) { long c = 0; @@ -93,7 +81,19 @@ public abstract class Nat256 return c == 0 ? 0 : inc(z, zOff + 2); } - public static int addExt(int[] x, int xOff, int[] zz, int zzOff) + public static int addExt(int[] xx, int[] yy, int[] zz) + { + long c = 0; + for (int i = 0; i < 16; ++i) + { + c += (xx[i] & M) + (yy[i] & M); + zz[i] = (int)c; + c >>>= 32; + } + return (int)c; + } + + public static int addToExt(int[] x, int xOff, int[] zz, int zzOff) { // assert zzOff <= 8; long c = 0; @@ -204,6 +204,20 @@ public abstract class Nat256 return false; } + public static boolean gteExt(int[] xx, int[] yy) + { + for (int i = 15; i >= 0; --i) + { + int xx_i = xx[i] ^ Integer.MIN_VALUE; + int yy_i = yy[i] ^ Integer.MIN_VALUE; + if (xx_i < yy_i) + return false; + if (xx_i > yy_i) + return true; + } + return false; + } + public static int inc(int[] z, int zOff) { // assert zOff < 8; @@ -262,6 +276,22 @@ public abstract class Nat256 return true; } + public static boolean isZeroExt(int[] xx) + { + if (xx[0] != 0) + { + return false; + } + for (int i = 1; i < 16; ++i) + { + if (xx[i] != 0) + { + return false; + } + } + return true; + } + public static void mul(int[] x, int[] y, int[] zz) { long y_0 = y[0] & M; @@ -444,181 +474,144 @@ public abstract class Nat256 return (int)c; } - public static int shiftUp(int[] x, int xLen, int bit) + public static int shiftUp(int[] x, int xLen, int c) { for (int i = 0; i < xLen; ++i) { int next = x[i]; - x[i] = (next << 1) | bit; - bit = next >>> 31; + x[i] = (next << 1) | (c >>> 31); + c = next; } - return bit; + return c >>> 31; } public static void square(int[] x, int[] zz) { + long x_0 = x[0] & M; + long zz_1; + { - int c = 0, i = 8, j = 16; + int c = 0, i = 7, j = 16; do { - long xVal = (x[--i] & M); + long xVal = (x[i--] & M); long p = xVal * xVal; zz[--j] = (c << 31) | (int)(p >>> 33); zz[--j] = (int)(p >>> 1); c = (int)p; } while (i > 0); + + { + long p = x_0 * x_0; + zz_1 = ((c << 31) & M) | (p >>> 33); + zz[0] = (int)(p >>> 1); + } } - long x_0 = x[0] & M; long x_1 = x[1] & M; - long zz_1 = zz[1] & M; long zz_2 = zz[2] & M; { - long cc = 0; - cc += x_1 * x_0 + zz_1; - zz[1] = (int)cc; - cc >>>= 32; - zz_2 += cc; + zz_1 += x_1 * x_0; + zz[1] = (int)zz_1; + zz_2 += zz_1 >>> 32; } long x_2 = x[2] & M; long zz_3 = zz[3] & M; long zz_4 = zz[4] & M; { - long cc = 0; - cc += x_2 * x_0 + zz_2; - zz[2] = (int)cc; - cc >>>= 32; - cc += x_2 * x_1 + zz_3; - zz_3 = cc & M; - cc >>>= 32; - zz_4 += cc; + zz_2 += x_2 * x_0; + zz[2] = (int)zz_2; + zz_3 += (zz_2 >>> 32) + x_2 * x_1; + zz_4 += zz_3 >>> 32; + zz_3 &= M; } long x_3 = x[3] & M; long zz_5 = zz[5] & M; long zz_6 = zz[6] & M; { - long cc = 0; - cc += x_3 * x_0 + zz_3; - zz[3] = (int)cc; - cc >>>= 32; - cc += x_3 * x_1 + zz_4; - zz_4 = cc & M; - cc >>>= 32; - cc += x_3 * x_2 + zz_5; - zz_5 = cc & M; - cc >>>= 32; - zz_6 += cc; + zz_3 += x_3 * x_0; + zz[3] = (int)zz_3; + zz_4 += (zz_3 >>> 32) + x_3 * x_1; + zz_5 += (zz_4 >>> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >>> 32; + zz_5 &= M; } long x_4 = x[4] & M; long zz_7 = zz[7] & M; long zz_8 = zz[8] & M; { - long cc = 0; - cc += x_4 * x_0 + zz_4; - zz[4] = (int)cc; - cc >>>= 32; - cc += x_4 * x_1 + zz_5; - zz_5 = cc & M; - cc >>>= 32; - cc += x_4 * x_2 + zz_6; - zz_6 = cc & M; - cc >>>= 32; - cc += x_4 * x_3 + zz_7; - zz_7 = cc & M; - cc >>>= 32; - zz_8 += cc; + zz_4 += x_4 * x_0; + zz[4] = (int)zz_4; + zz_5 += (zz_4 >>> 32) + x_4 * x_1; + zz_6 += (zz_5 >>> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >>> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >>> 32; + zz_7 &= M; } long x_5 = x[5] & M; long zz_9 = zz[9] & M; long zz_10 = zz[10] & M; { - long cc = 0; - cc += x_5 * x_0 + zz_5; - zz[5] = (int)cc; - cc >>>= 32; - cc += x_5 * x_1 + zz_6; - zz_6 = cc & M; - cc >>>= 32; - cc += x_5 * x_2 + zz_7; - zz_7 = cc & M; - cc >>>= 32; - cc += x_5 * x_3 + zz_8; - zz_8 = cc & M; - cc >>>= 32; - cc += x_5 * x_4 + zz_9; - zz_9 = cc & M; - cc >>>= 32; - zz_10 += cc; + zz_5 += x_5 * x_0; + zz[5] = (int)zz_5; + zz_6 += (zz_5 >>> 32) + x_5 * x_1; + zz_7 += (zz_6 >>> 32) + x_5 * x_2; + zz_6 &= M; + zz_8 += (zz_7 >>> 32) + x_5 * x_3; + zz_7 &= M; + zz_9 += (zz_8 >>> 32) + x_5 * x_4; + zz_8 &= M; + zz_10 += zz_9 >>> 32; + zz_9 &= M; } long x_6 = x[6] & M; long zz_11 = zz[11] & M; long zz_12 = zz[12] & M; { - long cc = 0; - cc += x_6 * x_0 + zz_6; - zz[6] = (int)cc; - cc >>>= 32; - cc += x_6 * x_1 + zz_7; - zz_7 = cc & M; - cc >>>= 32; - cc += x_6 * x_2 + zz_8; - zz_8 = cc & M; - cc >>>= 32; - cc += x_6 * x_3 + zz_9; - zz_9 = cc & M; - cc >>>= 32; - cc += x_6 * x_4 + zz_10; - zz_10 = cc & M; - cc >>>= 32; - cc += x_6 * x_5 + zz_11; - zz_11 = cc & M; - cc >>>= 32; - zz_12 += cc; + zz_6 += x_6 * x_0; + zz[6] = (int)zz_6; + zz_7 += (zz_6 >>> 32) + x_6 * x_1; + zz_8 += (zz_7 >>> 32) + x_6 * x_2; + zz_7 &= M; + zz_9 += (zz_8 >>> 32) + x_6 * x_3; + zz_8 &= M; + zz_10 += (zz_9 >>> 32) + x_6 * x_4; + zz_9 &= M; + zz_11 += (zz_10 >>> 32) + x_6 * x_5; + zz_10 &= M; + zz_12 += zz_11 >>> 32; + zz_11 &= M; } long x_7 = x[7] & M; long zz_13 = zz[13] & M; long zz_14 = zz[14] & M; { - long cc = 0; - cc += x_7 * x_0 + zz_7; - zz[7] = (int)cc; - cc >>>= 32; - cc += x_7 * x_1 + zz_8; - zz_8 = cc & M; - cc >>>= 32; - cc += x_7 * x_2 + zz_9; - zz_9 = cc & M; - cc >>>= 32; - cc += x_7 * x_3 + zz_10; - zz_10 = cc & M; - cc >>>= 32; - cc += x_7 * x_4 + zz_11; - zz_11 = cc & M; - cc >>>= 32; - cc += x_7 * x_5 + zz_12; - zz_12 = cc & M; - cc >>>= 32; - cc += x_7 * x_6 + zz_13; - zz_13 = cc & M; - cc >>>= 32; - zz_14 += cc; - } - - long zz_15 = zz[15] & M; - { - long cc = 0; - cc += zz_14; - zz[14] = (int)cc; - cc >>>= 32; - zz_15 += cc; + zz_7 += x_7 * x_0; + zz[7] = (int)zz_7; + zz_8 += (zz_7 >>> 32) + x_7 * x_1; + zz_9 += (zz_8 >>> 32) + x_7 * x_2; + zz_8 &= M; + zz_10 += (zz_9 >>> 32) + x_7 * x_3; + zz_9 &= M; + zz_11 += (zz_10 >>> 32) + x_7 * x_4; + zz_10 &= M; + zz_12 += (zz_11 >>> 32) + x_7 * x_5; + zz_11 &= M; + zz_13 += (zz_12 >>> 32) + x_7 * x_6; + zz_12 &= M; + zz_14 += zz_13 >>> 32; + zz_13 &= M; } zz[8] = (int)zz_8; @@ -628,9 +621,9 @@ public abstract class Nat256 zz[12] = (int)zz_12; zz[13] = (int)zz_13; zz[14] = (int)zz_14; - zz[15] = (int)zz_15; + zz[15] += (int)(zz_14 >>> 32); - shiftUp(zz, 16, (int)x_0 & 1); + shiftUp(zz, 16, (int)x_0 << 31); } public static int sub(int[] x, int[] y, int[] z) @@ -705,6 +698,49 @@ public abstract class Nat256 return x == 0 ? 0 : dec(z, 2); } + public static int subExt(int[] xx, int[] yy, int[] zz) + { + long c = 0; + for (int i = 0; i < 16; ++i) + { + c += (xx[i] & M) - (yy[i] & M); + zz[i] = (int)c; + c >>= 32; + } + return (int)c; + } + + public static int subFromExt(int[] x, int xOff, int[] zz, int zzOff) + { + // assert zzOff <= 8; + long c = 0; + c += (zz[zzOff + 0] & M) - (x[xOff + 0] & M); + zz[zzOff + 0] = (int)c; + c >>= 32; + c += (zz[zzOff + 1] & M) - (x[xOff + 1] & M); + zz[zzOff + 1] = (int)c; + c >>= 32; + c += (zz[zzOff + 2] & M) - (x[xOff + 2] & M); + zz[zzOff + 2] = (int)c; + c >>= 32; + c += (zz[zzOff + 3] & M) - (x[xOff + 3] & M); + zz[zzOff + 3] = (int)c; + c >>= 32; + c += (zz[zzOff + 4] & M) - (x[xOff + 4] & M); + zz[zzOff + 4] = (int)c; + c >>= 32; + c += (zz[zzOff + 5] & M) - (x[xOff + 5] & M); + zz[zzOff + 5] = (int)c; + c >>= 32; + c += (zz[zzOff + 6] & M) - (x[xOff + 6] & M); + zz[zzOff + 6] = (int)c; + c >>= 32; + c += (zz[zzOff + 7] & M) - (x[xOff + 7] & M); + zz[zzOff + 7] = (int)c; + c >>= 32; + return (int)c; + } + public static BigInteger toBigInteger(int[] x) { byte[] bs = new byte[32]; diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java index 840fe05d..4e032850 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java +++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java @@ -10,6 +10,10 @@ public class SecP256K1Field private static final int[] P = new int[]{ 0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; private static final int P7 = 0xFFFFFFFF; + private static final int[] PExt = new int[]{ 0x000E90A1, 0x000007A2, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFFFFF85E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF }; + private static final int PExt15 = 0xFFFFFFFF; private static final long PInv = 0x00000001000003D1L; public static void add(int[] x, int[] y, int[] z) @@ -21,6 +25,15 @@ public class SecP256K1Field } } + public static void addExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat256.addExt(xx, yy, zz); + if (c != 0 || (zz[15] == PExt15 && Nat256.gteExt(zz, PExt))) + { + Nat256.subExt(zz, PExt, zz); + } + } + public static void addOne(int[] x, int[] z) { System.arraycopy(x, 0, z, 0, 8); @@ -60,11 +73,11 @@ public class SecP256K1Field } } - private static void reduce(int[] tt, int[] z) + public static void reduce(int[] tt, int[] z) { long extra = -(tt[8] & M); extra += Nat256.mulWordAddExt((int)PInv, tt, 8, tt, 0) & M; - extra += (Nat256.addExt(tt, 8, tt, 1) & M) << 32; + extra += (Nat256.addToExt(tt, 8, tt, 1) & M) << 32; extra += (tt[8] & M); long c = Nat256.mulWordDwordAdd((int)PInv, extra, tt, 0) & M; @@ -95,4 +108,13 @@ public class SecP256K1Field Nat256.subDWord(PInv, z); } } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat256.subExt(xx, yy, zz); + if (c != 0) + { + Nat256.addExt(zz, PExt, zz); + } + } } diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java index 0b53240f..9881a007 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java +++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java @@ -10,6 +10,9 @@ public class SecP256R1Field private static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF }; private static final int P7 = 0xFFFFFFFF; + private static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0x00000001, 0xFFFFFFFE, + 0x00000002, 0xFFFFFFFE }; public static void add(int[] x, int[] y, int[] z) { @@ -20,6 +23,15 @@ public class SecP256R1Field } } + public static void addExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat256.addExt(xx, yy, zz); + if (c != 0 || Nat256.gteExt(zz, PExt)) + { + Nat256.subExt(zz, PExt, zz); + } + } + public static void addOne(int[] x, int[] z) { System.arraycopy(x, 0, z, 0, 8); @@ -59,7 +71,7 @@ public class SecP256R1Field } } - private static void reduce(int[] tt, int[] z) + public static void reduce(int[] tt, int[] z) { long t08 = tt[8] & M, t09 = tt[9] & M, t10 = tt[10] & M, t11 = tt[11] & M; long t12 = tt[12] & M, t13 = tt[13] & M, t14 = tt[14] & M, t15 = tt[15] & M; @@ -132,4 +144,13 @@ public class SecP256R1Field Nat256.add(z, P, z); } } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat256.subExt(xx, yy, zz); + if (c != 0) + { + Nat256.addExt(zz, PExt, zz); + } + } } diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java index d60b2e37..c97a7897 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java +++ b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java @@ -1,7 +1,5 @@ package org.bouncycastle.math.ec.custom.sec; -import java.math.BigInteger; - import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECFieldElement; import org.bouncycastle.math.ec.ECPoint; diff --git a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointPerformanceTest.java b/core/src/test/java/org/bouncycastle/math/ec/test/ECPointPerformanceTest.java index c919c6bf..c1420051 100644 --- a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointPerformanceTest.java +++ b/core/src/test/java/org/bouncycastle/math/ec/test/ECPointPerformanceTest.java @@ -4,9 +4,9 @@ import java.math.BigInteger; import java.security.SecureRandom; import junit.framework.TestCase; -import org.bouncycastle.asn1.sec.SECCustomNamedCurves; import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; @@ -30,7 +30,7 @@ public class ECPointPerformanceTest extends TestCase randMult(curveName, spec); } - spec = SECCustomNamedCurves.getByName(curveName); + spec = CustomNamedCurves.getByName(curveName); if (spec != null) { randMult(curveName + " (custom)", spec); diff --git a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java b/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java index 2002da41..e2be2deb 100644 --- a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java +++ b/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java @@ -7,9 +7,9 @@ import java.util.Enumeration; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -import org.bouncycastle.asn1.sec.SECCustomNamedCurves; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; @@ -446,7 +446,7 @@ public class ECPointTest extends TestCase X9ECParameters x9ECParameters = SECNamedCurves.getByName(name); implAddSubtractMultiplyTwiceEncodingTest(x9ECParameters); - x9ECParameters = SECCustomNamedCurves.getByName(name); + x9ECParameters = CustomNamedCurves.getByName(name); if (x9ECParameters != null) { implAddSubtractMultiplyTwiceEncodingTest(x9ECParameters); diff --git a/pg/src/main/java/org/bouncycastle/bcpg/ECPublicBCPGKey.java b/pg/src/main/java/org/bouncycastle/bcpg/ECPublicBCPGKey.java index 5983b325..9464af7c 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/ECPublicBCPGKey.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/ECPublicBCPGKey.java @@ -10,6 +10,8 @@ import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.math.ec.custom.sec.SecP256R1Curve; +import org.bouncycastle.util.BigIntegers; /** * base class for an EC Public Key. @@ -136,11 +138,12 @@ public abstract class ECPublicBCPGKey { throw new IOException(oid.getId() + " does not match any known curve."); } - if (!(curve.getCurve() instanceof ECCurve.Fp)) + // TODO: fix when custom curves have common interface + if (!((curve.getCurve() instanceof ECCurve.Fp) || (curve.getCurve() instanceof SecP256R1Curve))) { throw new IOException("Only FPCurves are supported."); } - return curve.getCurve().decodePoint(encodedPoint.toByteArray()); + return curve.getCurve().decodePoint(BigIntegers.asUnsignedByteArray(encodedPoint)); } } diff --git a/pkix/src/test/java/org/bouncycastle/eac/test/AllTests.java b/pkix/src/test/java/org/bouncycastle/eac/test/AllTests.java index a427e334..f8198556 100644 --- a/pkix/src/test/java/org/bouncycastle/eac/test/AllTests.java +++ b/pkix/src/test/java/org/bouncycastle/eac/test/AllTests.java @@ -119,7 +119,7 @@ public class AllTests if (!certHolder.isSignatureValid(verifier)) { - fail("first signature test failed"); + fail("second signature test failed"); } } @@ -157,7 +157,7 @@ public class AllTests if (!certHolder.isSignatureValid(verifier)) { - fail("first signature test failed"); + fail("second signature test failed"); } } @@ -192,7 +192,7 @@ public class AllTests public static Test suite() throws Exception { - TestSuite suite= new TestSuite("EAC tests"); + TestSuite suite = new TestSuite("EAC tests"); suite.addTestSuite(AllTests.class); diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java index 0eaae1db..5695e2ef 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java @@ -82,6 +82,8 @@ public class BCECPublicKey ECCurve curve = spec.getParams().getCurve(); EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed()); + // this may seem a little long-winded but it's how we pick up the custom curve. + this.q = EC5Util.convertCurve(ellipticCurve).createPoint(spec.getQ().getAffineXCoord().toBigInteger(), spec.getQ().getAffineYCoord().toBigInteger()); this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams()); } else @@ -132,7 +134,6 @@ public class BCECPublicKey ECDomainParameters dp = params.getParameters(); this.algorithm = algorithm; - this.q = params.getQ(); if (spec == null) { @@ -147,6 +148,8 @@ public class BCECPublicKey this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec); } + this.q = EC5Util.convertCurve(ecSpec.getCurve()).createPoint(params.getQ().getAffineXCoord().toBigInteger(), params.getQ().getAffineYCoord().toBigInteger()); + this.configuration = configuration; } diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java index 5eea1b92..e409b978 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java @@ -7,13 +7,27 @@ import java.security.spec.ECFieldFp; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.EllipticCurve; +import java.util.HashMap; +import java.util.Map; +import org.bouncycastle.asn1.sec.SECNamedCurves; +import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve; +import org.bouncycastle.math.ec.custom.sec.SecP256R1Curve; public class EC5Util { + private static Map customCurves = new HashMap(); + + static + { + customCurves.put(SECNamedCurves.getByName("secp256k1").getCurve(), CustomNamedCurves.getByName("secp256k1").getCurve()); + customCurves.put(SECNamedCurves.getByName("secp256r1").getCurve(), CustomNamedCurves.getByName("secp256r1").getCurve()); + } + public static EllipticCurve convertCurve( ECCurve curve, byte[] seed) @@ -24,6 +38,15 @@ public class EC5Util { return new EllipticCurve(new ECFieldFp(((ECCurve.Fp)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null); } + // TODO: really need an interface for these!! + else if (curve instanceof SecP256R1Curve) + { + return new EllipticCurve(new ECFieldFp(((SecP256R1Curve)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null); + } + else if (curve instanceof SecP256K1Curve) + { + return new EllipticCurve(new ECFieldFp(((SecP256K1Curve)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null); + } else { ECCurve.F2m curveF2m = (ECCurve.F2m)curve; @@ -53,7 +76,14 @@ public class EC5Util if (field instanceof ECFieldFp) { - return new ECCurve.Fp(((ECFieldFp)field).getP(), a, b); + ECCurve.Fp curve = new ECCurve.Fp(((ECFieldFp)field).getP(), a, b); + + if (customCurves.containsKey(curve)) + { + return (ECCurve)customCurves.get(curve); + } + + return curve; } else { diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java index fea5d9bf..4283273d 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java @@ -8,12 +8,12 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; import org.bouncycastle.asn1.nist.NISTNamedCurves; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.asn1.sec.SECCustomNamedCurves; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X962NamedCurves; import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; @@ -242,15 +242,15 @@ public class ECUtil public static X9ECParameters getNamedCurveByOid( ASN1ObjectIdentifier oid) { - X9ECParameters params = X962NamedCurves.getByOID(oid); - + X9ECParameters params = CustomNamedCurves.getByOID(oid); + if (params == null) { - params = SECCustomNamedCurves.getByOID(oid); + params = X962NamedCurves.getByOID(oid); if (params == null) { params = SECNamedCurves.getByOID(oid); - } else { System.out.println("using custom curve"); } + } if (params == null) { params = NISTNamedCurves.getByOID(oid); diff --git a/prov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java b/prov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java index 941f4763..5ad207ac 100644 --- a/prov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java +++ b/prov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java @@ -21,19 +21,35 @@ public class ECNamedCurveTable public static ECNamedCurveParameterSpec getParameterSpec( String name) { - X9ECParameters ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByName(name); + X9ECParameters ecP = org.bouncycastle.crypto.ec.CustomNamedCurves.getByName(name); if (ecP == null) { try { - ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(name)); + ecP = org.bouncycastle.crypto.ec.CustomNamedCurves.getByOID(new ASN1ObjectIdentifier(name)); } catch (IllegalArgumentException e) { // ignore - not an oid } + + if (ecP == null) + { + ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByName(name); + if (ecP == null) + { + try + { + ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(name)); + } + catch (IllegalArgumentException e) + { + // ignore - not an oid + } + } + } } - + if (ecP == null) { return null; diff --git a/prov/src/test/java/org/bouncycastle/jce/provider/test/ECDSA5Test.java b/prov/src/test/java/org/bouncycastle/jce/provider/test/ECDSA5Test.java index 802134c1..24354c80 100644 --- a/prov/src/test/java/org/bouncycastle/jce/provider/test/ECDSA5Test.java +++ b/prov/src/test/java/org/bouncycastle/jce/provider/test/ECDSA5Test.java @@ -27,6 +27,8 @@ import java.security.spec.ECPoint; import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPublicKeySpec; import java.security.spec.EllipticCurve; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; @@ -38,11 +40,14 @@ import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X962Parameters; +import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; import org.bouncycastle.jce.ECKeyUtil; import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.ECPointUtil; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.util.BigIntegers; import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.test.FixedSecureRandom; @@ -734,6 +739,76 @@ public class ECDSA5Test } } + private void testNamedCurveSigning() + throws Exception + { + testCustomNamedCurveSigning("secp256r1"); + testCustomNamedCurveSigning("secp256k1"); + } + + private void testCustomNamedCurveSigning(String name) + throws Exception + { + X9ECParameters x9Params = ECUtil.getNamedCurveByOid(ECUtil.getNamedCurveOid(name)); + + // TODO: one day this may have to change + if (x9Params.getCurve() instanceof ECCurve.Fp) + { + fail("curve not custom curve!!"); + } + + AlgorithmParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(name); + KeyPairGenerator keygen = KeyPairGenerator.getInstance("EC", "BC"); + keygen.initialize(ecSpec, new ECRandom()); + + KeyPair keys = keygen.generateKeyPair(); + + PrivateKeyInfo priv1 = PrivateKeyInfo.getInstance(keys.getPrivate().getEncoded()); + SubjectPublicKeyInfo pub1 = SubjectPublicKeyInfo.getInstance(keys.getPublic().getEncoded()); + + keygen = KeyPairGenerator.getInstance("EC", "BC"); + keygen.initialize(new ECGenParameterSpec("secp256r1"), new ECRandom()); + + Signature ecdsaSigner = Signature.getInstance("ECDSA", "BC"); + + ecdsaSigner.initSign(keys.getPrivate()); + + ecdsaSigner.update(new byte[100]); + + byte[] sig = ecdsaSigner.sign(); + + ecdsaSigner.initVerify(keys.getPublic()); + + ecdsaSigner.update(new byte[100]); + + if (!ecdsaSigner.verify(sig)) + { + fail("signature failed to verify"); + } + + KeyFactory kFact = KeyFactory.getInstance("EC", "BC"); + + PublicKey pub = kFact.generatePublic(new X509EncodedKeySpec(pub1.getEncoded())); + PrivateKey pri = kFact.generatePrivate(new PKCS8EncodedKeySpec(priv1.getEncoded())); + + ecdsaSigner = Signature.getInstance("ECDSA", "BC"); + + ecdsaSigner.initSign(pri); + + ecdsaSigner.update(new byte[100]); + + sig = ecdsaSigner.sign(); + + ecdsaSigner.initVerify(pub); + + ecdsaSigner.update(new byte[100]); + + if (!ecdsaSigner.verify(sig)) + { + fail("signature failed to verify"); + } + } + protected BigInteger[] derDecode( byte[] encoding) throws IOException @@ -766,6 +841,7 @@ public class ECDSA5Test testGeneration(); testKeyPairGenerationWithOIDs(); testNamedCurveParameterPreservation(); + testNamedCurveSigning(); } public static void main( |