forked from I2P_Developers/i2p.i2p
Crypto: Implement EdDSA key decoding
following the draft at https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04 (ticket #1723)
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package net.i2p.crypto.eddsa;
|
package net.i2p.crypto.eddsa;
|
||||||
|
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
|
||||||
import net.i2p.crypto.eddsa.math.GroupElement;
|
import net.i2p.crypto.eddsa.math.GroupElement;
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
||||||
@@ -32,6 +34,14 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
|
|||||||
this.edDsaSpec = spec.getParams();
|
this.edDsaSpec = spec.getParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.25
|
||||||
|
*/
|
||||||
|
public EdDSAPrivateKey(PKCS8EncodedKeySpec spec) throws InvalidKeySpecException {
|
||||||
|
this(new EdDSAPrivateKeySpec(decode(spec.getEncoded()),
|
||||||
|
EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)));
|
||||||
|
}
|
||||||
|
|
||||||
public String getAlgorithm() {
|
public String getAlgorithm() {
|
||||||
return "EdDSA";
|
return "EdDSA";
|
||||||
}
|
}
|
||||||
@@ -111,6 +121,32 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is really dumb for now.
|
||||||
|
* See getEncoded().
|
||||||
|
*
|
||||||
|
* @return 32 bytes for Ed25519, throws for other curves
|
||||||
|
* @since 0.9.25
|
||||||
|
*/
|
||||||
|
private static byte[] decode(byte[] d) throws InvalidKeySpecException {
|
||||||
|
try {
|
||||||
|
int idx = 0;
|
||||||
|
if (d[idx++] != 0x30 ||
|
||||||
|
d[idx++] != 37 ||
|
||||||
|
d[idx++] != 0x0a ||
|
||||||
|
d[idx++] != 1 ||
|
||||||
|
d[idx++] != 1 ||
|
||||||
|
d[idx++] != 0x04 ||
|
||||||
|
d[idx++] != 32)
|
||||||
|
throw new InvalidKeySpecException("unsupported key spec");
|
||||||
|
byte[] rv = new byte[32];
|
||||||
|
System.arraycopy(d, idx, rv, 0, 32);
|
||||||
|
return rv;
|
||||||
|
} catch (IndexOutOfBoundsException ioobe) {
|
||||||
|
throw new InvalidKeySpecException(ioobe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public EdDSAParameterSpec getParams() {
|
public EdDSAParameterSpec getParams() {
|
||||||
return edDsaSpec;
|
return edDsaSpec;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
package net.i2p.crypto.eddsa;
|
package net.i2p.crypto.eddsa;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
|
||||||
import net.i2p.crypto.eddsa.math.GroupElement;
|
import net.i2p.crypto.eddsa.math.GroupElement;
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
||||||
@@ -28,6 +30,14 @@ public class EdDSAPublicKey implements EdDSAKey, PublicKey {
|
|||||||
this.edDsaSpec = spec.getParams();
|
this.edDsaSpec = spec.getParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.25
|
||||||
|
*/
|
||||||
|
public EdDSAPublicKey(X509EncodedKeySpec spec) throws InvalidKeySpecException {
|
||||||
|
this(new EdDSAPublicKeySpec(decode(spec.getEncoded()),
|
||||||
|
EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)));
|
||||||
|
}
|
||||||
|
|
||||||
public String getAlgorithm() {
|
public String getAlgorithm() {
|
||||||
return "EdDSA";
|
return "EdDSA";
|
||||||
}
|
}
|
||||||
@@ -93,6 +103,40 @@ public class EdDSAPublicKey implements EdDSAKey, PublicKey {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is really dumb for now.
|
||||||
|
* See getEncoded().
|
||||||
|
*
|
||||||
|
* @return 32 bytes for Ed25519, throws for other curves
|
||||||
|
* @since 0.9.25
|
||||||
|
*/
|
||||||
|
private static byte[] decode(byte[] d) throws InvalidKeySpecException {
|
||||||
|
try {
|
||||||
|
int idx = 0;
|
||||||
|
if (d[idx++] != 0x30 ||
|
||||||
|
d[idx++] != 45 ||
|
||||||
|
d[idx++] != 0x30 ||
|
||||||
|
d[idx++] != 8 ||
|
||||||
|
d[idx++] != 0x06 ||
|
||||||
|
d[idx++] != 1 ||
|
||||||
|
d[idx++] != (1 * 40) + 3 ||
|
||||||
|
d[idx++] != 101 ||
|
||||||
|
d[idx++] != 100 ||
|
||||||
|
d[idx++] != 0x0a ||
|
||||||
|
d[idx++] != 1 ||
|
||||||
|
d[idx++] != 1 ||
|
||||||
|
d[idx++] != 0x03 ||
|
||||||
|
d[idx++] != 32 ||
|
||||||
|
d[idx++] != 0)
|
||||||
|
throw new InvalidKeySpecException("unsupported key spec");
|
||||||
|
byte[] rv = new byte[32];
|
||||||
|
System.arraycopy(d, idx, rv, 0, 32);
|
||||||
|
return rv;
|
||||||
|
} catch (IndexOutOfBoundsException ioobe) {
|
||||||
|
throw new InvalidKeySpecException(ioobe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public EdDSAParameterSpec getParams() {
|
public EdDSAParameterSpec getParams() {
|
||||||
return edDsaSpec;
|
return edDsaSpec;
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,8 @@ import java.security.PrivateKey;
|
|||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.KeySpec;
|
import java.security.spec.KeySpec;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
|
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
||||||
@@ -18,19 +20,31 @@ import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
|||||||
*/
|
*/
|
||||||
public class KeyFactory extends KeyFactorySpi {
|
public class KeyFactory extends KeyFactorySpi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As of 0.9.25, supports PKCS8EncodedKeySpec
|
||||||
|
*/
|
||||||
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
|
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
|
||||||
throws InvalidKeySpecException {
|
throws InvalidKeySpecException {
|
||||||
if (keySpec instanceof EdDSAPrivateKeySpec) {
|
if (keySpec instanceof EdDSAPrivateKeySpec) {
|
||||||
return new EdDSAPrivateKey((EdDSAPrivateKeySpec) keySpec);
|
return new EdDSAPrivateKey((EdDSAPrivateKeySpec) keySpec);
|
||||||
}
|
}
|
||||||
|
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||||
|
return new EdDSAPrivateKey((PKCS8EncodedKeySpec) keySpec);
|
||||||
|
}
|
||||||
throw new InvalidKeySpecException("key spec not recognised");
|
throw new InvalidKeySpecException("key spec not recognised");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As of 0.9.25, supports X509EncodedKeySpec
|
||||||
|
*/
|
||||||
protected PublicKey engineGeneratePublic(KeySpec keySpec)
|
protected PublicKey engineGeneratePublic(KeySpec keySpec)
|
||||||
throws InvalidKeySpecException {
|
throws InvalidKeySpecException {
|
||||||
if (keySpec instanceof EdDSAPublicKeySpec) {
|
if (keySpec instanceof EdDSAPublicKeySpec) {
|
||||||
return new EdDSAPublicKey((EdDSAPublicKeySpec) keySpec);
|
return new EdDSAPublicKey((EdDSAPublicKeySpec) keySpec);
|
||||||
}
|
}
|
||||||
|
if (keySpec instanceof X509EncodedKeySpec) {
|
||||||
|
return new EdDSAPublicKey((X509EncodedKeySpec) keySpec);
|
||||||
|
}
|
||||||
throw new InvalidKeySpecException("key spec not recognised");
|
throw new InvalidKeySpecException("key spec not recognised");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user