From 403044fc6c97c13e88a6b6f2f2ef1770a4a59ed1 Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 24 Jan 2016 13:28:03 +0000 Subject: [PATCH] DSAEngine: minor cleanup ElG KeyFactory: Use getParameters() instead of getParams() to get the correct class back SigUtil: Use split() in sigBytesToASN1(); new public ASN1 methods Javadoc, args checking --- core/java/src/net/i2p/crypto/DSAEngine.java | 5 +- core/java/src/net/i2p/crypto/SigUtil.java | 67 ++++++++++++++++--- .../net/i2p/crypto/elgamal/KeyFactory.java | 20 ++---- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/core/java/src/net/i2p/crypto/DSAEngine.java b/core/java/src/net/i2p/crypto/DSAEngine.java index 76f2004f8b..803ed6a644 100644 --- a/core/java/src/net/i2p/crypto/DSAEngine.java +++ b/core/java/src/net/i2p/crypto/DSAEngine.java @@ -234,7 +234,7 @@ public class DSAEngine { BigInteger s = new NativeBigInteger(1, sbytes); BigInteger r = new NativeBigInteger(1, rbytes); BigInteger y = new NativeBigInteger(1, verifyingKey.getData()); - BigInteger w = null; + BigInteger w; try { w = s.modInverse(CryptoConstants.dsaq); } catch (ArithmeticException ae) { @@ -402,8 +402,7 @@ public class DSAEngine { long start = _context.clock().now(); BigInteger k; - - boolean ok = false; + boolean ok; do { k = new BigInteger(160, _context.random()); ok = k.compareTo(CryptoConstants.dsaq) != 1; diff --git a/core/java/src/net/i2p/crypto/SigUtil.java b/core/java/src/net/i2p/crypto/SigUtil.java index d04abb438d..715c584721 100644 --- a/core/java/src/net/i2p/crypto/SigUtil.java +++ b/core/java/src/net/i2p/crypto/SigUtil.java @@ -549,9 +549,13 @@ public class SigUtil { /** * Split a byte array into two BigIntegers + * @param b length must be even * @return array of two BigIntegers + * @since 0.9.9 */ - private static BigInteger[] split(byte[] b) { + private static NativeBigInteger[] split(byte[] b) { + if ((b.length & 0x01) != 0) + throw new IllegalArgumentException("length must be even"); int sublen = b.length / 2; byte[] bx = new byte[sublen]; byte[] by = new byte[sublen]; @@ -565,9 +569,12 @@ public class SigUtil { /** * Combine two BigIntegers of nominal length = len / 2 * @return array of exactly len bytes + * @since 0.9.9 */ private static byte[] combine(BigInteger x, BigInteger y, int len) throws InvalidKeyException { + if ((len & 0x01) != 0) + throw new InvalidKeyException("length must be even"); int sublen = len / 2; byte[] b = new byte[len]; byte[] bx = rectify(x, sublen); @@ -609,7 +616,8 @@ public class SigUtil { /** * http://download.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html - * Signature Format ASN.1 sequence of two INTEGER values: r and s, in that order: + *
+     *  Signature Format: ASN.1 sequence of two INTEGER values: r and s, in that order:
      *                                SEQUENCE ::= { r INTEGER, s INTEGER }
      *
      *  http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
@@ -619,6 +627,7 @@ public class SigUtil {
      *  02 -- tag indicating INTEGER
      *  xx - length in octets
      *  xxxxxx - value
+     *
* * Convert to BigInteger and back so we have the minimum length representation, as required. * r and s are always non-negative. @@ -626,22 +635,43 @@ public class SigUtil { * Only supports sigs up to about 252 bytes. See code to fix BER encoding for this before you * add a SigType with bigger signatures. * + * @param sig length must be even * @throws IllegalArgumentException if too big * @since 0.8.7, moved to SigUtil in 0.9.9 */ private static byte[] sigBytesToASN1(byte[] sig) { - //System.out.println("pre TO asn1\n" + net.i2p.util.HexDump.dump(sig)); - int len = sig.length; - int sublen = len / 2; - byte[] tmp = new byte[sublen]; + BigInteger[] rs = split(sig); + return sigBytesToASN1(rs[0], rs[1]); + } - System.arraycopy(sig, 0, tmp, 0, sublen); - BigInteger r = new BigInteger(1, tmp); + /** + * http://download.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html + *
+     *  Signature Format: ASN.1 sequence of two INTEGER values: r and s, in that order:
+     *                                SEQUENCE ::= { r INTEGER, s INTEGER }
+     *
+     *  http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
+     *  30 -- tag indicating SEQUENCE
+     *  xx - length in octets
+     *
+     *  02 -- tag indicating INTEGER
+     *  xx - length in octets
+     *  xxxxxx - value
+     *
+ * + * r and s are always non-negative. + * + * Only supports sigs up to about 252 bytes. See code to fix BER encoding for this before you + * add a SigType with bigger signatures. + * + * @param sig length must be even + * @throws IllegalArgumentException if too big + * @since 0.9.25, split out from sigBytesToASN1(byte[]) + */ + public static byte[] sigBytesToASN1(BigInteger r, BigInteger s) { byte[] rb = r.toByteArray(); if (rb.length > 127) throw new IllegalArgumentException("FIXME R length > 127"); - System.arraycopy(sig, sublen, tmp, 0, sublen); - BigInteger s = new BigInteger(1, tmp); byte[] sb = s.toByteArray(); if (sb.length > 127) throw new IllegalArgumentException("FIXME S length > 127"); @@ -676,7 +706,8 @@ public class SigUtil { * See above. * Only supports sigs up to about 252 bytes. See code to fix BER encoding for bigger than that. * - * @return len bytes + * @param len must be even, twice the nominal length of each BigInteger + * @return len bytes, call split() on the result to get two BigIntegers * @since 0.8.7, moved to SigUtil in 0.9.9 */ private static byte[] aSN1ToSigBytes(byte[] asn, int len) @@ -722,6 +753,20 @@ public class SigUtil { return rv; } + /** + * See above. + * Only supports sigs up to about 252 bytes. See code to fix BER encoding for bigger than that. + * + * @param len nominal length of each BigInteger + * @return two BigIntegers + * @since 0.9.25 + */ + public static NativeBigInteger[] aSN1ToBigInteger(byte[] asn, int len) + throws SignatureException { + byte[] sig = aSN1ToSigBytes(asn, len * 2); + return split(sig); + } + public static void clearCaches() { synchronized(_ECPubkeyCache) { _ECPubkeyCache.clear(); diff --git a/core/java/src/net/i2p/crypto/elgamal/KeyFactory.java b/core/java/src/net/i2p/crypto/elgamal/KeyFactory.java index 3779b6f617..088c1ed402 100644 --- a/core/java/src/net/i2p/crypto/elgamal/KeyFactory.java +++ b/core/java/src/net/i2p/crypto/elgamal/KeyFactory.java @@ -60,23 +60,15 @@ public class KeyFactory extends KeyFactorySpi { throws InvalidKeySpecException { if (keySpec.isAssignableFrom(ElGamalPublicKeySpec.class) && key instanceof ElGamalPublicKey) { ElGamalPublicKey k = (ElGamalPublicKey) key; - // key.getParams() is a DHParameterSpec - DHParameterSpec dhp = k.getParams(); - if (dhp != null) { - if (dhp.getP().equals(I2P_ELGAMAL_2048_SPEC.getP()) && - dhp.getG().equals(I2P_ELGAMAL_2048_SPEC.getG())) - return (T) new ElGamalPrivateKeySpec(k.getY(), I2P_ELGAMAL_2048_SPEC); - return (T) new ElGamalPrivateKeySpec(k.getY(), new ElGamalParameterSpec(dhp.getP(), dhp.getG())); + ElGamalParameterSpec egp = k.getParameters(); + if (egp != null) { + return (T) new ElGamalPrivateKeySpec(k.getY(), egp); } } else if (keySpec.isAssignableFrom(ElGamalPrivateKeySpec.class) && key instanceof ElGamalPrivateKey) { ElGamalPrivateKey k = (ElGamalPrivateKey) key; - // key.getParams() is a DHParameterSpec - DHParameterSpec dhp = k.getParams(); - if (dhp != null) { - if (dhp.getP().equals(I2P_ELGAMAL_2048_SPEC.getP()) && - dhp.getG().equals(I2P_ELGAMAL_2048_SPEC.getG())) - return (T) new ElGamalPrivateKeySpec(k.getX(), I2P_ELGAMAL_2048_SPEC); - return (T) new ElGamalPrivateKeySpec(k.getX(), new ElGamalParameterSpec(dhp.getP(), dhp.getG())); + ElGamalParameterSpec egp = k.getParameters(); + if (egp != null) { + return (T) new ElGamalPrivateKeySpec(k.getX(), egp); } } throw new InvalidKeySpecException("not implemented yet " + key + " " + keySpec);