[java-plugin-shibd-oidc] 08/11: Add symmetric key tests
Codeberg
noreply at shibboleth.net
Wed Oct 7 14:29:13 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch dev/JSHIBDOIDC-31-cred-resolver
in repository java-plugin-shibd-oidc.
View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd-oidc/commit/ed46836be7cae94f349b197f0d85fe848af7fa6a
commit ed46836be7cae94f349b197f0d85fe848af7fa6a
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Mon Oct 5 10:34:54 2026 +0100
Add symmetric key tests
---
.../JWKCredentialStorageServiceResolverTest.java | 88 ++++++++++++++++++++--
1 file changed, 83 insertions(+), 5 deletions(-)
diff --git a/sp-oidc-impl/src/test/java/net/shibboleth/sp/oidc/profile/credential/impl/JWKCredentialStorageServiceResolverTest.java b/sp-oidc-impl/src/test/java/net/shibboleth/sp/oidc/profile/credential/impl/JWKCredentialStorageServiceResolverTest.java
index 987fa60..fd8681b 100644
--- a/sp-oidc-impl/src/test/java/net/shibboleth/sp/oidc/profile/credential/impl/JWKCredentialStorageServiceResolverTest.java
+++ b/sp-oidc-impl/src/test/java/net/shibboleth/sp/oidc/profile/credential/impl/JWKCredentialStorageServiceResolverTest.java
@@ -14,6 +14,10 @@
package net.shibboleth.sp.oidc.profile.credential.impl;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryNotEmptyException;
@@ -22,12 +26,15 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
+import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.time.Duration;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.security.credential.UsageType;
@@ -38,7 +45,10 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import com.nimbusds.jose.Algorithm;
+import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.KeyUse;
+import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
@@ -107,8 +117,8 @@ public class JWKCredentialStorageServiceResolverTest {
Files.createDirectories(Path.of(testRoot.toString(), "agents", "sp.example.org"));
// Generate key for testing.
- generateJWK(Path.of(testRoot.toString(), "agents", "localhost", "sp-signing.jwk"), KeyUse.SIGNATURE);
- generateJWK(
+ generateAsymmetricKeyJWK(Path.of(testRoot.toString(), "agents", "localhost", "sp-signing.jwk"), KeyUse.SIGNATURE);
+ generateAsymmetricKeyJWK(
Path.of(testRoot.toString(), "agents", "sp.example.org", "sp-encryption.jwk"),KeyUse.ENCRYPTION);
final FilesystemStorageService storage = new FilesystemStorageService();
@@ -165,7 +175,7 @@ public class JWKCredentialStorageServiceResolverTest {
Files.createDirectories(directory);
// Generate key for testing.
- generateJWK(Path.of(directory.toString(), "sp-signing.jwk"), KeyUse.SIGNATURE);
+ generateAsymmetricKeyJWK(Path.of(directory.toString(), "sp-signing.jwk"), KeyUse.SIGNATURE);
final FilesystemStorageService storage = new FilesystemStorageService();
storage.setId("test");
@@ -193,6 +203,53 @@ public class JWKCredentialStorageServiceResolverTest {
Assert.assertTrue(KeySupport.matchKeyPair(pubKey, privKey));
}
+ /* Test credential lookup for a given Agent (likely OIDC client, and OP) pulling out a symmetric key.*/
+ @Test
+ public void testSymmetricKeyStorageByAgentAndRelyingParty() throws Exception {
+
+ // Prep directories for agents.
+ // e73fd7b4d5d40e19ecd14b919b23fbd8ea99b748 sha-1 of https://op.example.org/
+ final Path directory = Path.of(testRoot.toString(), "agents", "rp.example.org","e73fd7b4d5d40e19ecd14b919b23fbd8ea99b748");
+ Files.createDirectories(directory);
+
+ // Generate key for testing.
+ final KeyGenerator generator = KeyGenerator.getInstance("HmacSHA256");
+ generator.init(256);
+ final SecretKey generatedSecretKey = generator.generateKey();
+ generateSymmetricKeyJWK(Path.of(directory.toString(), "sp-signing.jwk"), KeyUse.SIGNATURE,
+ generatedSecretKey, JWSAlgorithm.HS256);
+
+ final FilesystemStorageService storage = new FilesystemStorageService();
+ storage.setId("test");
+ storage.setReadOnly(true);
+ storage.setStorageBase(testRoot.toString());
+ storage.initialize();
+
+ final JWKCredentialStorageServiceResolver resolver = new JWKCredentialStorageServiceResolver();
+ resolver.setId("test");
+ resolver.setStorageService(storage);
+ resolver.setVelocityEngine(VelocityEngine.newVelocityEngine());
+ resolver.setContextTemplate("agents/$agentID/$transformedRelyingPartyID");
+ resolver.initialize();
+
+ final JWKCredential credential = (JWKCredential) resolver.resolveSingle(
+ buildCriteriaSet("rp.example.org", "default", "https://op.example.org/", UsageType.SIGNING));
+ assert credential != null;
+
+ final PrivateKey privKey = credential.getPrivateKey();
+ assertNull(privKey);
+
+ final PublicKey pubKey = credential.getPublicKey();
+ assertNull(pubKey);
+
+ final SecretKey secretKey = credential.getSecretKey();
+ assertNotNull(secretKey);
+
+ // Could compare with Arrays.equals. MessageDigest is better for sensitive operations, although this test is not
+ assertTrue(MessageDigest.isEqual(secretKey.getEncoded(), generatedSecretKey.getEncoded()));
+
+ }
+
@Test
public void testCaching() throws Exception {
// Prep directories for agent.
@@ -200,7 +257,7 @@ public class JWKCredentialStorageServiceResolverTest {
// Generate JWK for testing.
final var jwkFile = Path.of(testRoot.toString(), "agents", "localhost", "override", "sp-signing.jwk");
- generateJWK(jwkFile,KeyUse.SIGNATURE);
+ generateAsymmetricKeyJWK(jwkFile,KeyUse.SIGNATURE);
final FilesystemStorageService storage = new FilesystemStorageService();
storage.setId("test");
@@ -249,7 +306,7 @@ public class JWKCredentialStorageServiceResolverTest {
* @param use the KeyUse
* @throws Exception on error
*/
- private void generateJWK(@Nonnull final Path key, @Nonnull final KeyUse use) throws Exception {
+ private void generateAsymmetricKeyJWK(@Nonnull final Path key, @Nonnull final KeyUse use) throws Exception {
final RSAKey jwk = new RSAKeyGenerator(2048)
.keyID("test")
.keyUse(use)
@@ -258,6 +315,27 @@ public class JWKCredentialStorageServiceResolverTest {
Files.writeString(key, jwk.toJSONString(), StandardCharsets.UTF_8);
}
+ /**
+ * Generate a Symmetric JWK, of the 'octet' type. Save the JWK to file.
+ *
+ * @param keyPath the path where the key will be written
+ * @param use the KeyUse
+ * @param secretKey the secret key to use
+ * @param alg the algorithm
+ * @throws Exception on error
+ */
+ private void generateSymmetricKeyJWK(@Nonnull final Path keyPath, @Nonnull final KeyUse use,
+ final SecretKey secretKey, final Algorithm alg) throws Exception {
+
+ final OctetSequenceKey key = new OctetSequenceKey.Builder(secretKey)
+ .keyUse(use)
+ .algorithm(alg)
+ .keyID("test")
+ .build();
+
+ Files.writeString(keyPath, key.toJSONString(), StandardCharsets.UTF_8);
+ }
+
/**
* Builds a set of criteria for the resolver.
*
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list