diff --git a/core/java/src/net/i2p/crypto/DSAEngine.java b/core/java/src/net/i2p/crypto/DSAEngine.java index 51256db38d..41717ffb30 100644 --- a/core/java/src/net/i2p/crypto/DSAEngine.java +++ b/core/java/src/net/i2p/crypto/DSAEngine.java @@ -491,7 +491,7 @@ public class DSAEngine { } /** - * Generic verify DSA_SHA1 or ECDSA + * Generic verify DSA_SHA1, ECDSA, or RSA * @throws GeneralSecurityException if algorithm unvailable or on other errors * @since 0.9.9 */ @@ -504,7 +504,7 @@ public class DSAEngine { return altVerifySigSHA1(signature, data, verifyingKey); java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName()); - PublicKey pubKey = SigUtil.toJavaECKey(verifyingKey); + PublicKey pubKey = SigUtil.toJavaKey(verifyingKey); jsig.initVerify(pubKey); jsig.update(data); boolean rv = jsig.verify(SigUtil.toJavaSig(signature)); @@ -569,7 +569,7 @@ public class DSAEngine { } /** - * Generic sign DSA_SHA1 or ECDSA + * Generic sign DSA_SHA1, ECDSA, or RSA * @throws GeneralSecurityException if algorithm unvailable or on other errors * @since 0.9.9 */ @@ -579,7 +579,7 @@ public class DSAEngine { return altSignSHA1(data, privateKey); java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName()); - PrivateKey privKey = SigUtil.toJavaECKey(privateKey); + PrivateKey privKey = SigUtil.toJavaKey(privateKey); jsig.initSign(privKey, _context.random()); jsig.update(data); return SigUtil.fromJavaSig(jsig.sign(), type); diff --git a/core/java/src/net/i2p/crypto/KeyGenerator.java b/core/java/src/net/i2p/crypto/KeyGenerator.java index 15dec5e72a..bdf8c56881 100644 --- a/core/java/src/net/i2p/crypto/KeyGenerator.java +++ b/core/java/src/net/i2p/crypto/KeyGenerator.java @@ -219,7 +219,7 @@ public class KeyGenerator { public SimpleDataStructure[] generateSigningKeys(SigType type) throws GeneralSecurityException { if (type == SigType.DSA_SHA1) return generateSigningKeys(); - KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); + KeyPairGenerator kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName()); KeyPair kp; try { kpg.initialize(type.getParams(), _context.random()); @@ -238,9 +238,9 @@ public class KeyGenerator { if (!ECConstants.isBCAvailable()) throw new GeneralSecurityException(pname + " KPG failed for " + type, pe); if (log.shouldLog(Log.WARN)) - log.warn(pname + " KPG failed for " + type + ", trying BC", pe); + log.warn(pname + " KPG failed for " + type + ", trying BC" /* , pe */ ); try { - kpg = KeyPairGenerator.getInstance("EC", "BC"); + kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName(), "BC"); kpg.initialize(type.getParams(), _context.random()); kp = kpg.generateKeyPair(); } catch (ProviderException pe2) { @@ -255,8 +255,8 @@ public class KeyGenerator { throw new GeneralSecurityException(pname + " KPG for " + type, pe); } } - ECPublicKey pubkey = (ECPublicKey) kp.getPublic(); - ECPrivateKey privkey = (ECPrivateKey) kp.getPrivate(); + java.security.PublicKey pubkey = kp.getPublic(); + java.security.PrivateKey privkey = kp.getPrivate(); SimpleDataStructure[] keys = new SimpleDataStructure[2]; keys[0] = SigUtil.fromJavaKey(pubkey, type); keys[1] = SigUtil.fromJavaKey(privkey, type); @@ -292,7 +292,7 @@ public class KeyGenerator { public static void main2(String args[]) { RandomSource.getInstance().nextBoolean(); try { Thread.sleep(1000); } catch (InterruptedException ie) {} - int runs = 500; // warmup + int runs = 200; // warmup for (int j = 0; j < 2; j++) { for (int i = 0; i <= 100; i++) { SigType type = SigType.getByCode(i); @@ -306,7 +306,7 @@ public class KeyGenerator { e.printStackTrace(); } } - runs = 2000; + runs = 1000; } } @@ -331,9 +331,10 @@ public class KeyGenerator { } stime /= 1000*1000; vtime /= 1000*1000; - System.out.println("Sign/verify " + runs + " times: " + (vtime+stime) + " ms = " + + System.out.println(type + " sign/verify " + runs + " times: " + (vtime+stime) + " ms = " + (((double) stime) / runs) + " each sign, " + - (((double) vtime) / runs) + " each verify"); + (((double) vtime) / runs) + " each verify, " + + (((double) (stime + vtime)) / runs) + " s+v"); } /****** diff --git a/core/java/src/net/i2p/crypto/SigType.java b/core/java/src/net/i2p/crypto/SigType.java index 82ba8c4bd7..687820c376 100644 --- a/core/java/src/net/i2p/crypto/SigType.java +++ b/core/java/src/net/i2p/crypto/SigType.java @@ -56,7 +56,7 @@ public enum SigType { RSA_SHA1(17, 128, 256, 20, 128, SigAlgo.RSA, "SHA-1", "SHA1withRSA", RSAConstants.F4_1024_SPEC), RSA_SHA256(18, 256, 512, 32, 256, SigAlgo.RSA, "SHA-256", "SHA256withRSA", RSAConstants.F4_2048_SPEC), - RSA_SHA384(19, 384, 768, 48, 384, SigAlgo.RSA, "SHA-384", "SHA2384ithRSA", RSAConstants.F4_3072_SPEC), + RSA_SHA384(19, 384, 768, 48, 384, SigAlgo.RSA, "SHA-384", "SHA384withRSA", RSAConstants.F4_3072_SPEC), RSA_SHA512(20, 512, 1024, 64, 512, SigAlgo.RSA, "SHA-512", "SHA512withRSA", RSAConstants.F4_4096_SPEC), //MD5 diff --git a/core/java/src/net/i2p/crypto/SigUtil.java b/core/java/src/net/i2p/crypto/SigUtil.java index 58471376e6..5e5e032707 100644 --- a/core/java/src/net/i2p/crypto/SigUtil.java +++ b/core/java/src/net/i2p/crypto/SigUtil.java @@ -163,16 +163,8 @@ class SigUtil { private static ECPublicKey cvtToJavaECKey(SigningPublicKey pk) throws GeneralSecurityException { SigType type = pk.getType(); - int len = type.getPubkeyLen(); - int sublen = len / 2; - byte[] b = pk.getData(); - byte[] bx = new byte[sublen]; - byte[] by = new byte[sublen]; - System.arraycopy(b, 0, bx, 0, sublen); - System.arraycopy(b, sublen, by, 0, sublen); - BigInteger x = new NativeBigInteger(1, bx); - BigInteger y = new NativeBigInteger(1, by); - ECPoint w = new ECPoint(x, y); + BigInteger[] xy = split(pk.getData()); + ECPoint w = new ECPoint(xy[0], xy[1]); // see ECConstants re: casting ECPublicKeySpec ks = new ECPublicKeySpec(w, (ECParameterSpec) type.getParams()); KeyFactory kf = KeyFactory.getInstance("EC"); @@ -198,12 +190,7 @@ class SigUtil { BigInteger x = w.getAffineX(); BigInteger y = w.getAffineY(); int len = type.getPubkeyLen(); - int sublen = len / 2; - byte[] b = new byte[len]; - byte[] bx = rectify(x, sublen); - byte[] by = rectify(y, sublen); - System.arraycopy(bx, 0, b, 0, sublen); - System.arraycopy(by, 0, b, sublen, sublen); + byte[] b = combine(x, y, len); return new SigningPublicKey(type, b); } @@ -270,21 +257,16 @@ class SigUtil { } /** - * @deprecated unimplemented, unused + * @deprecated unused */ public static RSAPrivateKey toJavaRSAKey(SigningPrivateKey pk) throws GeneralSecurityException { - /* KeyFactory kf = KeyFactory.getInstance("RSA"); // private key is modulus (pubkey) + exponent - // get each part like in EC - BigInteger n = new NativeBigInteger(1, ...); - BigInteger d = new NativeBigInteger(1, ...); + BigInteger[] nd = split(pk.getData()); // modulus exponent - KeySpec ks = new RSAPrivateKeySpec(n, d); // 65537 0x10001 + KeySpec ks = new RSAPrivateKeySpec(nd[0], nd[1]); return (RSAPrivateKey) kf.generatePrivate(ks); - */ - throw new UnsupportedOperationException(); } /** @@ -299,18 +281,15 @@ class SigUtil { } /** - * @deprecated unimplemented, unused + * @deprecated unused */ public static SigningPrivateKey fromJavaKey(RSAPrivateKey pk, SigType type) throws GeneralSecurityException { - /* // private key is modulus (pubkey) + exponent BigInteger n = pk.getModulus(); BigInteger d = pk.getPrivateExponent(); - // put them together like in EC - return new SigningPrivateKey(type, bx); - */ - throw new UnsupportedOperationException(); + byte[] b = combine(n, d, type.getPrivkeyLen()); + return new SigningPrivateKey(type, b); } /** @@ -381,6 +360,36 @@ class SigUtil { } } + /** + * Split a byte array into two BigIntegers + * @return array of two BigIntegers + */ + private static BigInteger[] split(byte[] b) { + int sublen = b.length / 2; + byte[] bx = new byte[sublen]; + byte[] by = new byte[sublen]; + System.arraycopy(b, 0, bx, 0, sublen); + System.arraycopy(b, sublen, by, 0, sublen); + NativeBigInteger x = new NativeBigInteger(1, bx); + NativeBigInteger y = new NativeBigInteger(1, by); + return new NativeBigInteger[] {x, y}; + } + + /** + * Combine two BigIntegers of nominal length = len / 2 + * @return array of exactly len bytes + */ + private static byte[] combine(BigInteger x, BigInteger y, int len) + throws InvalidKeyException { + int sublen = len / 2; + byte[] b = new byte[len]; + byte[] bx = rectify(x, sublen); + byte[] by = rectify(y, sublen); + System.arraycopy(bx, 0, b, 0, sublen); + System.arraycopy(by, 0, b, sublen, sublen); + return b; + } + /** * @param bi non-negative * @return array of exactly len bytes