From 91c402473fea5333983e280497e7e9f70f66e407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20K=C3=B6rber?= Date: Wed, 27 Jul 2016 22:55:24 +0200 Subject: [PATCH] Use jose4j's thumbprint calculation --- .../org/shredzone/acme4j/Registration.java | 7 ++-- .../acme4j/challenge/TokenChallenge.java | 16 ++++++--- .../shredzone/acme4j/util/SignatureUtils.java | 36 ------------------- .../acme4j/challenge/ChallengeTest.java | 31 ---------------- .../acme4j/util/SignatureUtilsTest.java | 14 -------- 5 files changed, 15 insertions(+), 89 deletions(-) diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java index 091ecf46..eb1d7be6 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java @@ -290,11 +290,12 @@ public class Registration extends AcmeResource { String rollover; try { + final PublicJsonWebKey oldKeyJwk = PublicJsonWebKey.Factory.newPublicJwk(getSession().getKeyPair().getPublic()); + final PublicJsonWebKey newKeyJwk = PublicJsonWebKey.Factory.newPublicJwk(newKeyPair.getPublic()); + ClaimBuilder newKeyClaim = new ClaimBuilder(); newKeyClaim.putResource("reg"); - newKeyClaim.putBase64("newKey", SignatureUtils.jwkThumbprint(newKeyPair.getPublic())); - - final PublicJsonWebKey oldKeyJwk = PublicJsonWebKey.Factory.newPublicJwk(getSession().getKeyPair().getPublic()); + newKeyClaim.putBase64("newKey", newKeyJwk.calculateThumbprint("SHA-256")); JsonWebSignature jws = new JsonWebSignature(); jws.setPayload(newKeyClaim.toString()); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java index 97027718..1ddf8f2f 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java @@ -16,10 +16,11 @@ package org.shredzone.acme4j.challenge; import java.security.PublicKey; import org.jose4j.base64url.Base64Url; +import org.jose4j.jwk.PublicJsonWebKey; +import org.jose4j.lang.JoseException; import org.shredzone.acme4j.Session; import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.util.ClaimBuilder; -import org.shredzone.acme4j.util.SignatureUtils; /** * An extension of {@link Challenge} that handles challenges with a {@code token} and @@ -77,10 +78,15 @@ public class TokenChallenge extends Challenge { * @return Authorization string */ protected String computeAuthorization() { - PublicKey pk = getSession().getKeyPair().getPublic(); - return getToken() - + '.' - + Base64Url.encode(SignatureUtils.jwkThumbprint(pk)); + try { + PublicKey pk = getSession().getKeyPair().getPublic(); + PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(pk); + return getToken() + + '.' + + Base64Url.encode(jwk.calculateThumbprint("SHA-256")); + } catch (JoseException ex) { + throw new AcmeProtocolException("Cannot compute key thumbprint", ex); + } } @Override diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/util/SignatureUtils.java b/acme4j-client/src/main/java/org/shredzone/acme4j/util/SignatureUtils.java index 439d3875..e1afc35a 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/util/SignatureUtils.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/util/SignatureUtils.java @@ -13,19 +13,11 @@ */ package org.shredzone.acme4j.util; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; - import org.jose4j.jwk.EllipticCurveJsonWebKey; import org.jose4j.jwk.JsonWebKey; -import org.jose4j.jwk.JsonWebKey.OutputControlLevel; import org.jose4j.jwk.RsaJsonWebKey; import org.jose4j.jws.AlgorithmIdentifiers; import org.jose4j.jws.JsonWebSignature; -import org.jose4j.lang.JoseException; -import org.shredzone.acme4j.exception.AcmeProtocolException; /** * Utility class for signatures. @@ -73,32 +65,4 @@ public final class SignatureUtils { } } - /** - * Computes a JWK Thumbprint. It is frequently used in responses. - * - * @param key - * {@link PublicKey} to create a thumbprint of - * @return Thumbprint, SHA-256 hashed - * @see RFC 7638 - */ - public static byte[] jwkThumbprint(PublicKey key) { - if (key == null) { - throw new NullPointerException("key must not be null"); - } - - try { - final JsonWebKey jwk = JsonWebKey.Factory.newJwk(key); - - // We need to use ClaimBuilder to bring the keys in lexicographical order. - ClaimBuilder cb = new ClaimBuilder(); - cb.putAll(jwk.toParams(OutputControlLevel.PUBLIC_ONLY)); - - MessageDigest md = MessageDigest.getInstance("SHA-256"); - md.update(cb.toString().getBytes("UTF-8")); - return md.digest(); - } catch (JoseException | NoSuchAlgorithmException | UnsupportedEncodingException ex) { - throw new AcmeProtocolException("Cannot compute key thumbprint", ex); - } - } - } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java index c273afbc..ee7497bc 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java @@ -26,14 +26,10 @@ import java.io.ObjectOutputStream; import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; -import java.security.KeyPair; import java.util.Date; import java.util.Map; -import org.jose4j.base64url.Base64Url; import org.jose4j.json.JsonUtil; -import org.jose4j.jwk.JsonWebKey; -import org.jose4j.jwk.JsonWebKey.OutputControlLevel; import org.jose4j.lang.JoseException; import org.junit.Before; import org.junit.Test; @@ -43,7 +39,6 @@ import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeRetryAfterException; import org.shredzone.acme4j.provider.TestableConnectionProvider; import org.shredzone.acme4j.util.ClaimBuilder; -import org.shredzone.acme4j.util.SignatureUtils; import org.shredzone.acme4j.util.TestUtils; import org.shredzone.acme4j.util.TimestampParser; @@ -140,32 +135,6 @@ public class ChallengeTest { challenge.unmarshall(TestUtils.getJsonAsMap("dnsChallenge")); } - /** - * Test that the test keypair's thumbprint is correct. - */ - @Test - public void testJwkThumbprint() throws IOException, JoseException { - StringBuilder json = new StringBuilder(); - json.append('{'); - json.append("\"e\":\"").append(TestUtils.E).append("\","); - json.append("\"kty\":\"").append(TestUtils.KTY).append("\","); - json.append("\"n\":\"").append(TestUtils.N).append("\""); - json.append('}'); - - KeyPair keypair = TestUtils.createKeyPair(); - - // Test the JWK raw output. The JSON string must match the assert string - // exactly, as the thumbprint is a digest of that string. - final JsonWebKey jwk = JsonWebKey.Factory.newJwk(keypair.getPublic()); - ClaimBuilder cb = new ClaimBuilder(); - cb.putAll(jwk.toParams(OutputControlLevel.PUBLIC_ONLY)); - assertThat(cb.toString(), is(json.toString())); - - // Make sure the returned thumbprint is correct - byte[] thumbprint = SignatureUtils.jwkThumbprint(keypair.getPublic()); - assertThat(thumbprint, is(Base64Url.decode(TestUtils.THUMBPRINT))); - } - /** * Test that a challenge can be triggered. */ diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/util/SignatureUtilsTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/util/SignatureUtilsTest.java index 1506243f..d665bbc1 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/util/SignatureUtilsTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/util/SignatureUtilsTest.java @@ -20,7 +20,6 @@ import java.security.KeyPair; import java.security.Security; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.jose4j.base64url.Base64Url; import org.jose4j.jwk.PublicJsonWebKey; import org.junit.BeforeClass; import org.junit.Test; @@ -87,17 +86,4 @@ public class SignatureUtilsTest { assertThat(type, is("ES512")); } - /** - * Test if {@link SignatureUtils#jwkThumbprint(java.security.PublicKey)} returns the - * correct thumb print. - */ - @Test - public void testJwkThumbprint() throws Exception { - KeyPair keyPair = TestUtils.createKeyPair(); - - byte[] thumbprint = SignatureUtils.jwkThumbprint(keyPair.getPublic()); - - assertThat(Base64Url.encode(thumbprint), is(TestUtils.THUMBPRINT)); - } - }