From c6533202f79e3de0c98091bc24452c8cdf38ee5c Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 15 Sep 2013 15:12:07 +0000 Subject: [PATCH] Add RSAConstants Specify RSA parameters Add RSA sig types Specify cert signature algorithm when generating keys Extend keygen max wait Catch NPE if sign fails in SU3File Fix signature conversion for RSA Fix public key conversion for RSA --- .../java/src/net/i2p/crypto/KeyStoreUtil.java | 27 ++++++++- .../java/src/net/i2p/crypto/RSAConstants.java | 29 ++++++++++ core/java/src/net/i2p/crypto/SU3File.java | 2 + core/java/src/net/i2p/crypto/SigType.java | 5 ++ core/java/src/net/i2p/crypto/SigUtil.java | 55 +++++++++++++++---- 5 files changed, 106 insertions(+), 12 deletions(-) create mode 100644 core/java/src/net/i2p/crypto/RSAConstants.java diff --git a/core/java/src/net/i2p/crypto/KeyStoreUtil.java b/core/java/src/net/i2p/crypto/KeyStoreUtil.java index 19530cdce..95e0c41b2 100644 --- a/core/java/src/net/i2p/crypto/KeyStoreUtil.java +++ b/core/java/src/net/i2p/crypto/KeyStoreUtil.java @@ -315,10 +315,11 @@ public class KeyStoreUtil { "-dname", "CN=" + cname + ",OU=" + ou + ",O=I2P Anonymous Network,L=XX,ST=XX,C=XX", "-validity", Integer.toString(validDays), // 10 years "-keyalg", keyAlg, + "-sigalg", getSigAlg(keySize, keyAlg), "-keysize", Integer.toString(keySize), "-keypass", keyPW }; - boolean success = (new ShellCommand()).executeSilentAndWaitTimed(args, 30); // 30 secs + boolean success = (new ShellCommand()).executeSilentAndWaitTimed(args, 240); if (success) { success = ks.exists(); } @@ -335,6 +336,30 @@ public class KeyStoreUtil { return success; } + private static String getSigAlg(int size, String keyalg) { + if (keyalg.equals("EC")) + keyalg = "ECDSA"; + String hash; + if (keyalg.equals("ECDSA")) { + if (size <= 256) + hash = "SHA256"; + else if (size <= 384) + hash = "SHA384"; + else + hash = "SHA512"; + } else { + if (size <= 1024) + hash = "SHA1"; + else if (size <= 2048) + hash = "SHA256"; + else if (size <= 3072) + hash = "SHA384"; + else + hash = "SHA512"; + } + return hash + "with" + keyalg; + } + /** * Get a private key out of a keystore * diff --git a/core/java/src/net/i2p/crypto/RSAConstants.java b/core/java/src/net/i2p/crypto/RSAConstants.java new file mode 100644 index 000000000..3f77d09f1 --- /dev/null +++ b/core/java/src/net/i2p/crypto/RSAConstants.java @@ -0,0 +1,29 @@ +package net.i2p.crypto; + +import java.math.BigInteger; +import java.security.spec.RSAKeyGenParameterSpec; + +import net.i2p.util.NativeBigInteger; + +/** + * Constants for RSA + * + * @since 0.9.9 + */ +class RSAConstants { + + /** + * Generate a spec + */ + private static RSAKeyGenParameterSpec genSpec(int size, BigInteger exp) { + return new RSAKeyGenParameterSpec(size, exp); + } + + private static final BigInteger F4 = new NativeBigInteger(RSAKeyGenParameterSpec.F4); + + // standard specs + public static final RSAKeyGenParameterSpec F4_1024_SPEC = genSpec(1024, F4); + public static final RSAKeyGenParameterSpec F4_2048_SPEC = genSpec(2048, F4); + public static final RSAKeyGenParameterSpec F4_3072_SPEC = genSpec(3072, F4); + public static final RSAKeyGenParameterSpec F4_4096_SPEC = genSpec(4096, F4); +} diff --git a/core/java/src/net/i2p/crypto/SU3File.java b/core/java/src/net/i2p/crypto/SU3File.java index f5e25f1b0..630ca2a03 100644 --- a/core/java/src/net/i2p/crypto/SU3File.java +++ b/core/java/src/net/i2p/crypto/SU3File.java @@ -385,6 +385,8 @@ public class SU3File { SimpleDataStructure hash = sigType.getHashInstance(); hash.setData(sha); Signature signature = _context.dsa().sign(hash, privkey, sigType); + if (signature == null) + throw new IOException("sig fail"); //System.out.println("hash\n" + HexDump.dump(sha)); //System.out.println("sig\n" + HexDump.dump(signature.getData())); signature.writeBytes(out); diff --git a/core/java/src/net/i2p/crypto/SigType.java b/core/java/src/net/i2p/crypto/SigType.java index 94f726da0..82ba8c4bd 100644 --- a/core/java/src/net/i2p/crypto/SigType.java +++ b/core/java/src/net/i2p/crypto/SigType.java @@ -54,6 +54,11 @@ public enum SigType { ECDSA_SHA256_K409(15, 104, 52, 32, 104, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K409_SPEC), ECDSA_SHA256_K571(16, 144, 72, 32, 144, SigAlgo.EC, "SHA-256", "SHA256withECDSA", ECConstants.K571_SPEC), + 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_SHA512(20, 512, 1024, 64, 512, SigAlgo.RSA, "SHA-512", "SHA512withRSA", RSAConstants.F4_4096_SPEC), + //MD5 //ELGAMAL_SHA256 //RSA_SHA1 diff --git a/core/java/src/net/i2p/crypto/SigUtil.java b/core/java/src/net/i2p/crypto/SigUtil.java index 99525c7f9..58471376e 100644 --- a/core/java/src/net/i2p/crypto/SigUtil.java +++ b/core/java/src/net/i2p/crypto/SigUtil.java @@ -31,6 +31,7 @@ import java.security.spec.ECPoint; import java.security.spec.EllipticCurve; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import java.security.spec.X509EncodedKeySpec; @@ -169,8 +170,8 @@ class SigUtil { byte[] by = new byte[sublen]; System.arraycopy(b, 0, bx, 0, sublen); System.arraycopy(b, sublen, by, 0, sublen); - BigInteger x = new BigInteger(1, bx); - BigInteger y = new BigInteger(1, by); + BigInteger x = new NativeBigInteger(1, bx); + BigInteger y = new NativeBigInteger(1, by); ECPoint w = new ECPoint(x, y); // see ECConstants re: casting ECPublicKeySpec ks = new ECPublicKeySpec(w, (ECParameterSpec) type.getParams()); @@ -184,7 +185,7 @@ class SigUtil { int len = type.getPubkeyLen(); int sublen = len / 2; byte[] b = pk.getData(); - BigInteger s = new BigInteger(1, b); + BigInteger s = new NativeBigInteger(1, b); // see ECConstants re: casting ECPrivateKeySpec ks = new ECPrivateKeySpec(s, (ECParameterSpec) type.getParams()); KeyFactory kf = KeyFactory.getInstance("EC"); @@ -254,42 +255,71 @@ class SigUtil { return new SigningPrivateKey(type, bx); } + /** + * @deprecated unused + */ public static RSAPublicKey toJavaRSAKey(SigningPublicKey pk) throws GeneralSecurityException { + SigType type = pk.getType(); KeyFactory kf = KeyFactory.getInstance("RSA"); + BigInteger n = new NativeBigInteger(1, pk.getData()); + BigInteger e = ((RSAKeyGenParameterSpec)type.getParams()).getPublicExponent(); // modulus exponent - KeySpec ks = new RSAPublicKeySpec(null, null); // FIXME + KeySpec ks = new RSAPublicKeySpec(n, e); return (RSAPublicKey) kf.generatePublic(ks); } + /** + * @deprecated unimplemented, 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, ...); // modulus exponent - KeySpec ks = new RSAPrivateKeySpec(null, null); // FIXME + KeySpec ks = new RSAPrivateKeySpec(n, d); // 65537 0x10001 return (RSAPrivateKey) kf.generatePrivate(ks); + */ + throw new UnsupportedOperationException(); } + /** + * @deprecated unused + */ public static SigningPublicKey fromJavaKey(RSAPublicKey pk, SigType type) throws GeneralSecurityException { - BigInteger y = pk.getPublicExponent(); + BigInteger n = pk.getModulus(); int len = type.getPubkeyLen(); - byte[] by = rectify(y, len); - return new SigningPublicKey(type, by); + byte[] bn = rectify(n, len); + return new SigningPublicKey(type, bn); } + /** + * @deprecated unimplemented, unused + */ public static SigningPrivateKey fromJavaKey(RSAPrivateKey pk, SigType type) throws GeneralSecurityException { - BigInteger x = pk.getPrivateExponent(); - int len = type.getPrivkeyLen(); - byte[] bx = rectify(x, len); + /* + // 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(); } /** * @return ASN.1 representation */ public static byte[] toJavaSig(Signature sig) { + // RSA sigs are not ASN encoded + if (sig.getType().getBaseAlgorithm() == SigAlgo.RSA) + return sig.getData(); return sigBytesToASN1(sig.getData()); } @@ -299,6 +329,9 @@ class SigUtil { */ public static Signature fromJavaSig(byte[] asn, SigType type) throws SignatureException { + // RSA sigs are not ASN encoded + if (type.getBaseAlgorithm() == SigAlgo.RSA) + return new Signature(type, asn); return new Signature(type, aSN1ToSigBytes(asn, type.getSigLen())); }