[java-oidc-common] branch main updated: Improve readability of signature signing algorithm to credential lookup

Phil Smart philip.smart at jisc.ac.uk
Mon Feb 20 12:31:00 UTC 2023


This is an automated email from the git hooks/post-receive script.

philsmart pushed a commit to branch main
in repository java-oidc-common.

View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=8561fd7385e54bf6800dad9d63c58e02c760666c

The following commit(s) were added to refs/heads/main by this push:
     new 8561fd7  Improve readability of signature signing algorithm to credential lookup
8561fd7 is described below

commit 8561fd7385e54bf6800dad9d63c58e02c760666c
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Mon Feb 20 12:30:57 2023 +0000

    Improve readability of signature signing algorithm to credential lookup
---
 .../security/credential/JWACredentialSupport.java  | 23 ++++++--
 .../BasicSignatureSigningParametersResolver.java   | 69 +++++++++++++++-------
 2 files changed, 67 insertions(+), 25 deletions(-)

diff --git a/oidc-common-crypto-api/src/main/java/net/shibboleth/oidc/security/credential/JWACredentialSupport.java b/oidc-common-crypto-api/src/main/java/net/shibboleth/oidc/security/credential/JWACredentialSupport.java
index afc2d44..56a4d04 100644
--- a/oidc-common-crypto-api/src/main/java/net/shibboleth/oidc/security/credential/JWACredentialSupport.java
+++ b/oidc-common-crypto-api/src/main/java/net/shibboleth/oidc/security/credential/JWACredentialSupport.java
@@ -54,21 +54,34 @@ public final class JWACredentialSupport {
      * Is the EC key supplied compatible with the EC Curve required by the algorithm given.
      * 
      * @param key the key to check compatibility for
-     * @param algorithm the algorithm to match compatibility against
+     * @param algorithm the JWS algorithm to match compatibility against
      * 
      * @return true if compatible, false otherwise.
      * 
      * @throws JOSEException if there is an issue deriving algorithms
      */
     public static boolean keySupportsCurve(@Nonnull final ECKey key, 
-            @Nonnull @NotEmpty final String algorithm) throws JOSEException {
+            @Nonnull @NotEmpty final JWSAlgorithm algorithm) throws JOSEException {
         
         final JWSAlgorithm algCompatibleWithCredentialCurve = 
                 ECDSA.resolveAlgorithm(Curve.forECParameterSpec(key.getParams()));
         
-        final JWSAlgorithm alg = JWSAlgorithm.parse(algorithm);
-        
-        return algCompatibleWithCredentialCurve == alg;
+        return algCompatibleWithCredentialCurve == algorithm;
+    }
+    
+    /**
+     * Is the EC key supplied compatible with the EC Curve required by the algorithm given.
+     * 
+     * @param key the key to check compatibility for
+     * @param algorithm the string algorithm to match compatibility against
+     * 
+     * @return true if compatible, false otherwise.
+     * 
+     * @throws JOSEException if there is an issue deriving algorithms
+     */
+    public static boolean keySupportsCurve(@Nonnull final ECKey key, 
+            @Nonnull @NotEmpty final String algorithm) throws JOSEException {
+        return keySupportsCurve(key, JWSAlgorithm.parse(algorithm));
     }
 
 }
diff --git a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jose/impl/BasicSignatureSigningParametersResolver.java b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jose/impl/BasicSignatureSigningParametersResolver.java
index 0e33854..f9ebd62 100644
--- a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jose/impl/BasicSignatureSigningParametersResolver.java
+++ b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jose/impl/BasicSignatureSigningParametersResolver.java
@@ -19,6 +19,8 @@ package net.shibboleth.oidc.security.jose.impl;
 
 import java.security.Key;
 import java.security.interfaces.ECKey;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.RSAPrivateKey;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -37,6 +39,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWSAlgorithm;
 
 import net.shibboleth.oidc.security.CredentialConversionUtil;
 import net.shibboleth.oidc.security.credential.JWACredentialSupport;
@@ -205,16 +208,31 @@ public class BasicSignatureSigningParametersResolver
         final List<String> algorithms = getEffectiveSignatureAlgorithms(criteria, includeExcludePredicate);
         log.trace("Resolved effective signature algorithms: {}", algorithms);
         
+        findCompatibleAlgorithmAndCredential(algorithms, credentials, params);
+        
+    }
+    
+    /**
+     * Loop through the algorithms and find the first compatible credential. Add the compatible algorithm and credential
+     * to the signing parameters. 
+     * 
+     * @param algorithms the algorithms to find compatible from
+     * @param credentials the credentials to find compatibility with
+     * @param params the parameters to add a compatible algorithm and credential too.
+     */
+    protected void findCompatibleAlgorithmAndCredential(final List<String> algorithms, 
+            final List<Credential> credentials, @Nonnull final SignatureSigningParameters params) {
+        
         // Pick the first credential that matches one of the supported algorithms. Take algorithm priority.
         for (final String algorithm : algorithms) {
             for (final Credential credential : credentials) {
                 if (log.isTraceEnabled()) {
                     final Key key = CredentialSupport.extractSigningKey(credential);  
-                    log.trace("Evaluating credential '{}' of type '{}' against algorithm: {}",
+                    log.trace("Evaluating signing credential '{}' of type '{}' against algorithm: {}",
                             CredentialConversionUtil.resolveKid(credential), key != null ? key.getAlgorithm() : "n/a",
                                     algorithm);
                 }
-                if (credentialSupportsAlgorithm(credential, algorithm)) {
+                if (credentialSupportsSigningAlgorithm(credential, algorithm)) {
                     if (log.isTraceEnabled()) {
                         log.trace("Credential '{}' passed eval against algorithm: {}", 
                                 CredentialConversionUtil.resolveKid(credential), algorithm);
@@ -243,34 +261,45 @@ public class BasicSignatureSigningParametersResolver
     }
 
     /**
-     * Evaluate whether the specified credential is supported for use with the specified algorithm URI.
+     * Evaluate whether the specified credential is supported for use with the specified signing algorithm.
      * 
-     * <p>If EC key type, the curve is also checked against the algorithm for compatibility.</p>
+     * <p>First, the key type is checked against the algorithm family, then the algorithm and key length are checked. 
+     * If the key is an EC type, the curve is also checked against the algorithm.</p>
      * 
      * @param credential the credential to evaluate
      * @param algorithm the algorithm URI to evaluate
      * @return true if credential may be used with the supplied algorithm URI, false otherwise
      */
-    protected boolean credentialSupportsAlgorithm(@Nonnull final Credential credential, 
+    protected boolean credentialSupportsSigningAlgorithm(@Nonnull final Credential credential, 
             @Nonnull @NotEmpty final String algorithm) {
         
-        final boolean credentialSupportAlgorithm =  AlgorithmSupport.credentialSupportsAlgorithmForSigning(credential, 
-                getAlgorithmRegistry().get(algorithm));
-        
-        // Check private key only as for signing operation. Only check if initial compatibility is established
-        if (credentialSupportAlgorithm && JWACredentialSupport.isECKeyType(credential.getPrivateKey())) {            
-            try {
-                return JWACredentialSupport.keySupportsCurve((ECKey)credential.getPrivateKey(), algorithm);
-            } catch (final JOSEException e) {
-                log.trace("Algorithm '{}' and EC credential '{}' threw an error while checking for compatibility, "
-                        + "credential can not be used", algorithm, CredentialConversionUtil.resolveKid(credential), e);
-                return false;
-            }                    
+        try {
+            final JWSAlgorithm supportedAlgorithm = JWSAlgorithm.parse(algorithm);
+            final Key key = CredentialSupport.extractSigningKey(credential);
+            
+            boolean credSupportsAlgorithm = false;
+            if (JWSAlgorithm.Family.HMAC_SHA.contains(supportedAlgorithm) && credential.getSecretKey() != null) {
+                credSupportsAlgorithm = true;
+            } else if (JWSAlgorithm.Family.RSA.contains(supportedAlgorithm) 
+                    && credential.getPrivateKey() instanceof RSAPrivateKey) {
+                credSupportsAlgorithm = true;
+            } else if (JWSAlgorithm.Family.EC.contains(supportedAlgorithm)
+                    && credential.getPrivateKey() instanceof ECPrivateKey
+                    && JWACredentialSupport.keySupportsCurve((ECKey)credential.getPrivateKey(), supportedAlgorithm)) {
+                credSupportsAlgorithm = true;
+            }
+
+            return credSupportsAlgorithm && AlgorithmSupport.checkKeyAlgorithmAndLength(key, 
+                    getAlgorithmRegistry().get(algorithm));
+            
+        } catch (final JOSEException e) {
+            log.trace("Algorithm '{}' and EC credential '{}' threw an error while checking for compatibility, "
+                    + "credential can not be used", algorithm, 
+                    CredentialConversionUtil.resolveKid(credential), e);
+            return false;
         }  
-        return credentialSupportAlgorithm;
     }
-
-
+   
     /**
      * Get the effective list of signing credentials to consider.
      * 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list