diff --git a/core/java/src/net/i2p/crypto/SigType.java b/core/java/src/net/i2p/crypto/SigType.java index 245711153..fbd2d7f46 100644 --- a/core/java/src/net/i2p/crypto/SigType.java +++ b/core/java/src/net/i2p/crypto/SigType.java @@ -2,6 +2,8 @@ package net.i2p.crypto; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; import java.util.HashMap; import java.util.Map; @@ -9,6 +11,10 @@ import java.util.Map; * Defines the properties for various signature types * that I2P supports or may someday support. * + * All Signatures, SigningPublicKeys, and SigningPrivateKeys have a type. + * Note that a SigType specifies both an algorithm and parameters, so that + * we may change primes or curves for a given algorithm. + * * @since 0.9.8 */ public enum SigType { @@ -17,15 +23,15 @@ public enum SigType { * Pubkey 128 bytes; privkey 20 bytes; hash 20 bytes; sig 40 bytes * @since 0.9.8 */ - DSA_SHA1(0, 128, 20, 20, 40, "SHA-1", "SHA1withDSA"), - /** Pubkey 40 bytes; privkey 20 bytes; hash 20 bytes; sig 40 bytes */ - ECDSA_SHA1(1, 40, 20, 20, 40, "SHA-1", "SHA1withECDSA"), + DSA_SHA1(0, 128, 20, 20, 40, "SHA-1", "SHA1withDSA", null), + /** Pubkey 48 bytes; privkey 24 bytes; hash 20 bytes; sig 48 bytes */ + ECDSA_SHA1_P192(1, 48, 24, 20, 48, "SHA-1", "SHA1withECDSA", null), /** Pubkey 64 bytes; privkey 32 bytes; hash 32 bytes; sig 64 bytes */ - ECDSA_SHA256(2, 64, 32, 32, 64, "SHA-256", "SHA256withECDSA"), + ECDSA_SHA256_P256(2, 64, 32, 32, 64, "SHA-256", "SHA256withECDSA", null), /** Pubkey 96 bytes; privkey 48 bytes; hash 48 bytes; sig 96 bytes */ - ECDSA_SHA384(3, 96, 48, 48, 96, "SHA-384", "SHA384withECDSA"), - /** Pubkey 128 bytes; privkey 64 bytes; hash 64 bytes; sig 128 bytes */ - ECDSA_SHA512(4, 128, 64, 64, 128, "SHA-512", "SHA512withECDSA") + ECDSA_SHA384_P384(3, 96, 48, 48, 96, "SHA-384", "SHA384withECDSA", null), + /** Pubkey 132 bytes; privkey 66 bytes; hash 64 bytes; sig 132 bytes */ + ECDSA_SHA512_P521(4, 132, 66, 64, 132, "SHA-512", "SHA512withECDSA", null), //MD5 //ELGAMAL_SHA256 @@ -45,8 +51,10 @@ public enum SigType { private final int code, pubkeyLen, privkeyLen, hashLen, sigLen; private final String digestName, algoName; + private final AlgorithmParameterSpec params; - SigType(int cod, int pubLen, int privLen, int hLen, int sLen, String mdName, String aName) { + SigType(int cod, int pubLen, int privLen, int hLen, int sLen, + String mdName, String aName, AlgorithmParameterSpec pSpec) { code = cod; pubkeyLen = pubLen; privkeyLen = privLen; @@ -54,14 +62,30 @@ public enum SigType { sigLen = sLen; digestName = mdName; algoName = aName; + params = pSpec; } + /** the unique identifier for this type */ public int getCode() { return code; } + /** the length of the public key, in bytes */ public int getPubkeyLen() { return pubkeyLen; } + /** the length of the private key, in bytes */ public int getPrivkeyLen() { return privkeyLen; } + /** the length of the hash, in bytes */ public int getHashLen() { return hashLen; } + /** the length of the signature, in bytes */ public int getSigLen() { return sigLen; } + /** the standard name used for the Java crypto factories */ public String getAlgorithmName() { return algoName; } + /** + * The elliptic curve ECParameterSpec for ECDSA; DSAParameterSpec for DSA + * @throws InvalidParameterSpecException if the algorithm is not available on this JVM. + */ + public AlgorithmParameterSpec getParams() throws InvalidParameterSpecException { + if (params == null) + throw new InvalidParameterSpecException(toString() + " is not available in this JVM"); + return params; + } /** @throws UnsupportedOperationException if not supported */ public MessageDigest getDigestInstance() { diff --git a/core/java/src/net/i2p/data/Signature.java b/core/java/src/net/i2p/data/Signature.java index 412706302..55b60c7a9 100644 --- a/core/java/src/net/i2p/data/Signature.java +++ b/core/java/src/net/i2p/data/Signature.java @@ -65,4 +65,23 @@ public class Signature extends SimpleDataStructure { public SigType getType() { return _type; } + + /** + * @since 0.9.8 + */ + @Override + public String toString() { + StringBuilder buf = new StringBuilder(64); + buf.append('[').append(getClass().getSimpleName()).append(' ').append(_type).append(": "); + int length = length(); + if (_data == null) { + buf.append("null"); + } else if (length <= 32) { + buf.append(toBase64()); + } else { + buf.append("size: ").append(Integer.toString(length)); + } + buf.append(']'); + return buf.toString(); + } } diff --git a/core/java/src/net/i2p/data/SigningPrivateKey.java b/core/java/src/net/i2p/data/SigningPrivateKey.java index 818509b07..4b60ee7e8 100644 --- a/core/java/src/net/i2p/data/SigningPrivateKey.java +++ b/core/java/src/net/i2p/data/SigningPrivateKey.java @@ -78,4 +78,23 @@ public class SigningPrivateKey extends SimpleDataStructure { public SigningPublicKey toPublic() { return KeyGenerator.getSigningPublicKey(this); } + + /** + * @since 0.9.8 + */ + @Override + public String toString() { + StringBuilder buf = new StringBuilder(64); + buf.append('[').append(getClass().getSimpleName()).append(' ').append(_type).append(": "); + int length = length(); + if (_data == null) { + buf.append("null"); + } else if (length <= 32) { + buf.append(toBase64()); + } else { + buf.append("size: ").append(Integer.toString(length)); + } + buf.append(']'); + return buf.toString(); + } } diff --git a/core/java/src/net/i2p/data/SigningPublicKey.java b/core/java/src/net/i2p/data/SigningPublicKey.java index c1c9445d9..a5119e795 100644 --- a/core/java/src/net/i2p/data/SigningPublicKey.java +++ b/core/java/src/net/i2p/data/SigningPublicKey.java @@ -92,4 +92,20 @@ public class SigningPublicKey extends SimpleDataStructure { public SigType getType() { return _type; } + + /** + * @since 0.9.8 + */ + @Override + public String toString() { + StringBuilder buf = new StringBuilder(64); + buf.append('[').append(getClass().getSimpleName()).append(' ').append(_type).append(": "); + if (_data == null) { + buf.append("null"); + } else { + buf.append("size: ").append(Integer.toString(length())); + } + buf.append(']'); + return buf.toString(); + } } diff --git a/core/java/src/net/i2p/util/NativeBigInteger.java b/core/java/src/net/i2p/util/NativeBigInteger.java index cdd300f86..c84ebf059 100644 --- a/core/java/src/net/i2p/util/NativeBigInteger.java +++ b/core/java/src/net/i2p/util/NativeBigInteger.java @@ -317,11 +317,15 @@ public class NativeBigInteger extends BigInteger { @Override public BigInteger modPow(BigInteger exponent, BigInteger m) { - if (_nativeOk) + // jbigi.c convert_j2mp() and convert_mp2j() do NOT currently support negative numbers + // Where negative or zero values aren't legal in modPow() anyway, avoid native, + // as the Java code will throw an exception rather than silently fail + if (_nativeOk && signum() >= 0 && exponent.signum() >= 0 && m.signum() > 0) return new NativeBigInteger(nativeModPow(toByteArray(), exponent.toByteArray(), m.toByteArray())); else return super.modPow(exponent, m); } + @Override public byte[] toByteArray(){ if(cachedBa == null) //Since we are immutable it is safe to never update the cached ba after it has initially been generated