JWSBuilder when used directly with AsymmetricSignatureSignerContext produces non compliant ECDSA signed JWT (#29333)
closes #29309 Signed-off-by: Francis Pouatcha <francis.pouatcha@adorsys.com>
This commit is contained in:
parent
5a68056f2a
commit
2683c0a7d1
6 changed files with 117 additions and 13 deletions
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.crypto;
|
||||||
|
|
||||||
|
import org.keycloak.common.VerificationException;
|
||||||
|
|
||||||
|
public class ECDSASignatureVerifierContext extends AsymmetricSignatureVerifierContext{
|
||||||
|
public ECDSASignatureVerifierContext(KeyWrapper key) {
|
||||||
|
super(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(byte[] data, byte[] signature) throws VerificationException {
|
||||||
|
try {
|
||||||
|
int expectedSize = ECDSAAlgorithm.getSignatureLength(getAlgorithm());
|
||||||
|
byte[] derSignature = ECDSAAlgorithm.concatenatedRSToASN1DER(signature, expectedSize);
|
||||||
|
return super.verify(data, derSignature);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new VerificationException("Verification failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,16 +30,18 @@ import java.security.spec.ECPublicKeySpec;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.ClassRule;
|
||||||
import org.keycloak.common.util.Base64Url;
|
import org.keycloak.common.util.Base64Url;
|
||||||
import org.keycloak.common.util.KeyUtils;
|
import org.keycloak.common.util.KeyUtils;
|
||||||
import org.keycloak.crypto.AsymmetricSignatureSignerContext;
|
import org.keycloak.crypto.ECDSASignatureSignerContext;
|
||||||
import org.keycloak.crypto.AsymmetricSignatureVerifierContext;
|
import org.keycloak.crypto.ECDSASignatureVerifierContext;
|
||||||
import org.keycloak.crypto.KeyUse;
|
import org.keycloak.crypto.KeyUse;
|
||||||
import org.keycloak.crypto.KeyWrapper;
|
import org.keycloak.crypto.KeyWrapper;
|
||||||
import org.keycloak.crypto.SignatureSignerContext;
|
import org.keycloak.crypto.SignatureSignerContext;
|
||||||
import org.keycloak.crypto.SignatureVerifierContext;
|
import org.keycloak.crypto.SignatureVerifierContext;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import org.keycloak.rule.CryptoInitRule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Import test-settings from:
|
* Import test-settings from:
|
||||||
|
@ -208,7 +210,7 @@ public class TestSettings {
|
||||||
keyWrapper.setType(keyPair.getPublic().getAlgorithm());
|
keyWrapper.setType(keyPair.getPublic().getAlgorithm());
|
||||||
keyWrapper.setUse(KeyUse.SIG);
|
keyWrapper.setUse(KeyUse.SIG);
|
||||||
keyWrapper.setKid(kid);
|
keyWrapper.setKid(kid);
|
||||||
return new AsymmetricSignatureSignerContext(keyWrapper);
|
return new ECDSASignatureSignerContext(keyWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SignatureVerifierContext getSignatureVerifierContext(PublicKey publicKey, String algorithm,
|
private static SignatureVerifierContext getSignatureVerifierContext(PublicKey publicKey, String algorithm,
|
||||||
|
@ -219,7 +221,7 @@ public class TestSettings {
|
||||||
keyWrapper.setType(publicKey.getAlgorithm());
|
keyWrapper.setType(publicKey.getAlgorithm());
|
||||||
keyWrapper.setUse(KeyUse.SIG);
|
keyWrapper.setUse(KeyUse.SIG);
|
||||||
keyWrapper.setKid(kid);
|
keyWrapper.setKid(kid);
|
||||||
return new AsymmetricSignatureVerifierContext(keyWrapper);
|
return new ECDSASignatureVerifierContext(keyWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<String, String> ECDSA_CURVE_2_SPECS_NAMES = new HashMap<>();
|
private static final Map<String, String> ECDSA_CURVE_2_SPECS_NAMES = new HashMap<>();
|
||||||
|
|
|
@ -16,13 +16,12 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.sdjwt.sdjwtvp;
|
package org.keycloak.sdjwt.sdjwtvp;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import static org.junit.Assert.assertTrue;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import org.junit.ClassRule;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.common.VerificationException;
|
import org.keycloak.common.VerificationException;
|
||||||
|
import org.keycloak.rule.CryptoInitRule;
|
||||||
import org.keycloak.sdjwt.DisclosureSpec;
|
import org.keycloak.sdjwt.DisclosureSpec;
|
||||||
import org.keycloak.sdjwt.IssuerSignedJWT;
|
import org.keycloak.sdjwt.IssuerSignedJWT;
|
||||||
import org.keycloak.sdjwt.SdJwt;
|
import org.keycloak.sdjwt.SdJwt;
|
||||||
|
@ -30,13 +29,17 @@ import org.keycloak.sdjwt.TestSettings;
|
||||||
import org.keycloak.sdjwt.TestUtils;
|
import org.keycloak.sdjwt.TestUtils;
|
||||||
import org.keycloak.sdjwt.vp.SdJwtVP;
|
import org.keycloak.sdjwt.vp.SdJwtVP;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import java.util.Arrays;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:francis.pouatcha@adorsys.com">Francis Pouatcha</a>
|
* @author <a href="mailto:francis.pouatcha@adorsys.com">Francis Pouatcha</a>
|
||||||
*/
|
*/
|
||||||
public class SdJwtVPTest {
|
public abstract class SdJwtVPTest {
|
||||||
|
@ClassRule
|
||||||
|
public static CryptoInitRule cryptoInitRule = new CryptoInitRule();
|
||||||
// Additional tests can be written to cover edge cases, error conditions,
|
// Additional tests can be written to cover edge cases, error conditions,
|
||||||
// and any other functionality specific to the SdJwt class.
|
// and any other functionality specific to the SdJwt class.
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
eyJhbGciOiJFUzI1NiIsInR5cCIgOiAidmMrc2Qtand0Iiwia2lkIiA6ICJkb2Mtc2lnbmVyLTA1LTI1LTIwMjIifQ.eyJfc2QiOlsiSHZyS1g2ZlBWMHY5S195Q1ZGQmlMRkhzTWF4Y0RfMTE0RW02VlQ4eDFsZyJdLCJfc2RfYWxnIjoic2hhLTI1NiIsInN1YiI6IjZjNWMwYTQ5LWI1ODktNDMxZC1iYWU3LTIxOTEyMmE5ZWMyYyIsImlzcyI6Imh0dHBzOi8vaXNzdWVyLmV4YW1wbGUuY29tIiwiaWF0IjoxNjgzMDAwMDAwLCJleHAiOjE4ODMwMDAwMDB9.MEQCICde3GkeuNWixUiD3zk5F9OMGD2HJW6Lmo4waWkVXDddAiByEPMrOn8aE9Tf33_J3SIiVBEhQNthU58O7D0Y1Xywcg~WyIyR0xDNDJzS1F2ZUNmR2ZyeU5STjl3IiwgInN0cmVldF9hZGRyZXNzIiwgIlNjaHVsc3RyLiAxMiJd~WyJlbHVWNU9nM2dTTklJOEVZbnN4QV9BIiwgImxvY2FsaXR5IiwgIlNjaHVscGZvcnRhIl0~WyI2SWo3dE0tYTVpVlBHYm9TNXRtdlZBIiwgInJlZ2lvbiIsICJTYWNoc2VuLUFuaGFsdCJd~WyJlSThaV205UW5LUHBOUGVOZW5IZGhRIiwgImNvdW50cnkiLCAiREUiXQ~WyJRZ19PNjR6cUF4ZTQxMmExMDhpcm9BIiwgImFkZHJlc3MiLCB7Il9zZCI6IFsiNnZoOWJxLXpTNEdLTV83R3BnZ1ZiWXp6dTZvT0dYcm1OVkdQSFA3NVVkMCIsICI5Z2pWdVh0ZEZST0NnUnJ0TmNHVVhtRjY1cmRlemlfNkVyX2o3NmttWXlNIiwgIktVUkRQaDRaQzE5LTN0aXotRGYzOVY4ZWlkeTFvVjNhM0gxRGEyTjBnODgiLCAiV045cjlkQ0JKOEhUQ3NTMmpLQVN4VGpFeVc1bTV4NjVfWl8ycm8yamZYTSJdfV0~
|
eyJraWQiOiJkb2Mtc2lnbmVyLTA1LTI1LTIwMjIiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFUzI1NiJ9.eyJfc2QiOlsiSHZyS1g2ZlBWMHY5S195Q1ZGQmlMRkhzTWF4Y0RfMTE0RW02VlQ4eDFsZyJdLCJfc2RfYWxnIjoic2hhLTI1NiIsInN1YiI6IjZjNWMwYTQ5LWI1ODktNDMxZC1iYWU3LTIxOTEyMmE5ZWMyYyIsImlzcyI6Imh0dHBzOi8vaXNzdWVyLmV4YW1wbGUuY29tIiwiaWF0IjoxNjgzMDAwMDAwLCJleHAiOjE4ODMwMDAwMDB9.Bhhy9eDenyBCsh9F064pxs5SK0Tbfc0o4xXlzmYv50qODKShpfsiC8__W1SXrF687JsbXmbD7VA5Db7iMoPwbg~WyIyR0xDNDJzS1F2ZUNmR2ZyeU5STjl3IiwgInN0cmVldF9hZGRyZXNzIiwgIlNjaHVsc3RyLiAxMiJd~WyJlbHVWNU9nM2dTTklJOEVZbnN4QV9BIiwgImxvY2FsaXR5IiwgIlNjaHVscGZvcnRhIl0~WyI2SWo3dE0tYTVpVlBHYm9TNXRtdlZBIiwgInJlZ2lvbiIsICJTYWNoc2VuLUFuaGFsdCJd~WyJlSThaV205UW5LUHBOUGVOZW5IZGhRIiwgImNvdW50cnkiLCAiREUiXQ~WyJRZ19PNjR6cUF4ZTQxMmExMDhpcm9BIiwgImFkZHJlc3MiLCB7Il9zZCI6IFsiNnZoOWJxLXpTNEdLTV83R3BnZ1ZiWXp6dTZvT0dYcm1OVkdQSFA3NVVkMCIsICI5Z2pWdVh0ZEZST0NnUnJ0TmNHVVhtRjY1cmRlemlfNkVyX2o3NmttWXlNIiwgIktVUkRQaDRaQzE5LTN0aXotRGYzOVY4ZWlkeTFvVjNhM0gxRGEyTjBnODgiLCAiV045cjlkQ0JKOEhUQ3NTMmpLQVN4VGpFeVc1bTV4NjVfWl8ycm8yamZYTSJdfV0~
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.crypto.def.test;
|
||||||
|
|
||||||
|
import org.junit.Assume;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.keycloak.common.util.Environment;
|
||||||
|
import org.keycloak.sdjwt.sdjwtvp.SdJwtVPTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test with default security provider and non-fips bouncycastle
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:francis.pouatcha@adorsys.com">Francis Pouatcha</a>
|
||||||
|
*/
|
||||||
|
public class DefaultCryptoSdJwtVPTest extends SdJwtVPTest {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
// Run this test just if java is not in FIPS mode
|
||||||
|
Assume.assumeFalse("Java is in FIPS mode. Skipping the test.", Environment.isJavaInFipsMode());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.crypto.elytron.test;
|
||||||
|
|
||||||
|
import org.keycloak.sdjwt.sdjwtvp.SdJwtVPTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test with Elytron provider
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:francis.pouatcha@adorsys.com">Francis Pouatcha</a>
|
||||||
|
*/
|
||||||
|
public class ElytronCryptoSdJwtVPTest extends SdJwtVPTest {
|
||||||
|
}
|
Loading…
Reference in a new issue