EdDsaTest.java
package org.jose4j.jws;
import org.jose4j.jwk.PublicJsonWebKey;
import org.jose4j.keys.EdDsaKeyUtil;
import org.jose4j.lang.JoseException;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
public class EdDsaTest
{
@BeforeClass
public static void check()
{
// skip these tests if EdDSA isn't available (i.e. before Java 17)
org.junit.Assume.assumeTrue(new EdDsaKeyUtil().isAvailable());
}
@Test
public void rfc8037appendixA1to5() throws Exception
{
// https://www.rfc-editor.org/rfc/rfc8037.html#appendix-A.1
String jwkJson = "{\"kty\":\"OKP\",\"crv\":\"Ed25519\"," +
"\"d\":\"nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A\"," +
"\"x\":\"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo\"}";
PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(jwkJson);
String jkt = jwk.calculateBase64urlEncodedThumbprint("SHA-256");
Assert.assertEquals("kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k", jkt);
JsonWebSignature jwsSigner = new JsonWebSignature();
jwsSigner.setAlgorithmHeaderValue(AlgorithmIdentifiers.EDDSA);
jwsSigner.setPayload("Example of Ed25519 signing");
jwsSigner.setKey(jwk.getPrivateKey());
String jws = jwsSigner.getCompactSerialization();
String expectedJws = "eyJhbGciOiJFZERTQSJ9.RXhhbXBsZSBvZiBFZDI1NTE5IHNpZ25pbmc.hgyY0il_MGCj" +
"P0JzlnLWG1PPOt7-09PGcvMg3AIbQR6dWbhijcNR4ki4iylGjg5BhVsPt9g7sVvpAr_MuM0KAg";
Assert.assertEquals(expectedJws, jws);
String jwkJsonPubOnly = "{\"kty\":\"OKP\",\"crv\":\"Ed25519\",\"x\":\"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo\"}";
PublicJsonWebKey jwkPubOnly = PublicJsonWebKey.Factory.newPublicJwk(jwkJsonPubOnly);
String jktPublicOnly = jwkPubOnly.calculateBase64urlEncodedThumbprint("SHA-256");
Assert.assertEquals("kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k", jktPublicOnly);
JsonWebSignature jwsVerifier = new JsonWebSignature();
jwsVerifier.setCompactSerialization(expectedJws);
jwsVerifier.setKey(jwkPubOnly.getPublicKey());
boolean okay = jwsVerifier.verifySignature();
Assert.assertTrue(okay);
Assert.assertEquals("Example of Ed25519 signing", jwsVerifier.getPayload());
String alteredJws = "eyJhbGciOiJFZERTQSJ9.RXhhbXBsZSBvZiBFZDI1NTE5IHNpZ25pbmc.hgyY0il_MGCj" +
"X0JzlnLWG1PPOt7-09PGcvMg3AIbQR6dWbhijcNR4ki4iylGjg5BhVsPt9g7sVvpAr_MuM0KAg";
jwsVerifier = new JsonWebSignature();
jwsVerifier.setCompactSerialization(alteredJws);
jwsVerifier.setKey(jwkPubOnly.getPublicKey());
okay = jwsVerifier.verifySignature();
Assert.assertFalse(okay);
}
@Test
public void verifyProducedElsewhere() throws JoseException
{
// JWS created using Nimbus which uses Tink for EdDSA
PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(
"{\"kty\":\"OKP\",\"crv\":\"Ed25519\",\"x\":\"sipir4_DXRPiq3vgQPbX5EIZjhdxFVO0bwcVnIFZxQA\"}");
String jws = "eyJhbGciOiJFZERTQSJ9.bWVo.BieQMHmbP-qyMnrbUV_mySYcoDqaxTrQGkGOZ5KGcAZ_8uwwSlds62O8yeHvp5sc4FnEas8XbJilf3-FQbQrAQ";
// verify the signature
JsonWebSignature jwsObject = new JsonWebSignature();
jwsObject.setCompactSerialization(jws);
jwsObject.setKey(jwk.getPublicKey());
Assert.assertTrue(jwsObject.verifySignature());
Assert.assertEquals("meh", jwsObject.getPayload());
// reproduce the JWS, which works b/c EdDSA is deterministic
jwk = PublicJsonWebKey.Factory.newPublicJwk(
"{\"kty\":\"OKP\",\"d\":\"-g8nVY3FlaY9SNE1c5Edn6kQXXQN13SVLCmdlKYgqYM\"," +
"\"crv\":\"Ed25519\",\"x\":\"sipir4_DXRPiq3vgQPbX5EIZjhdxFVO0bwcVnIFZxQA\"}");
jwsObject = new JsonWebSignature();
jwsObject.setAlgorithmHeaderValue(AlgorithmIdentifiers.EDDSA);
jwsObject.setKey(jwk.getPrivateKey());
jwsObject.setPayload("meh");
Assert.assertEquals(jws, jwsObject.getCompactSerialization());
}
@Test
public void ed25519RoundTripGenKeys() throws JoseException
{
EdDsaKeyUtil keyUtil = new EdDsaKeyUtil();
KeyPair keyPair1 = keyUtil.generateKeyPair(EdDsaKeyUtil.ED25519);
KeyPair keyPair2 = keyUtil.generateKeyPair(EdDsaKeyUtil.ED25519);
PrivateKey priv1 = keyPair1.getPrivate();
PublicKey pub1 = keyPair1.getPublic();
PrivateKey priv2 = keyPair2.getPrivate();
PublicKey pub2 = keyPair2.getPublic();
JwsTestSupport.testBasicRoundTrip("Little Ed", AlgorithmIdentifiers.EDDSA, priv1, pub1, priv2, pub2);
}
@Test
public void ed448RoundTripGenKeys() throws JoseException
{
EdDsaKeyUtil keyUtil = new EdDsaKeyUtil();
KeyPair keyPair1 = keyUtil.generateKeyPair(EdDsaKeyUtil.ED448);
KeyPair keyPair2 = keyUtil.generateKeyPair(EdDsaKeyUtil.ED448);
PrivateKey priv1 = keyPair1.getPrivate();
PublicKey pub1 = keyPair1.getPublic();
PrivateKey priv2 = keyPair2.getPrivate();
PublicKey pub2 = keyPair2.getPublic();
JwsTestSupport.testBasicRoundTrip("Big Ed", AlgorithmIdentifiers.EDDSA, priv1, pub1, priv2, pub2);
}
@Test
public void edMixedRoundTripGenKeys() throws JoseException
{
EdDsaKeyUtil keyUtil = new EdDsaKeyUtil();
KeyPair keyPair1 = keyUtil.generateKeyPair(EdDsaKeyUtil.ED25519);
KeyPair keyPair2 = keyUtil.generateKeyPair(EdDsaKeyUtil.ED448);
PrivateKey priv1 = keyPair1.getPrivate();
PublicKey pub1 = keyPair1.getPublic();
PrivateKey priv2 = keyPair2.getPrivate();
PublicKey pub2 = keyPair2.getPublic();
JwsTestSupport.testBasicRoundTrip("Cousin Eddie", AlgorithmIdentifiers.EDDSA, priv1, pub1, priv2, pub2);
}
}