propagate from branch 'i2p.i2p' (head 5a3ad2a39b0e0f06e70cb8b4d4f7b1d6461afc1a)

to branch 'i2p.i2p.str4d.eddsa' (head b2a13496a248ebfdac0aa3a8528a27ceff091b6b)
This commit is contained in:
str4d
2014-06-24 02:14:05 +00:00
9 changed files with 227 additions and 52 deletions

View File

@@ -42,6 +42,7 @@ import java.security.interfaces.ECKey;
import java.security.interfaces.RSAKey;
import net.i2p.I2PAppContext;
import net.i2p.crypto.eddsa.EdDSAKey;
import net.i2p.data.Hash;
import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
@@ -503,7 +504,11 @@ public class DSAEngine {
if (type == SigType.DSA_SHA1)
return altVerifySigSHA1(signature, data, offset, len, verifyingKey);
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
java.security.Signature jsig;
if (type.getBaseAlgorithm() == SigAlgo.EdDSA)
jsig = new net.i2p.crypto.eddsa.EdDSAEngine(type.getDigestInstance());
else
jsig = java.security.Signature.getInstance(type.getAlgorithmName());
PublicKey pubKey = SigUtil.toJavaKey(verifyingKey);
jsig.initVerify(pubKey);
jsig.update(data, offset, len);
@@ -543,7 +548,11 @@ public class DSAEngine {
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
String algo = getRawAlgo(type);
java.security.Signature jsig = java.security.Signature.getInstance(algo);
java.security.Signature jsig;
if (type.getBaseAlgorithm() == SigAlgo.EdDSA)
jsig = new net.i2p.crypto.eddsa.EdDSAEngine(); // Ignore algo, EdDSAKey includes a hash specification.
else
jsig = java.security.Signature.getInstance(algo);
jsig.initVerify(pubKey);
jsig.update(hash.getData());
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
@@ -580,7 +589,11 @@ public class DSAEngine {
if (type == SigType.DSA_SHA1)
return altSignSHA1(data, offset, len, privateKey);
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
java.security.Signature jsig;
if (type.getBaseAlgorithm() == SigAlgo.EdDSA)
jsig = new net.i2p.crypto.eddsa.EdDSAEngine(type.getDigestInstance());
else
jsig = java.security.Signature.getInstance(type.getAlgorithmName());
PrivateKey privKey = SigUtil.toJavaKey(privateKey);
jsig.initSign(privKey, _context.random());
jsig.update(data, offset, len);
@@ -613,7 +626,11 @@ public class DSAEngine {
if (type.getHashLen() != hashlen)
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
java.security.Signature jsig = java.security.Signature.getInstance(algo);
java.security.Signature jsig;
if (type.getBaseAlgorithm() == SigAlgo.EdDSA)
jsig = new net.i2p.crypto.eddsa.EdDSAEngine(); // Ignore algo, EdDSAKey includes a hash specification.
else
jsig = java.security.Signature.getInstance(algo);
jsig.initSign(privKey, _context.random());
jsig.update(hash.getData());
return SigUtil.fromJavaSig(jsig.sign(), type);
@@ -640,6 +657,8 @@ public class DSAEngine {
return "NONEwithDSA";
case EC:
return "NONEwithECDSA";
case EdDSA:
return "NONEwithEdDSA";
case RSA:
return "NONEwithRSA";
default:
@@ -653,6 +672,8 @@ public class DSAEngine {
return "NONEwithDSA";
if (key instanceof ECKey)
return "NONEwithECDSA";
if (key instanceof EdDSAKey)
return "NONEwithEdDSA";
if (key instanceof RSAKey)
return "NONEwithRSA";
throw new UnsupportedOperationException("Raw signatures unsupported for " + key.getClass().getName());

View File

@@ -216,40 +216,46 @@ public class KeyGenerator {
public SimpleDataStructure[] generateSigningKeys(SigType type) throws GeneralSecurityException {
if (type == SigType.DSA_SHA1)
return generateSigningKeys();
KeyPairGenerator kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName());
KeyPair kp;
try {
if (type.getBaseAlgorithm() == SigAlgo.EdDSA) {
net.i2p.crypto.eddsa.KeyPairGenerator kpg = new net.i2p.crypto.eddsa.KeyPairGenerator();
kpg.initialize(type.getParams(), _context.random());
kp = kpg.generateKeyPair();
} catch (ProviderException pe) {
// java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DOMAIN_PARAMS_INVALID
// This is a RuntimeException, thx Sun
// Fails for P-192 only, on Ubuntu
Log log = _context.logManager().getLog(KeyGenerator.class);
String pname = kpg.getProvider().getName();
if ("BC".equals(pname)) {
if (log.shouldLog(Log.WARN))
log.warn("BC KPG failed for " + type, pe);
throw new GeneralSecurityException("BC KPG for " + type, pe);
}
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 */ );
} else {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName());
try {
kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName(), "BC");
kpg.initialize(type.getParams(), _context.random());
kp = kpg.generateKeyPair();
} catch (ProviderException pe2) {
} catch (ProviderException pe) {
// java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DOMAIN_PARAMS_INVALID
// This is a RuntimeException, thx Sun
// Fails for P-192 only, on Ubuntu
Log log = _context.logManager().getLog(KeyGenerator.class);
String pname = kpg.getProvider().getName();
if ("BC".equals(pname)) {
if (log.shouldLog(Log.WARN))
log.warn("BC KPG failed for " + type, pe);
throw new GeneralSecurityException("BC KPG for " + type, pe);
}
if (!ECConstants.isBCAvailable())
throw new GeneralSecurityException(pname + " KPG failed for " + type, pe);
if (log.shouldLog(Log.WARN))
log.warn("BC KPG failed for " + type + " also", pe2);
// throw original exception
throw new GeneralSecurityException(pname + " KPG for " + type, pe);
} catch (GeneralSecurityException gse) {
if (log.shouldLog(Log.WARN))
log.warn("BC KPG failed for " + type + " also", gse);
// throw original exception
throw new GeneralSecurityException(pname + " KPG for " + type, pe);
log.warn(pname + " KPG failed for " + type + ", trying BC" /* , pe */ );
try {
kpg = KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName(), "BC");
kpg.initialize(type.getParams(), _context.random());
kp = kpg.generateKeyPair();
} catch (ProviderException pe2) {
if (log.shouldLog(Log.WARN))
log.warn("BC KPG failed for " + type + " also", pe2);
// throw original exception
throw new GeneralSecurityException(pname + " KPG for " + type, pe);
} catch (GeneralSecurityException gse) {
if (log.shouldLog(Log.WARN))
log.warn("BC KPG failed for " + type + " also", gse);
// throw original exception
throw new GeneralSecurityException(pname + " KPG for " + type, pe);
}
}
}
java.security.PublicKey pubkey = kp.getPublic();

View File

@@ -515,6 +515,10 @@ public class SU3File {
StringBuilder buf = new StringBuilder(256);
buf.append("Available signature types:\n");
for (SigType t : EnumSet.allOf(SigType.class)) {
if (!t.isAvailable())
continue;
if (t == SigType.EdDSA_SHA512_25519)
continue; // not supported by keytool, and does double hashing right now
buf.append(" ").append(t).append("\t(code: ").append(t.getCode()).append(')');
if (t.getCode() == DEFAULT_SIG_CODE)
buf.append(" DEFAULT");

View File

@@ -9,6 +9,7 @@ public enum SigAlgo {
DSA("DSA"),
EC("EC"),
EdDSA("EdDSA"),
RSA("RSA")
;

View File

@@ -9,6 +9,7 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.data.Hash;
import net.i2p.data.SimpleDataStructure;
@@ -47,7 +48,8 @@ public enum SigType {
// TESTING....................
/** Pubkey 32 bytes; privkey 32 bytes; hash 64 bytes; sig 64 bytes; */
EdDSA_SHA512_25519(7, 32, 32, 64, 64, SigAlgo.EdDSA, "SHA-512", "SHA512withEdDSA", EdDSANamedCurveTable.getByName("ed25519-sha-512"));
// others..........
@@ -169,7 +171,8 @@ public enum SigType {
return true;
try {
getParams();
Signature.getInstance(getAlgorithmName());
if (getBaseAlgorithm() != SigAlgo.EdDSA)
Signature.getInstance(getAlgorithmName());
getDigestInstance();
getHashInstance();
} catch (Exception e) {

View File

@@ -5,7 +5,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
@@ -33,6 +32,11 @@ import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey;
@@ -47,8 +51,10 @@ import net.i2p.util.NativeBigInteger;
*/
public class SigUtil {
private static final Map<SigningPublicKey, ECPublicKey> _pubkeyCache = new LHMCache<SigningPublicKey, ECPublicKey>(64);
private static final Map<SigningPrivateKey, ECPrivateKey> _privkeyCache = new LHMCache<SigningPrivateKey, ECPrivateKey>(16);
private static final Map<SigningPublicKey, ECPublicKey> _ECPubkeyCache = new LHMCache<SigningPublicKey, ECPublicKey>(64);
private static final Map<SigningPrivateKey, ECPrivateKey> _ECPrivkeyCache = new LHMCache<SigningPrivateKey, ECPrivateKey>(16);
private static final Map<SigningPublicKey, EdDSAPublicKey> _EdPubkeyCache = new LHMCache<SigningPublicKey, EdDSAPublicKey>(64);
private static final Map<SigningPrivateKey, EdDSAPrivateKey> _EdPrivkeyCache = new LHMCache<SigningPrivateKey, EdDSAPrivateKey>(16);
private SigUtil() {}
@@ -62,6 +68,8 @@ public class SigUtil {
return toJavaDSAKey(pk);
case EC:
return toJavaECKey(pk);
case EdDSA:
return toJavaEdDSAKey(pk);
case RSA:
return toJavaRSAKey(pk);
default:
@@ -79,6 +87,8 @@ public class SigUtil {
return toJavaDSAKey(pk);
case EC:
return toJavaECKey(pk);
case EdDSA:
return toJavaEdDSAKey(pk);
case RSA:
return toJavaRSAKey(pk);
default:
@@ -96,6 +106,8 @@ public class SigUtil {
return fromJavaKey((DSAPublicKey) pk);
case EC:
return fromJavaKey((ECPublicKey) pk, type);
case EdDSA:
return fromJavaKey((EdDSAPublicKey) pk, type);
case RSA:
return fromJavaKey((RSAPublicKey) pk, type);
default:
@@ -113,6 +125,8 @@ public class SigUtil {
return fromJavaKey((DSAPrivateKey) pk);
case EC:
return fromJavaKey((ECPrivateKey) pk, type);
case EdDSA:
return fromJavaKey((EdDSAPrivateKey) pk, type);
case RSA:
return fromJavaKey((RSAPrivateKey) pk, type);
default:
@@ -126,14 +140,14 @@ public class SigUtil {
public static ECPublicKey toJavaECKey(SigningPublicKey pk)
throws GeneralSecurityException {
ECPublicKey rv;
synchronized (_pubkeyCache) {
rv = _pubkeyCache.get(pk);
synchronized (_ECPubkeyCache) {
rv = _ECPubkeyCache.get(pk);
}
if (rv != null)
return rv;
rv = cvtToJavaECKey(pk);
synchronized (_pubkeyCache) {
_pubkeyCache.put(pk, rv);
synchronized (_ECPubkeyCache) {
_ECPubkeyCache.put(pk, rv);
}
return rv;
}
@@ -144,14 +158,14 @@ public class SigUtil {
public static ECPrivateKey toJavaECKey(SigningPrivateKey pk)
throws GeneralSecurityException {
ECPrivateKey rv;
synchronized (_privkeyCache) {
rv = _privkeyCache.get(pk);
synchronized (_ECPrivkeyCache) {
rv = _ECPrivkeyCache.get(pk);
}
if (rv != null)
return rv;
rv = cvtToJavaECKey(pk);
synchronized (_privkeyCache) {
_privkeyCache.put(pk, rv);
synchronized (_ECPrivkeyCache) {
_ECPrivkeyCache.put(pk, rv);
}
return rv;
}
@@ -196,6 +210,72 @@ public class SigUtil {
return new SigningPrivateKey(type, bs);
}
/**
* @return JAVA EdDSA public key!
*/
public static EdDSAPublicKey toJavaEdDSAKey(SigningPublicKey pk)
throws GeneralSecurityException {
EdDSAPublicKey rv;
synchronized (_EdPubkeyCache) {
rv = _EdPubkeyCache.get(pk);
}
if (rv != null)
return rv;
rv = cvtToJavaEdDSAKey(pk);
synchronized (_EdPubkeyCache) {
_EdPubkeyCache.put(pk, rv);
}
return rv;
}
/**
* @return JAVA EdDSA private key!
*/
public static EdDSAPrivateKey toJavaEdDSAKey(SigningPrivateKey pk)
throws GeneralSecurityException {
EdDSAPrivateKey rv;
synchronized (_EdPrivkeyCache) {
rv = _EdPrivkeyCache.get(pk);
}
if (rv != null)
return rv;
rv = cvtToJavaEdDSAKey(pk);
synchronized (_EdPrivkeyCache) {
_EdPrivkeyCache.put(pk, rv);
}
return rv;
}
private static EdDSAPublicKey cvtToJavaEdDSAKey(SigningPublicKey pk)
throws GeneralSecurityException {
try {
return new EdDSAPublicKey(new EdDSAPublicKeySpec(
pk.getData(), (EdDSAParameterSpec) pk.getType().getParams()));
} catch (IllegalArgumentException iae) {
throw new InvalidKeyException(iae);
}
}
private static EdDSAPrivateKey cvtToJavaEdDSAKey(SigningPrivateKey pk)
throws GeneralSecurityException {
try {
return new EdDSAPrivateKey(new EdDSAPrivateKeySpec(
pk.getData(), (EdDSAParameterSpec) pk.getType().getParams()));
} catch (IllegalArgumentException iae) {
throw new InvalidKeyException(iae);
}
}
public static SigningPublicKey fromJavaKey(EdDSAPublicKey pk, SigType type)
throws GeneralSecurityException {
return new SigningPublicKey(type, pk.getAbyte());
}
public static SigningPrivateKey fromJavaKey(EdDSAPrivateKey pk, SigType type)
throws GeneralSecurityException {
return new SigningPrivateKey(type, pk.getSeed());
}
public static DSAPublicKey toJavaDSAKey(SigningPublicKey pk)
throws GeneralSecurityException {
KeyFactory kf = KeyFactory.getInstance("DSA");
@@ -290,8 +370,8 @@ public class SigUtil {
* @return ASN.1 representation
*/
public static byte[] toJavaSig(Signature sig) {
// RSA sigs are not ASN encoded
if (sig.getType().getBaseAlgorithm() == SigAlgo.RSA)
// RSA and EdDSA sigs are not ASN encoded
if (sig.getType().getBaseAlgorithm() == SigAlgo.RSA || sig.getType().getBaseAlgorithm() == SigAlgo.EdDSA)
return sig.getData();
return sigBytesToASN1(sig.getData());
}
@@ -302,8 +382,8 @@ public class SigUtil {
*/
public static Signature fromJavaSig(byte[] asn, SigType type)
throws SignatureException {
// RSA sigs are not ASN encoded
if (type.getBaseAlgorithm() == SigAlgo.RSA)
// RSA and EdDSA sigs are not ASN encoded
if (type.getBaseAlgorithm() == SigAlgo.RSA || type.getBaseAlgorithm() == SigAlgo.EdDSA)
return new Signature(type, asn);
return new Signature(type, aSN1ToSigBytes(asn, type.getSigLen()));
}
@@ -530,11 +610,17 @@ public class SigUtil {
}
public static void clearCaches() {
synchronized(_pubkeyCache) {
_pubkeyCache.clear();
synchronized(_ECPubkeyCache) {
_ECPubkeyCache.clear();
}
synchronized(_privkeyCache) {
_privkeyCache.clear();
synchronized(_ECPrivkeyCache) {
_ECPrivkeyCache.clear();
}
synchronized(_EdPubkeyCache) {
_EdPubkeyCache.clear();
}
synchronized(_EdPrivkeyCache) {
_EdPrivkeyCache.clear();
}
}
}

View File

@@ -0,0 +1,42 @@
package net.i2p.crypto.provider;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Provider;
public final class I2PProvider extends Provider {
public static final String PROVIDER_NAME = "I2P";
private static final String INFO = "I2P Security Provider v0.1, implementing" +
"several algorithms used by I2P.";
/**
* Construct a new provider. This should only be required when
* using runtime registration of the provider using the
* <code>Security.addProvider()</code> mechanism.
*/
public I2PProvider() {
super(PROVIDER_NAME, 0.1, INFO);
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
setup();
return null;
}
});
}
private void setup() {
// TODO: Implement SPIs for existing code
//put("Cipher.AES", "net.i2p.crypto.provider.CipherSpi$aesCBC");
//put("Cipher.ElGamal", "net.i2p.crypto.provider.CipherSpi$elGamal");
//put("Mac.HmacMD5-I2P", "net.i2p.crypto.provider.MacSpi");
put("MessageDigest.SHA-1", "net.i2p.crypto.SHA1");
//put("Signature.SHA1withDSA", "net.i2p.crypto.provider.SignatureSpi");
// EdDSA
put("KeyFactory.EdDSA", "net.i2p.crypto.eddsa.KeyFactory");
put("KeyPairGenerator.EdDSA", "net.i2p.crypto.eddsa.KeyPairGenerator");
put("Signature.SHA512withEdDSA", "net.i2p.crypto.eddsa.EdDSAEngine");
}
}