KEYCLOAK-9868 x5t and x5t#S256 JWK parameters
This commit is contained in:
parent
c6bd293d25
commit
d5cc18b960
4 changed files with 80 additions and 4 deletions
|
@ -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]));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue