diff options
Diffstat (limited to 'eaaf_core_utils/src/main/java')
| -rw-r--r-- | eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/JoseUtils.java | 138 | 
1 files changed, 93 insertions, 45 deletions
| diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/JoseUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/JoseUtils.java index a67f3523..f3c8588d 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/JoseUtils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/JoseUtils.java @@ -4,6 +4,7 @@ import java.io.IOException;  import java.security.Key;  import java.security.KeyFactory;  import java.security.KeyStore; +import java.security.MessageDigest;  import java.security.NoSuchAlgorithmException;  import java.security.Provider;  import java.security.PublicKey; @@ -16,6 +17,7 @@ import java.security.spec.InvalidKeySpecException;  import java.security.spec.PKCS8EncodedKeySpec;  import java.security.spec.X509EncodedKeySpec;  import java.util.Collections; +import java.util.Date;  import java.util.List;  import java.util.Map;  import java.util.Map.Entry; @@ -203,7 +205,7 @@ public class JoseUtils {    }    /** -   * Verify a JOSE signature. +   * Verify a JOSE signature without signing certificate validation.     *     * @param serializedContent Serialized content that should be verified     * @param trustedCerts      Trusted certificates that should be used for @@ -216,6 +218,29 @@ public class JoseUtils {    public static JwsResult validateSignature(@Nonnull final String serializedContent,        @Nonnull final List<X509Certificate> trustedCerts, @Nonnull final AlgorithmConstraints constraints)        throws JoseException, IOException { +    return validateSignature(serializedContent, trustedCerts, constraints, false); + +  } + +  /** +   * Verify a JOSE signature. +   * +   * @param serializedContent              Serialized content that should be +   *                                       verified +   * @param trustedCerts                   Trusted certificates that should be +   *                                       used for verification +   * @param constraints                    {@link AlgorithmConstraints} for +   *                                       verification +   * @param needValidateSigningCertificate If <code>true</code> then the signing +   *                                       certificate itself must be valid +   * @return {@link JwsResult} object +   * @throws JoseException In case of a signature verification error +   * @throws IOException   In case of a general error +   */ +  public static JwsResult validateSignature(@Nonnull final String serializedContent, +      @Nonnull final List<X509Certificate> trustedCerts, @Nonnull final AlgorithmConstraints constraints, +      final boolean needValidateSigningCertificate) +      throws JoseException, IOException {      final JsonWebSignature jws = new JsonWebSignature();      // set payload      jws.setCompactSerialization(serializedContent); @@ -224,66 +249,30 @@ public class JoseUtils {      jws.setAlgorithmConstraints(constraints);      // load signinc certs -    Key selectedKey = null; -    final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); -    final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); -    if (x5cCerts != null) { -      log.debug("Found x509 certificate in JOSE header ... "); -      log.trace("Sorting received X509 certificates ... "); -      final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); - -       -       -      if (trustedCerts.contains(sortedX5cCerts.get(0))) { -        selectedKey = sortedX5cCerts.get(0).getPublicKey(); - -      } else { -        log.info("Can NOT find JOSE certificate in truststore."); -        if (log.isDebugEnabled()) { -          try { -            log.debug("Cert: {}", Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); - -          } catch (final CertificateEncodingException e) { -            log.warn("Can not create DEBUG output", e); - -          } -        } -      } - -    } else if (StringUtils.isNotEmpty(x5t256)) { -      log.debug("Found x5t256 fingerprint in JOSE header .... "); -      final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver( -          trustedCerts); -      selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); - -    } else { -      throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint"); +    Key selectedKey = selectSigningKey(jws, trustedCerts); +    // validate signing-certificate constrains +    if (needValidateSigningCertificate) { +      validateSigningCertificate(selectedKey, trustedCerts);      } -    if (selectedKey == null) { -      throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED"); - -    } -     -    //set BouncyCastleProvider as default provider +    // set BouncyCastleProvider as default provider      final ProviderContext providerCtx = new ProviderContext();      providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME);      jws.setProviderContext(providerCtx); -     +      // set verification key      jws.setKey(convertToBcKeyIfRequired(selectedKey)); -      +      // load payLoad      return new JwsResult(          jws.verifySignature(),          jws.getUnverifiedPayload(),          jws.getHeaders(), -        x5cCerts); +        jws.getCertificateChainHeaderValue());    } -      /**     * Convert an ECC public-key into BouncyCastle implementation.     *   @@ -357,6 +346,65 @@ public class JoseUtils {    } +  private static void validateSigningCertificate(Key selectedKey, List<X509Certificate> trustedCerts) +      throws JoseException { +    X509Certificate signingCert = trustedCerts.stream() +        .filter(el -> MessageDigest.isEqual(el.getPublicKey().getEncoded(), selectedKey.getEncoded())) +        .findFirst() +        .get(); + +    Date now = new Date(); +    if (now.before(signingCert.getNotBefore()) || now.after(signingCert.getNotAfter())) { +      log.error("JOSE signing-certificate is not valid. Now: {}, Before: {}, After: {}", +          now, signingCert.getNotBefore(), signingCert.getNotAfter()); +      throw new JoseException("JOSE signing-certificate is not in validity periode"); + +    } else { +      log.debug("JOSE signing-certificate is in validity periode"); + +    } +  } + +  private static Key selectSigningKey(JsonWebSignature jws, List<X509Certificate> trustedCerts) +      throws JoseException { +    final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); +    final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); +    if (x5cCerts != null) { +      log.debug("Found x509 certificate in JOSE header ... "); +      log.trace("Sorting received X509 certificates ... "); +      final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); + +      if (trustedCerts.contains(sortedX5cCerts.get(0))) { +        return sortedX5cCerts.get(0).getPublicKey(); + +      } else { +        log.info("Can NOT find JOSE certificate in truststore."); +        if (log.isDebugEnabled()) { +          try { +            log.debug("Cert: {}", Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); + +          } catch (final CertificateEncodingException e) { +            log.warn("Can not create DEBUG output", e); + +          } +        } +      } + +    } else if (StringUtils.isNotEmpty(x5t256)) { +      log.debug("Found x5t256 fingerprint in JOSE header .... "); +      final X509VerificationKeyResolver x509VerificationKeyResolver = +          new X509VerificationKeyResolver(trustedCerts); +      return x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); + +    } else { +      throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint"); + +    } + +    throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED"); + +  } +    private JoseUtils() {    } | 
