mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 23:12:06 -03:30
JWK Algorithm Key Pair support (#44203)
Closes #44141 Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
parent
10f3feeee6
commit
f6702decc0
@ -54,4 +54,8 @@ public interface Algorithm {
|
||||
String ECDH_ES_A128KW = CryptoConstants.ECDH_ES_A128KW;
|
||||
String ECDH_ES_A192KW = CryptoConstants.ECDH_ES_A192KW;
|
||||
String ECDH_ES_A256KW = CryptoConstants.ECDH_ES_A256KW;
|
||||
|
||||
String ML_DSA_44 = "ML-DSA-44";
|
||||
String ML_DSA_65 = "ML-DSA-65";
|
||||
String ML_DSA_87 = "ML-DSA-87";
|
||||
}
|
||||
|
||||
@ -22,5 +22,6 @@ public interface KeyType {
|
||||
String RSA = "RSA";
|
||||
String OCT = "OCT";
|
||||
String OKP = "OKP";
|
||||
String AKP = "AKP";
|
||||
|
||||
}
|
||||
|
||||
55
core/src/main/java/org/keycloak/jose/jwk/AKPPublicJWK.java
Normal file
55
core/src/main/java/org/keycloak/jose/jwk/AKPPublicJWK.java
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.jose.jwk;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:takashi.norimatsu.ws@hitachi.com">Takashi Norimatsu</a>
|
||||
*/
|
||||
public class AKPPublicJWK extends JWK {
|
||||
|
||||
public static final String PUB = "pub";
|
||||
|
||||
@JsonProperty(PUB)
|
||||
private String pub;
|
||||
|
||||
public String getPub() {
|
||||
return pub;
|
||||
}
|
||||
|
||||
public void setPub(String pub) {
|
||||
this.pub = pub;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public <T> T getOtherClaim(String claimName, Class<T> claimType) {
|
||||
Object claim = null;
|
||||
if (claimName.equals(PUB)) {
|
||||
claim = getPub();
|
||||
}
|
||||
if (claim != null) {
|
||||
return claimType.cast(claim);
|
||||
} else {
|
||||
return super.getOtherClaim(claimName, claimType);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
59
core/src/main/java/org/keycloak/jose/jwk/AKPUtils.java
Normal file
59
core/src/main/java/org/keycloak/jose/jwk/AKPUtils.java
Normal file
@ -0,0 +1,59 @@
|
||||
package org.keycloak.jose.jwk;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.crypto.Algorithm;
|
||||
|
||||
/**
|
||||
* Adds and removes prefix to X.509 DER encoded public keys.
|
||||
*/
|
||||
public class AKPUtils {
|
||||
|
||||
// See AKPJWKTest to generate new prefixes
|
||||
static final Map<String, byte[]> PREFIXES = new HashMap<>();
|
||||
static {
|
||||
PREFIXES.put(Algorithm.ML_DSA_44, new byte[] { 48, -126, 5, 50, 48, 11, 6, 9, 96, -122, 72, 1, 101, 3, 4, 3, 17, 3, -126, 5, 33, 0, });
|
||||
PREFIXES.put(Algorithm.ML_DSA_65, new byte[] { 48, -126, 7, -78, 48, 11, 6, 9, 96, -122, 72, 1, 101, 3, 4, 3, 18, 3, -126, 7, -95, 0, });
|
||||
PREFIXES.put(Algorithm.ML_DSA_87, new byte[] { 48, -126, 10, 50, 48, 11, 6, 9, 96, -122, 72, 1, 101, 3, 4, 3, 19, 3, -126, 10, 33, 0, });
|
||||
}
|
||||
|
||||
public static PublicKey fromEncodedPub(String publicKey, String algorithm) {
|
||||
try {
|
||||
byte[] prefix = PREFIXES.get(algorithm);
|
||||
byte[] keyWithPadding = combine(prefix, Base64.getUrlDecoder().decode(publicKey));
|
||||
|
||||
EncodedKeySpec keySpec = new X509EncodedKeySpec(keyWithPadding);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
|
||||
return keyFactory.generatePublic(keySpec);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String toEncodedPub(PublicKey publicKey, String algorithm) {
|
||||
byte[] prefix = PREFIXES.get(algorithm);
|
||||
byte[] keyOutWithoutPadding = removePadding(publicKey.getEncoded(), prefix.length);
|
||||
return Base64.getUrlEncoder().withoutPadding().encodeToString(keyOutWithoutPadding);
|
||||
}
|
||||
|
||||
private static byte[] combine(byte[] first, byte[] second) {
|
||||
byte[] c = new byte[first.length + second.length];
|
||||
System.arraycopy(first, 0, c, 0, first.length);
|
||||
System.arraycopy(second, 0, c, first.length, second.length);
|
||||
return c;
|
||||
}
|
||||
|
||||
private static byte[] removePadding(byte[] bytes, int length) {
|
||||
byte[] b = new byte[bytes.length - length];
|
||||
System.arraycopy(bytes, length, b, 0, bytes.length - length);
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
@ -83,6 +83,19 @@ public class JWKBuilder {
|
||||
return rsa(key);
|
||||
}
|
||||
|
||||
public JWK akp(PublicKey key) {
|
||||
AKPPublicJWK k = new AKPPublicJWK();
|
||||
|
||||
String kid = this.kid != null ? this.kid : KeyUtils.createKeyId(key);
|
||||
k.setKeyId(kid);
|
||||
k.setKeyType(KeyType.AKP);
|
||||
k.setAlgorithm(algorithm);
|
||||
k.setPub(AKPUtils.toEncodedPub(key, algorithm));
|
||||
k.setPublicKeyUse(KeyUse.SIG.getSpecName());
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
public JWK rsa(Key key) {
|
||||
return rsa(key, null, KeyUse.SIG);
|
||||
}
|
||||
|
||||
@ -82,6 +82,8 @@ public class JWKParser {
|
||||
return createECPublicKey(normalizedJwkNode);
|
||||
} else if (KeyType.OKP.equals(keyType)) {
|
||||
return JWKBuilder.EdEC_UTILS.createOKPPublicKey(jwk);
|
||||
} else if (KeyType.AKP.equals(keyType)) {
|
||||
return createAPKPublicKey(normalizedJwkNode);
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported keyType " + keyType);
|
||||
}
|
||||
@ -143,8 +145,15 @@ public class JWKParser {
|
||||
}
|
||||
}
|
||||
|
||||
private static PublicKey createAPKPublicKey(JsonNode jwk) {
|
||||
String algorithm = jwk.path(JWK.ALGORITHM).asText();
|
||||
String publicKey = jwk.path(AKPPublicJWK.PUB).asText();
|
||||
return AKPUtils.fromEncodedPub(publicKey, algorithm);
|
||||
}
|
||||
|
||||
public boolean isKeyTypeSupported(String keyType) {
|
||||
return (RSAPublicJWK.RSA.equals(keyType) || ECPublicJWK.EC.equals(keyType)
|
||||
|| (JWKBuilder.EdEC_UTILS.isEdECSupported() && OKPPublicJWK.OKP.equals(keyType)));
|
||||
|| (JWKBuilder.EdEC_UTILS.isEdECSupported() && OKPPublicJWK.OKP.equals(keyType)))
|
||||
|| KeyType.AKP.equals(keyType);
|
||||
}
|
||||
}
|
||||
|
||||
100
core/src/test/java/org/keycloak/jose/jwk/AKPJWKTest.java
Normal file
100
core/src/test/java/org/keycloak/jose/jwk/AKPJWKTest.java
Normal file
@ -0,0 +1,100 @@
|
||||
package org.keycloak.jose.jwk;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import org.keycloak.crypto.Algorithm;
|
||||
import org.keycloak.crypto.KeyType;
|
||||
import org.keycloak.crypto.KeyUse;
|
||||
import org.keycloak.rule.CryptoInitRule;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
public abstract class AKPJWKTest {
|
||||
|
||||
// There is a chance that two keys are generated starting with the same byte, hence generating multiple keys to take the common prefix from all
|
||||
private static final int KEYS_TO_GENERATE = 5;
|
||||
|
||||
@ClassRule
|
||||
public static CryptoInitRule cryptoInitRule = new CryptoInitRule();
|
||||
|
||||
@Test
|
||||
public void parseMLS_DSA_44() throws IOException {
|
||||
testDecodingAndEncodingPublicKey(Algorithm.ML_DSA_44, AKPSamples.ML_DSA_44);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMLS_DSA_65() throws IOException {
|
||||
testDecodingAndEncodingPublicKey(Algorithm.ML_DSA_65, AKPSamples.ML_DSA_65);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMLS_DSA_87() throws IOException {
|
||||
testDecodingAndEncodingPublicKey(Algorithm.ML_DSA_87, AKPSamples.ML_DSA_87);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixMLS_DSA_44() throws NoSuchAlgorithmException {
|
||||
testPrefix(Algorithm.ML_DSA_44);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixMLS_DSA_65() throws NoSuchAlgorithmException {
|
||||
testPrefix(Algorithm.ML_DSA_65);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixMLS_DSA_87() throws NoSuchAlgorithmException {
|
||||
testPrefix(Algorithm.ML_DSA_87);
|
||||
}
|
||||
|
||||
private void testDecodingAndEncodingPublicKey(String algorithm, String sampleJwk) throws IOException {
|
||||
JWK jwk = JsonSerialization.readValue(sampleJwk, JWK.class);
|
||||
|
||||
PublicKey publicKey = JWKParser.create(jwk).toPublicKey();
|
||||
|
||||
Assert.assertTrue(publicKey.getAlgorithm().startsWith("ML-DSA"));
|
||||
|
||||
JWK akp = JWKBuilder.create().algorithm(algorithm).kid(jwk.getKeyId()).akp(publicKey);
|
||||
|
||||
Assert.assertEquals(algorithm, akp.getAlgorithm());
|
||||
Assert.assertEquals(KeyType.AKP, akp.getKeyType());
|
||||
Assert.assertEquals(KeyUse.SIG.getSpecName(), akp.getPublicKeyUse());
|
||||
Assert.assertEquals(jwk.getKeyId(), akp.getKeyId());
|
||||
Assert.assertEquals(jwk.getOtherClaim(AKPPublicJWK.PUB, String.class), akp.getOtherClaim(AKPPublicJWK.PUB, String.class));
|
||||
}
|
||||
|
||||
private JWK getJwk(String algorithm) throws IOException {
|
||||
InputStream inputStream = getClass().getResourceAsStream(algorithm.replace('-', '_') + ".jose.json");
|
||||
return JsonSerialization.readValue(inputStream, JWK.class);
|
||||
}
|
||||
|
||||
private void testPrefix(String algorithm) throws NoSuchAlgorithmException {
|
||||
KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm);
|
||||
|
||||
byte[] expectedPrefix = kpg.generateKeyPair().getPublic().getEncoded();
|
||||
|
||||
for (int i = 0; i < KEYS_TO_GENERATE; i++) {
|
||||
byte[] bytes2 = kpg.generateKeyPair().getPublic().getEncoded();
|
||||
expectedPrefix = findMatchingPrefix(expectedPrefix, bytes2);
|
||||
}
|
||||
|
||||
Assert.assertArrayEquals(AKPUtils.PREFIXES.get(algorithm), expectedPrefix);
|
||||
}
|
||||
|
||||
private static byte[] findMatchingPrefix(byte[] a, byte[] b) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
for (int i = 0; i < a.length && a[i] == b[i]; i++) {
|
||||
bos.write(a[i]);
|
||||
}
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
30
core/src/test/java/org/keycloak/jose/jwk/AKPSamples.java
Normal file
30
core/src/test/java/org/keycloak/jose/jwk/AKPSamples.java
Normal file
@ -0,0 +1,30 @@
|
||||
package org.keycloak.jose.jwk;
|
||||
|
||||
// ML-DSA examples from https://github.com/cose-wg/draft-ietf-cose-dilithium/tree/main/examples/jose
|
||||
public interface AKPSamples {
|
||||
|
||||
String ML_DSA_44 = "{\n" +
|
||||
" \"kid\": \"T4xl70S7MT6Zeq6r9V9fPJGVn76wfnXJ21-gyo0Gu6o\",\n" +
|
||||
" \"kty\": \"AKP\",\n" +
|
||||
" \"alg\": \"ML-DSA-44\",\n" +
|
||||
" \"pub\": \"unH59k4RuutY-pxvu24U5h8YZD2rSVtHU5qRZsoBmBMcRPgmu9VuNOVdteXi1zNIXjnqJg_GAAxepLqA00Vc3lO0bzRIKu39VFD8Lhuk8l0V-cFEJC-zm7UihxiQMMUEmOFxe3x1ixkKZ0jqmqP3rKryx8tSbtcXyfea64QhT6XNje2SoMP6FViBDxLHBQo2dwjRls0k5a-XSQSu2OTOiHLoaWsLe8pQ5FLNfTDqmkrawDEdZyxr3oSWJAsHQxRjcIiVzZuvwxYy1zl2STiP2vy_fTBaPemkleynQzqPg7oPCyXEE8bjnJbrfWkbNNN8438e6tHPIX4l7zTuzz98YPhLjt_d6EBdT4MldsYe-Y4KLyjaGHcAlTkk9oa5RhRwW89T0z_t1DSO3dvfKLUGXh8gd1BD6Fz5MfgpF5NjoafnQEqDjsAAhrCXY4b-Y3yYJEdX4_dp3dRGdHG_rWcPmgX4JG7lCnser4f8QGnDriqiAzJYEXeS8LzUngg_0bx0lqv_KcyU5IaLISFO0xZSU5mmEPvdSoDnyAcV8pV44qhLtAvd29n0ehG259oRihtljTWeiu9V60a1N2tbZVl5mEqSK-6_xZvNYA1TCdzNctvweH24unV7U3wer9XA9Q6kvJWDVJ4oKaQsKMrCSMlteBJMRxWbGK7ddUq6F7GdQw-3j2M-qdJvVKm9UPjY9rc1lPgol25-oJxTu7nxGlbJUH-4m5pevAN6NyZ6lfhbjWTKlxkrEKZvQXs_Yf6cpXEwpI_ZJeriq1UC1XHIpRkDwdOY9MH3an4RdDl2r9vGl_IwlKPNdh_5aF3jLgn7PCit1FNJAwC8fIncAXgAlgcXIpRXdfJk4bBiO89GGccSyDh2EgXYdpG3XvNgGWy7npuSoNTE7WIyblAk13UQuO4sdCbMIuriCdyfE73mvwj15xgb07RZRQtFGlFTmnFcIdZ90zDrWXDbANntv7KCKwNvoTuv64bY3HiGbj-NQ-U9eMylWVpvr4hrXcES8c9K3PqHWADZC0iIOvlzFv4VBoc_wVflcOrL_SIoaNFCNBAZZq-2v5lAgpJTqVOtqJ_HVraoSfcKy5g45p-qULunXj6Jwq21fobQiKubBKKOZwcJFyJD7F4ACKXOrz-HIvSHMCWW_9dVrRuCpJw0s0aVFbRqopDNhu446nqb4_EDYQM1tTHMozPd_jKxRRD0sH75X8ZoToxFSpLBDbtdWcenxj-zBf6IGWfZnmaetjKEBYJWC7QDQx1A91pJVJCEgieCkoIfTqkeQuePpIyu48g2FG3P1zjRF-kumhUTfSjo5qS0YiZQy0E1BMs6M11EvuxXRsHClLHoy5nLYI2Sj4zjVjYyxSHyPRPGGo9hwB34yWxzYNtPPGiqXS_dNCpi_zRZwRY4lCGrQ-hYTEWIK1Dm5OlttvC4_eiQ1dv63NiGkLRJ5kJA3bICN0fzCDY-MBqnd1cWn8YVBijVkgtaoascjL9EywDgJdeHnXK0eeOvUxHHhXJVkNqcibn8O4RQdpVU60TSA-uiu675ytIjcBHC6kTv8A8pmkj_4oypPd-F92YIJC741swkYQoeIHj8rE-ThcMUkF7KqC5VORbZTRp8HsZSqgiJcIPaouuxd1-8Rxrid3fXkE6p8bkrysPYoxWEJgh7ZFsRCPDWX-yTeJwFN0PKFP1j0F6YtlLfK5wv-c4F8ZQHA_-yc_gODicy7KmWDZgbTP07e7gEWzw4MFRrndjbDQ\",\n" +
|
||||
" \"priv\": \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"\n" +
|
||||
"}";
|
||||
|
||||
String ML_DSA_65 = "{\n" +
|
||||
" \"kid\": \"Suiu29qbfuaBaR4Ats-c6XQBePB_OpAxAwcTR_0KXVM\",\n" +
|
||||
" \"kty\": \"AKP\",\n" +
|
||||
" \"alg\": \"ML-DSA-65\",\n" +
|
||||
" \"pub\": \"QksvJn5Y1bO0TXGs_Gpla7JpUNV8YdsciAvPof6rRD8JQquL2619cIq7w1YHj22ZolInH-YsdAkeuUr7m5JkxQqIjg3-2AzV-yy9NmfmDVOevkSTAhnNT67RXbs0VaJkgCufSbzkLudVD-_91GQqVa3mk4aKRgy-wD9PyZpOMLzP-opHXlOVOWZ067galJN1h4gPbb0nvxxPWp7kPN2LDlOzt_tJxzrfvC1PjFQwNSDCm_l-Ju5X2zQtlXyJOTZSLQlCtB2C7jdyoAVwrftUXBFDkisElvgmoKlwBks23fU0tfjhwc0LVWXqhGtFQx8GGBQ-zol3e7P2EXmtIClf4KbgYq5u7Lwu848qwaItyTt7EmM2IjxVth64wHlVQruy3GXnIurcaGb_qWg764qZmteoPl5uAWwuTDX292Sa071S7GfsHFxue5lydxIYvpVUu6dyfwuExEubCovYMfz_LJd5zNTKMMatdbBJg-Qd6JPuXznqc1UYC3CccEXCLTOgg_auB6EUdG0b_cy-5bkEOHm7Wi4SDipGNig_ShzUkkot5qSqPZnd2I9IqqToi_0ep2nYLBB3ny3teW21Qpccoom3aGPt5Zl7fpzhg7Q8zsJ4sQ2SuHRCzgQ1uxYlFx21VUtHAjnFDSoMOkGyo4gH2wcLR7-z59EPPNl51pljyNefgCnMSkjrBPyz1wiET-uqi23f8Bq2TVk1jmUFxOwdfLsU7SIS30WOzvwD_gMDexUFpMlEQyL1-Y36kaTLjEWGCi2tx1FTULttQx5JpryPW6lW5oKw5RMyGpfRliYCiRyQePYqipZGoxOHpvCWhCZIN4meDY7H0RxWWQEpiyCzRQgWkOtMViwao6Jb7wZWbLNMebwLJeQJXWunk-gTEeQaMykVJobwDUiX-E_E7fSybVRTZXherY1jrvZKh8C5Gi5VADg5Vs319uN8-dVILRyOOlvjjxclmsRcn6HEvTvxd9MS7lKm2gI8BXIqhzgnTdqNGwTpmDHPV8hygqJWxWXCltBSSgY6OkGkioMAmXjZjYq_Ya9o6AE7WU_hUdm-wZmQLExwtJWEIBdDxrUxA9L9JL3weNyQtaGItPjXcheZiNBBbJTUxXwIYLnXtT1M0mHzMqGFFWXVKsN_AIdHyv4yDzY9m-tuQRfbQ_2K7r5eDOL1Tj8DZ-s8yXG74MMBqOUvlglJNgNcbuPKLRPbSDoN0E3BYkfeDgiUrXy34a5-vU-PkAWCsgAh539wJUUBxqw90V1Du7eTHFKDJEMSFYwusbPhEX4ZTwoeTHg--8Ysn4HCFWLQ00pfBCteqvMvMflcWwVfTnogcPsJb1bEFVSc3nTzhk6Ln8J-MplyS0Y5mGBEtVko_WlyeFsoDCWj4hqrgU7L-ww8vsCRSQfskH8lodiLzj0xmugiKjWUXbYq98x1zSnB9dmPy5P3UNwwMQdpebtR38N9I-jup4Bzok0-JsaOe7EORZ8ld7kAgDWa4K7BAxjc2eD540Apwxs-VLGFVkXbQgYYeDNG2tW1Xt20-XezJqZVUl6-IZXsqc7DijwNInO3fT5o8ZAcLKUUlzSlEXe8sIlHaxjLoJ-oubRtlKKUbzWOHeyxmYZSxYqQhSQj4sheedGXJEYWJ-Y5DRqB-xpy-cftxL10fdXIUhe1hWFBAoQU3b5xRY8KCytYnfLhsFF4O49xhnax3vuumLpJbCqTXpLureoKg5PvWfnpFPB0P-ZWQN35mBzqbb3ZV6U0rU55DvyXTuiZOK2Z1TxbaAd1OZMmg0cpuzewgueV-Nh_UubIqNto5RXCd7vqgqdXDUKAiWyYegYIkD4wbGMqIjxV8Oo2ggOcSj9UQPS1rD5u0rLckAzsxyty9Q5JsmKa0w8Eh7Jwe4Yob4xPVWWbJfm916avRgzDxXo5gmY7txdGFYHhlolJKdhBU9h6f0gtKEtbiUzhp4IWsqAR8riHQs7lLVEz6P537a4kL1r5FjfDf_yjJDBQmy_kdWMDqaNln-MlKK8eENjUO-qZGy0Ql4bMZtNbHXjfJUuSzapA-RqYfkqSLKgQUOW8NTDKhUk73yqCU3TQqDEKaGAoTsPscyMm7u_8QrvUK8kbc-XnxrWZ0BZJBjdinzh2w-QvjbWQ5mqFp4OMgY94__tIU8vvCUNJiYA1RdyodlfPfH5-avpxOCvBD6C7ZIDyQ-6huGEQEAb6DP8ydWIZQ8xY603DoEKKXkJWcP6CJo3nHFEdj_vcEbDQ-WESDpcQFa1fRIiGuALj-sEWcjGdSHyE8QATOcuWl4TLVzRPKAf4tCXx1zyvhJbXQu0jf0yfzVpOhPun4n-xqK4SxPBCeuJOkQ2VG9jDXWH4pnjbAcrqjveJqVti7huMXTLGuqU2uoihBw6mGqu_WSlOP2-XTEyRyvxbv2t-z9V6GPt1V9ceBukA0oGwtJqgD-q7NXFK8zhw7desI5PZMXf3nuVgbJ3xdvAlzkmm5f9RoqQS6_hqwPQEcclq1MEZ3yML5hc99TDtZWy9gGkhR0Hs3QJxxgP7bEqGFP-HjTPnJsrGaT6TjKP7qCxJlcFKLUr5AU_kxMULeUysWWtSGJ9mpxBvsyW1Juo\",\n" +
|
||||
" \"priv\": \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"\n" +
|
||||
"}";
|
||||
|
||||
String ML_DSA_87 = "{\n" +
|
||||
" \"kid\": \"tRn1JNIkgMsABVQBlXeDHxAIcclh-2IX0UdDEzPt5XU\",\n" +
|
||||
" \"kty\": \"AKP\",\n" +
|
||||
" \"alg\": \"ML-DSA-87\",\n" +
|
||||
" \"pub\": \"5F_8jMc9uIXcZi5ioYzY44AylxF_pWWIFKmFtf8dt7Roz8gruSnx2Gt37RT1rhamU2h3LOUZEkEBBeBFaXWukf22Q7US8STV5gvWi4x-Mf4Bx7DcZa5HBQHMVlpuHfz8_RJWVDPEr-3VEYIeLpYQxFJ14oNt7jXO1p1--mcv0eQxi-9etuiX6LRRqiAt7QQrKq73envj9pkUbaIpqL2z_6SWRFln51IXv7yQSPmVZEPYcx-DPrMN4Q2slv_-fPZeoERcPjHoYB4TO-ahAHZP4xluJncmRB8xdR-_mm9YgGRPTnJ15X3isPEF5NsFXVDdHJyTT931NbjeKLDHTARJ8iLNLtC7j7x3XM7oyUBmW0D3EvT34AdQ6eHkzZz_JdGUXD6bylPM1PEu7nWBhW69aPJoRZVuPnvrdh8P51vdMb_i-gGBEzl7OHvVnWKmi4r3-iRauTLmn3eOLO79ITBPu4CZ6hPY6lfBgTGXovda4lEHW1Ha04-FNmnp1fmKNlUJiUGZOhWUhg-6cf5TDuXCn1jyl4r2iMy3Wlg4o1nBEumOJahYOsjawfhh_Vjir7pd5aUuAgkE9bQrwIdONb788-YRloR2jzbgCPBHEhd86-YnYHOB5W6q7hYcFym43lHb3kdNSMxoJJ6icWK4eZPmDITtbMZCPLNnbZ61CyyrWjoEnvExOB1iP6b7y8nbHnzAJeoEGLna0sxszU6V-izsJP7spwMYp1Fxa3IT9j7b9lpjM4NX-Dj5TsBxgiwkhRJIiFEHs9HE6SRnjHYU6hrwOBBGGfKuNylAvs-mninLtf9sPiCke-Sk90usNMEzwApqcGrMxv_T2OT71pqZcE4Sg8hQ2MWNHldTzZWHuDxMNGy5pYE3IT7BCDTGat_iu1xQGo7y7K3Rtnej3xpt64br8HIsT1Aw4g-QGN1bb8U-6iT9kre1tAJf6umW0-SP1MZQ2C261-r5NmOWmFEvJiU9LvaEfIUY6FZcyaVJXG__V83nMjiCxUp9tHCrLa-P_Sv3lPp8aS2ef71TLuzB14gOLKCzIWEovii0qfHRUfrJeAiwvZi3tDphKprIZYEr_qxvR0YCd4QLUqOwh_kWynztwPdo6ivRnqIRVfhLSgTEAArSrgWHFU1WC8Ckd6T5MpqJhN0x6x8qBePZGHAdYwz8qa9h7wiNLFWBrLRj5DmQLl1CVxnpVrjW33MFso4P8n060N4ghdKSSZsZozkNQ5b7O6yajYy-rSp6QpD8msb8oEX5imFKRaOcviQ2D4TRT45HJxKs63Tb9FtT1JoORzfkdv_E1bL3zSR6oYbTt2Stnpz-7kVqc8KR2N45EkFKxDkRw3IXOte0cq81xoU87S_ntf4KiVZaszuqb2XN2SgxnXBl4EDnpehPmqkD92SAlLrQcTaxaSe47G28K-8MwoVt4eeVkj4UEsSfJN7rbCH2yKl2XJx5huDaS0xn2ODQyNRmgk-5I9hXMUiZDNLvEzx4zuyrcu2d0oXFo3ZoUtVFNCB__TQCf2x27ej9GjLXLDAEi7qnl9Xfb94n0IfeVyGte3-j6NP3DWv8OrLiUjNTaLv6Fay1yzfUaU6LI86-Jd6ckloiGhg7kE0_hd-ZKakZxU1vh0Vzc6DW7MFAPky75iCZlDXoBpZjTNGo5HR-mCW_ozblu60U9zZA8bn-voANuu_hYwxh-uY1sHTFZOqp2xicnnMChz_GTm1Je8XCkICYegeiHUryEHA6T6B_L9gW8S_R4ptMD0Sv6b1KHqqKeubwKltCWPUsr2En9iYypnz06DEL5Wp8KMhrLid2AMPpLI0j1CWGJExXHpBWjfIC8vbYH4YKVl-euRo8eDcuKosb5hxUGM9Jvy1siVXUpIKpkZt2YLP5pEBP_EVOoHPh5LJomrLMpORr1wBKbEkfom7npX1g817bK4IeYmZELI8zXUUtUkx3LgNTckwjx90Vt6oVXpFEICIUDF_LAVMUftzz6JUvbwOZo8iAZqcnVslAmRXeY_ZPp5eEHFfHlsb8VQ73Rd_p8XlFf5R1WuWiUGp2TzJ-VQvj3BTdQfOwSxR9RUk4xjqNabLqTFcQ7As246bHJXH6XVnd4DbEIDPfNa8FaWb_DNEgQAiXGqa6n7l7aFq5_6Kp0XeBBM0sOzJt4fy8JC6U0DEcMnWxKFDtMM7q06LubQYFCEEdQ5b1Qh2LbQZ898tegmeF--EZ4F4hvYebZPV8sM0ZcsKBXyCr585qs00PRxr0S6rReekGRBIvXzMojmid3dxc6DPpdV3x5zxlxaIBxO3i_6axknSSdxnS04_bemWqQ3CLf6mpSqfTIQJT1407GB4QINAAC9Ch3AXUR_n1jr64TGWzbIr8uDcnoVCJlOgmlXpmOwubigAzJattbWRi7k4QYBnA3_4QMjt73n2Co4-F_Qh4boYLpmwWG2SwcIw2PeXGr2LY2zwkPR4bcSyx1Z6UK5trQpWlpQCxgsvV_RvGzpN22RtHoihPH74K0cBIzCz7tK-jqeuWl1A7af7KmQ66fpRBr5ykTLOsa17WblkcIB_jDvqKfEcdxhPWJUwmOo4TIQS-xH8arLOy_NQFG2m14_yxwUemXC-QxLUYi6_FIcqwPBKjCdpQtadRdyftQSKO0SP-GxUvamMZzWI780rXuOBkq5kyYLy9QF9bf_-bL6QLpe1WMCQlOeXZaCPoncgYoT0WZ17jB52Xb2lPWsyXYK54npszkbKJ4OIqfvF8xqRXcVe22VwJuqT9Uy4-4KKQgQ7TXla7Gdm2H7mKl8YXQlsGCT2Ypc8O4t0Sfw7qYAuaDGf752Hbm3fl1bupcB2huIPlIaDP6IRR9XvTYIW2flbwYfhKLmoVKnG85uUi2qtqCjPOIuU3-peT0othfmwKQXaoOqO-V4r6wPL1VHxVFtIYmEdVt0RccUOvpOVR_OAHG9uHOzTmueK5557Qxp0ojtZCHyN-hgoMZJLrvdKkTCxPNo2-mZQbHoVh2FnThZ9JbO49dB8lKXP4_MU5xAnjXMgKXtbfI8w6ZWATE_XWgf2VQMUpGp4wpy44yWQTxHxh_4T9540BGwG0FU0bkgrwA_erseGZnepqdmz5_ScCs84O5Xr5MbYhJLCGGxY6O5GqS-ooB2w0Mt87KbbE4bpYje9CAHH8FX3pDrJyLsyasA3zxmk4OmGpG7Z70ofONJtHRe56R5287vFmuazEEutXn81kNzB-3aJT1ga3vnWZw4CSvFKoWYSA7auLgrHSHFZdITfOrgtmQmGbFhM9kSBdY1UCnpzf65oos3PZWRa2twfUxxLAnPNtrxpRGyvtsapw7ljUagZmuyh3hLCjhAxYmnoE1dbyIWvpCqSlEtVjL1yb_nuLEzgvmZuV02fHxGuWgHTOMVGXpf81Rce3eoBK3lapW1wkzezlk3tcA2bZOtA9qbxdsbVR37kemzQ9K1e3Y0OWhtSj\",\n" +
|
||||
" \"priv\": \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"\n" +
|
||||
"}";
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package org.keycloak.crypto.def.test;
|
||||
|
||||
import org.keycloak.common.util.Environment;
|
||||
import org.keycloak.jose.jwk.AKPJWKTest;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
|
||||
public class DefaultCryptoAKPJWKTest extends AKPJWKTest {
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
Assume.assumeFalse("Java is in FIPS mode. Skipping the test.", Environment.isJavaInFipsMode());
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user