/** * Turn a KeyInfo into an EncryptedKey collection. * * @param keyInfo KeyInfo to process * @param limit depth of references to follow * @return encrypted keys */ @Nonnull protected Iterable<EncryptedKey> resolveKeyInfo(@Nullable final KeyInfo keyInfo, int limit) { List<EncryptedKey> resolvedEncKeys = new ArrayList<>(); if (keyInfo == null) { return resolvedEncKeys; } // The first time in, we don't directly resolve any keys, only references. // After that, we always start by looking inline. if (limit < depthLimit) { for (final EncryptedKey encKey : keyInfo.getEncryptedKeys()) { if (matchRecipient(encKey.getRecipient())) { resolvedEncKeys.add(encKey); } } } if (limit == 0) { log.info("Reached depth limit for KeyInfoReferences"); } else { for (final KeyInfoReference ref : keyInfo.getKeyInfoReferences()) { for (final EncryptedKey encKey : resolveKeyInfo(dereferenceURI(ref), limit - 1)) { resolvedEncKeys.add(encKey); } } } return resolvedEncKeys; }
/** * Checks whether the supplied public key matches one of the keys in the given KeyInfo. * * <p>Evaluates both {@link KeyValue} and {@link DEREncodedKeyValue} children of the KeyInfo. * * <p>Matches are performed using Java <code>equals()</code> against {@link PublicKey}s decoded * from the KeyInfo data. * * @param key public key presenter of the assertion * @param keyInfo key info from subject confirmation of the assertion * @return true if the public key in the certificate matches one of the key values in the key * info, false otherwise * @throws AssertionValidationException thrown if there is a problem matching the key value */ protected boolean matchesKeyValue(@Nullable final PublicKey key, @Nonnull final KeyInfo keyInfo) throws AssertionValidationException { if (key == null) { log.debug("Presenter PublicKey was null, skipping KeyValue match"); return false; } if (matchesKeyValue(key, keyInfo.getKeyValues())) { return true; } if (matchesDEREncodedKeyValue(key, keyInfo.getDEREncodedKeyValues())) { return true; } log.debug( "Failed to match either a KeyInfo KeyValue or DEREncodedKeyValue against supplied PublicKey param"); return false; }
/** * Checks whether the presenter's certificate matches a certificate described by the X509Data * within the KeyInfo. * * <p>Matches are performed using Java <code>equals()</code> against {@link X509Certificate}s * decoded from the KeyInfo data. * * @param cert certificate of the presenter of the assertion * @param keyInfo key info from subject confirmation of the assertion * @return true if the presenter's certificate matches the key described by an X509Data within the * KeyInfo, false otherwise. * @throws AssertionValidationException thrown if there is a problem matching the certificate */ protected boolean matchesX509Certificate( @Nullable final X509Certificate cert, @Nonnull final KeyInfo keyInfo) throws AssertionValidationException { if (cert == null) { log.debug("Presenter X509Certificate was null, skipping certificate match"); return false; } List<X509Data> x509Datas = keyInfo.getX509Datas(); if (x509Datas == null || x509Datas.isEmpty()) { log.debug("KeyInfo contained no X509Data children, skipping certificate match"); return false; } log.debug("Attempting to match KeyInfo X509Data to supplied X509Certificate param"); List<org.opensaml.xmlsec.signature.X509Certificate> xmlCertificates; for (X509Data data : x509Datas) { xmlCertificates = data.getX509Certificates(); if (xmlCertificates == null || xmlCertificates.isEmpty()) { log.debug("X509Data contained no X509Certificate children, skipping certificate match"); continue; } for (org.opensaml.xmlsec.signature.X509Certificate xmlCertificate : xmlCertificates) { try { X509Certificate kiCert = KeyInfoSupport.getCertificate(xmlCertificate); if (Objects.equals(cert, kiCert)) { log.debug("Matched X509Certificate"); return true; } } catch (CertificateException e) { log.warn("KeyInfo contained Certificate value that can not be parsed", e); } } } log.debug("Failed to match a KeyInfo X509Data against supplied X509Certificate param"); return false; }