Skip to content

Commit c7b1d62

Browse files
authored
Merge pull request #47 from rnicoll/sun-x509-key
Add handling of X509Key wrapped EdDSA keys
2 parents 4899b66 + a2c70ec commit c7b1d62

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

src/net/i2p/crypto/eddsa/EdDSAEngine.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222
import java.security.Signature;
2323
import java.security.SignatureException;
2424
import java.security.spec.AlgorithmParameterSpec;
25+
import java.security.spec.InvalidKeySpecException;
26+
import java.security.spec.X509EncodedKeySpec;
2527
import java.util.Arrays;
2628

2729
import net.i2p.crypto.eddsa.math.Curve;
2830
import net.i2p.crypto.eddsa.math.GroupElement;
2931
import net.i2p.crypto.eddsa.math.ScalarOps;
32+
import sun.security.x509.X509Key;
3033

3134
/**
3235
* Signing and verification for EdDSA.
@@ -154,6 +157,16 @@ protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException
154157
}
155158
} else if (!key.getParams().getHashAlgorithm().equals(digest.getAlgorithm()))
156159
throw new InvalidKeyException("Key hash algorithm does not match chosen digest");
160+
} else if (publicKey instanceof X509Key) {
161+
// X509Certificate will sometimes contain an X509Key rather than the EdDSAPublicKey itself; the contained
162+
// key is valid but needs to be instanced as an EdDSAPublicKey before it can be used.
163+
EdDSAPublicKey parsedPublicKey;
164+
try {
165+
parsedPublicKey = new EdDSAPublicKey(new X509EncodedKeySpec(publicKey.getEncoded()));
166+
} catch (InvalidKeySpecException ex) {
167+
throw new InvalidKeyException("cannot handle X.509 EdDSA public key: " + publicKey.getAlgorithm());
168+
}
169+
engineInitVerify(parsedPublicKey);
157170
} else {
158171
throw new InvalidKeyException("cannot identify EdDSA public key: " + publicKey.getClass());
159172
}

test/net/i2p/crypto/eddsa/EdDSAEngineTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.security.PublicKey;
2222
import java.security.Signature;
2323
import java.security.SignatureException;
24+
import java.security.cert.X509Certificate;
2425

2526
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
2627
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
@@ -30,6 +31,8 @@
3031
import org.junit.Rule;
3132
import org.junit.Test;
3233
import org.junit.rules.ExpectedException;
34+
import sun.security.util.DerValue;
35+
import sun.security.x509.X509Key;
3336

3437
/**
3538
* @author str4d
@@ -213,4 +216,21 @@ public void testVerifyOneShot() throws Exception {
213216

214217
assertThat("verifyOneShot() failed", sgr.verifyOneShot(TEST_MSG, TEST_MSG_SIG), is(true));
215218
}
219+
220+
@Test
221+
public void testVerifyX509PublicKeyInfo() throws Exception {
222+
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("Ed25519");
223+
Signature sgr = new EdDSAEngine(MessageDigest.getInstance(spec.getHashAlgorithm()));
224+
for (Ed25519TestVectors.TestTuple testCase : Ed25519TestVectors.testCases) {
225+
EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(testCase.pk, spec);
226+
PublicKey vKey = new EdDSAPublicKey(pubKey);
227+
PublicKey x509Key = X509Key.parse(new DerValue(vKey.getEncoded()));
228+
sgr.initVerify(x509Key);
229+
230+
sgr.update(testCase.message);
231+
232+
assertThat("Test case " + testCase.caseNum + " failed",
233+
sgr.verify(testCase.sig), is(true));
234+
}
235+
}
216236
}

0 commit comments

Comments
 (0)