KEYCLOAK-9868 x5t and x5t#S256 JWK parameters

This commit is contained in:
Mark Stickel 2019-03-25 16:02:13 -07:00 committed by Marek Posolda
parent c6bd293d25
commit d5cc18b960
4 changed files with 80 additions and 4 deletions

View file

@ -23,9 +23,7 @@ import org.bouncycastle.openssl.PEMWriter;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.security.Key; import java.security.*;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
@ -157,4 +155,12 @@ public final class PemUtils {
return pem.trim(); return pem.trim();
} }
public static String generateThumbprint(String[] certChain, String encoding) throws NoSuchAlgorithmException, IOException {
return Base64Url.encode(generateThumbprintBytes(certChain, encoding));
}
static byte[] generateThumbprintBytes(String[] certChain, String encoding) throws NoSuchAlgorithmException, IOException {
return MessageDigest.getInstance(encoding).digest(pemToDer(certChain[0]));
}
} }

View file

@ -0,0 +1,40 @@
package org.keycloak.common.util;
import org.junit.Test;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import static org.junit.Assert.assertEquals;
public class PemUtilsTest {
@Test
public void testGenerateThumbprintBytesSha1() throws IOException, NoSuchAlgorithmException {
String[] test = new String[] {"abcdefg"};
byte[] digest = PemUtils.generateThumbprintBytes(test, "SHA-1");
assertEquals(20, digest.length);
}
@Test
public void testGenerateThumbprintBytesSha256() throws IOException, NoSuchAlgorithmException {
String[] test = new String[] {"abcdefg"};
byte[] digest = PemUtils.generateThumbprintBytes(test, "SHA-256");
assertEquals(32, digest.length);
}
@Test
public void testGenerateThumbprintSha1() throws IOException, NoSuchAlgorithmException {
String[] test = new String[] {"abcdefg"};
String encoded = PemUtils.generateThumbprint(test, "SHA-1");
assertEquals(27, encoded.length());
}
@Test
public void testGenerateThumbprintSha256() throws IOException, NoSuchAlgorithmException {
String[] test = new String[] {"abcdefg"};
String encoded = PemUtils.generateThumbprint(test, "SHA-256");
assertEquals(43, encoded.length());
}
}

View file

@ -18,6 +18,10 @@
package org.keycloak.jose.jwk; package org.keycloak.jose.jwk;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import org.keycloak.common.util.PemUtils;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -39,6 +43,10 @@ public class RSAPublicJWK extends JWK {
@JsonProperty("x5c") @JsonProperty("x5c")
private String[] x509CertificateChain; private String[] x509CertificateChain;
private String sha1x509Thumbprint;
private String sha256x509Thumbprint;
public String getModulus() { public String getModulus() {
return modulus; return modulus;
} }
@ -61,6 +69,24 @@ public class RSAPublicJWK extends JWK {
public void setX509CertificateChain(String[] x509CertificateChain) { public void setX509CertificateChain(String[] x509CertificateChain) {
this.x509CertificateChain = x509CertificateChain; this.x509CertificateChain = x509CertificateChain;
if (x509CertificateChain != null && x509CertificateChain.length > 0) {
try {
sha1x509Thumbprint = PemUtils.generateThumbprint(x509CertificateChain, "SHA-1");
sha256x509Thumbprint = PemUtils.generateThumbprint(x509CertificateChain, "SHA-256");
} catch (NoSuchAlgorithmException | IOException e) {
throw new RuntimeException(e);
}
}
}
@JsonProperty("x5t")
public String getSha1x509Thumbprint() {
return sha1x509Thumbprint;
}
@JsonProperty("x5t#S256")
public String getSha256x509Thumbprint() {
return sha256x509Thumbprint;
} }
} }

View file

@ -60,6 +60,10 @@ public class JWKTest {
assertNotNull(((RSAPublicJWK) jwk).getPublicExponent()); assertNotNull(((RSAPublicJWK) jwk).getPublicExponent());
assertNotNull(((RSAPublicJWK) jwk).getX509CertificateChain()); assertNotNull(((RSAPublicJWK) jwk).getX509CertificateChain());
assertEquals(PemUtils.encodeCertificate(certificate), ((RSAPublicJWK) jwk).getX509CertificateChain()[0]); assertEquals(PemUtils.encodeCertificate(certificate), ((RSAPublicJWK) jwk).getX509CertificateChain()[0]);
assertNotNull(((RSAPublicJWK) jwk).getSha1x509Thumbprint());
assertEquals(PemUtils.generateThumbprint(((RSAPublicJWK) jwk).getX509CertificateChain(), "SHA-1"), ((RSAPublicJWK) jwk).getSha1x509Thumbprint());
assertNotNull(((RSAPublicJWK) jwk).getSha256x509Thumbprint());
assertEquals(PemUtils.generateThumbprint(((RSAPublicJWK) jwk).getX509CertificateChain(), "SHA-256"), ((RSAPublicJWK) jwk).getSha256x509Thumbprint());
String jwkJson = JsonSerialization.writeValueAsString(jwk); String jwkJson = JsonSerialization.writeValueAsString(jwk);