diff --git a/core/java/src/net/i2p/crypto/eddsa/EdDSAPrivateKey.java b/core/java/src/net/i2p/crypto/eddsa/EdDSAPrivateKey.java index 4136b321a..7fc3dbe85 100644 --- a/core/java/src/net/i2p/crypto/eddsa/EdDSAPrivateKey.java +++ b/core/java/src/net/i2p/crypto/eddsa/EdDSAPrivateKey.java @@ -3,6 +3,7 @@ package net.i2p.crypto.eddsa; import java.security.PrivateKey; import net.i2p.crypto.eddsa.math.GroupElement; +import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec; import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; @@ -39,9 +40,75 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey { return "PKCS#8"; } + /** + * This follows the spec at + * https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04 + * NOT the docs from + * java.security.spec.PKCS8EncodedKeySpec + * quote: + *
+ * The PrivateKeyInfo syntax is defined in the PKCS#8 standard as follows:
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes [0] IMPLICIT Attributes OPTIONAL }
+ * Version ::= INTEGER
+ * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ * PrivateKey ::= OCTET STRING
+ * Attributes ::= SET OF Attribute
+ *
+ *
+ *
+ * AlgorithmIdentifier ::= SEQUENCE
+ * {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY OPTIONAL
+ * }
+ *
+ *
+ * @return 39 bytes for Ed25519, null for other curves
+ * @since implemented in 0.9.25
+ */
public byte[] getEncoded() {
- // TODO Auto-generated method stub
- return null;
+ // 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;
+ byte[] rv = new byte[totlen];
+ int idx = 0;
+ // sequence
+ rv[idx++] = 0x30;
+ rv[idx++] = (byte) (5 + seed.length);
+
+ // version
+ // not in the Josefsson example
+ //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);
+ // 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;
+ // params
+ rv[idx++] = 0x0a;
+ rv[idx++] = 1;
+ rv[idx++] = 1; // Ed25519
+ // the key
+ rv[idx++] = 0x04; // octet string
+ rv[idx++] = (byte) seed.length;
+ System.arraycopy(seed, 0, rv, idx, seed.length);
+ return rv;
}
public EdDSAParameterSpec getParams() {
diff --git a/core/java/src/net/i2p/crypto/eddsa/EdDSAPublicKey.java b/core/java/src/net/i2p/crypto/eddsa/EdDSAPublicKey.java
index 8e436bd1d..4e71f128f 100644
--- a/core/java/src/net/i2p/crypto/eddsa/EdDSAPublicKey.java
+++ b/core/java/src/net/i2p/crypto/eddsa/EdDSAPublicKey.java
@@ -3,6 +3,7 @@ package net.i2p.crypto.eddsa;
import java.security.PublicKey;
import net.i2p.crypto.eddsa.math.GroupElement;
+import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
@@ -35,9 +36,61 @@ public class EdDSAPublicKey implements EdDSAKey, PublicKey {
return "X.509";
}
+ /**
+ * This follows the spec at
+ * ref: https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04
+ * which matches the docs from
+ * java.security.spec.X509EncodedKeySpec
+ * quote:
+ *
+ * The SubjectPublicKeyInfo syntax is defined in the X.509 standard as follows:
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *
+ *
+ *
+ * AlgorithmIdentifier ::= SEQUENCE
+ * {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY OPTIONAL
+ * }
+ *
+ *
+ * @return 47 bytes for Ed25519, null for other curves
+ * @since implemented in 0.9.25
+ */
public byte[] getEncoded() {
- // TODO Auto-generated method stub
- return null;
+ // 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 = 15 + Abyte.length;
+ byte[] rv = new byte[totlen];
+ int idx = 0;
+ // sequence
+ rv[idx++] = 0x30;
+ rv[idx++] = (byte) (13 + Abyte.length);
+ // Algorithm Identifier
+ // sequence
+ 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
+ rv[idx++] = 0x06;
+ rv[idx++] = 3;
+ rv[idx++] = (1 * 40) + 3;
+ rv[idx++] = 101;
+ rv[idx++] = 100;
+ // params
+ rv[idx++] = 0x0a;
+ rv[idx++] = 1;
+ rv[idx++] = 1; // Ed25519
+ // the key
+ rv[idx++] = 0x03; // bit string
+ rv[idx++] = (byte) (1 + Abyte.length);
+ rv[idx++] = 0; // number of trailing unused bits
+ System.arraycopy(Abyte, 0, rv, idx, Abyte.length);
+ return rv;
}
public EdDSAParameterSpec getParams() {