diff --git a/core/java/src/net/i2p/crypto/KeyStoreUtil.java b/core/java/src/net/i2p/crypto/KeyStoreUtil.java index da0b6dc18..b4f21767a 100644 --- a/core/java/src/net/i2p/crypto/KeyStoreUtil.java +++ b/core/java/src/net/i2p/crypto/KeyStoreUtil.java @@ -479,6 +479,7 @@ public class KeyStoreUtil { List a = new ArrayList(32); a.add(keytool); a.add("-genkey"); // -genkeypair preferred in newer keytools, but this works with more + //a.add("-v"); // verbose, gives you a stack trace on exception a.add("-storetype"); a.add(KeyStore.getDefaultType()); a.add("-keystore"); a.add(ks.getAbsolutePath()); a.add("-storepass"); a.add(ksPW); @@ -765,6 +766,7 @@ public class KeyStoreUtil { * KeyStoreUtil import file.ks file.key alias keypw (imxports private key from file to keystore) * KeyStoreUtil export file.ks alias keypw (exports private key from keystore) * KeyStoreUtil keygen file.ks alias keypw (create keypair in keystore) + * KeyStoreUtil keygen2 file.ks alias keypw (create keypair using I2PProvider) */ /**** public static void main(String[] args) { @@ -781,6 +783,10 @@ public class KeyStoreUtil { testKeygen(args); return; } + if (args.length > 0 && "keygen2".equals(args[0])) { + testKeygen2(args); + return; + } File ksf = (args.length > 0) ? new File(args[0]) : null; if (ksf != null && !ksf.exists()) { createKeyStore(ksf, DEFAULT_KEYSTORE_PASSWORD); @@ -835,5 +841,26 @@ public class KeyStoreUtil { DEFAULT_KEY_VALID_DAYS, "EdDSA", 256, pw); System.out.println("genkey ok? " + ok); } + + private static void testKeygen2(String[] args) throws Exception { + // keygen test using the I2PProvider + SigType type = SigType.EdDSA_SHA512_Ed25519; + java.security.KeyPairGenerator kpg = java.security.KeyPairGenerator.getInstance(type.getBaseAlgorithm().getName()); + kpg.initialize(type.getParams()); + java.security.KeyPair kp = kpg.generateKeyPair(); + java.security.PublicKey jpub = kp.getPublic(); + java.security.PrivateKey jpriv = kp.getPrivate(); + + System.out.println("Encoded private key:"); + System.out.println(net.i2p.util.HexDump.dump(jpriv.getEncoded())); + System.out.println("Encoded public key:"); + System.out.println(net.i2p.util.HexDump.dump(jpub.getEncoded())); + + java.security.Signature jsig = java.security.Signature.getInstance("SHA512withEdDSA"); + jsig.initSign(jpriv); + jsig.update(new byte[111]); + net.i2p.data.Signature sig = SigUtil.fromJavaSig(jsig.sign(), type); + System.out.println("Signature test: " + sig); + } ****/ } diff --git a/core/java/src/net/i2p/crypto/eddsa/EdDSAPrivateKey.java b/core/java/src/net/i2p/crypto/eddsa/EdDSAPrivateKey.java index c1dcd8032..81029c62e 100644 --- a/core/java/src/net/i2p/crypto/eddsa/EdDSAPrivateKey.java +++ b/core/java/src/net/i2p/crypto/eddsa/EdDSAPrivateKey.java @@ -53,7 +53,7 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey { /** * This follows the spec at * https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04 - * NOT the docs from + * AND the docs from * java.security.spec.PKCS8EncodedKeySpec * quote: *
@@ -77,39 +77,43 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
      *  }
      *
* - * @return 39 bytes for Ed25519, null for other curves + * Note that the private key encoding is not fully specified in the Josefsson draft, + * and the example is wrong, as it's lacking Version and AlgorithmIdentifier. + * But sun.security.pkcs.PKCS8Key expects them so we must include them for keytool to work. + * + * @return 49 bytes for Ed25519, null for other curves * @since implemented in 0.9.25 */ public byte[] getEncoded() { // TODO no equals() implemented in spec, but it's essentially a singleton if (!edDsaSpec.equals(EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512))) return null; - int totlen = 7 + seed.length; + int totlen = 17 + seed.length; byte[] rv = new byte[totlen]; int idx = 0; // sequence rv[idx++] = 0x30; - rv[idx++] = (byte) (5 + seed.length); + rv[idx++] = (byte) (15 + seed.length); // version // not in the Josefsson example - //rv[idx++] = 0x02; - //rv[idx++] = 1; - //rv[idx++] = 0; + rv[idx++] = 0x02; + rv[idx++] = 1; + rv[idx++] = 0; // Algorithm Identifier // sequence // not in the Josefsson example - //rv[idx++] = 0x30; - //rv[idx++] = (byte) (10 + seed.length); + rv[idx++] = 0x30; + rv[idx++] = 8; // OID 1.3.101.100 // https://msdn.microsoft.com/en-us/library/windows/desktop/bb540809%28v=vs.85%29.aspx // not in the Josefsson example - //rv[idx++] = 0x06; - //rv[idx++] = 3; - //rv[idx++] = (1 * 40) + 3; - //rv[idx++] = 101; - //rv[idx++] = 100; + rv[idx++] = 0x06; + rv[idx++] = 3; + rv[idx++] = (1 * 40) + 3; + rv[idx++] = 101; + rv[idx++] = 100; // params rv[idx++] = 0x0a; rv[idx++] = 1; @@ -132,7 +136,17 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey { try { int idx = 0; if (d[idx++] != 0x30 || - d[idx++] != 37 || + d[idx++] != 47 || + d[idx++] != 0x02 || + d[idx++] != 1 || + d[idx++] != 0 || + d[idx++] != 0x30 || + d[idx++] != 8 || + d[idx++] != 0x06 || + d[idx++] != 3 || + d[idx++] != (1 * 40) + 3 || + d[idx++] != 101 || + d[idx++] != 100 || d[idx++] != 0x0a || d[idx++] != 1 || d[idx++] != 1 || diff --git a/core/java/src/net/i2p/crypto/eddsa/EdDSAPublicKey.java b/core/java/src/net/i2p/crypto/eddsa/EdDSAPublicKey.java index 0e91f087b..5b7036547 100644 --- a/core/java/src/net/i2p/crypto/eddsa/EdDSAPublicKey.java +++ b/core/java/src/net/i2p/crypto/eddsa/EdDSAPublicKey.java @@ -118,7 +118,7 @@ public class EdDSAPublicKey implements EdDSAKey, PublicKey { d[idx++] != 0x30 || d[idx++] != 8 || d[idx++] != 0x06 || - d[idx++] != 1 || + d[idx++] != 3 || d[idx++] != (1 * 40) + 3 || d[idx++] != 101 || d[idx++] != 100 ||