summaryrefslogtreecommitdiff
path: root/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/JoseUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/JoseUtils.java')
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/JoseUtils.java138
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() {
}