mirror of https://github.com/shred/acme4j
Use jose4j's thumbprint calculation
parent
31c4d6d133
commit
91c402473f
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <a href="https://tools.ietf.org/html/rfc7638">RFC 7638</a>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue