davidkarlsen commented on a change in pull request #462: Httpsig URL: https://github.com/apache/cxf/pull/462#discussion_r226867333
########## File path: rt/rs/security/http-signature/src/main/java/org/apache/cxf/rs/security/httpsignature/MessageVerifier.java ########## @@ -0,0 +1,212 @@ +package org.apache.cxf.rs.security.httpsignature; + +import org.apache.cxf.common.logging.LogUtils; +import org.tomitribe.auth.signatures.Signature; +import org.tomitribe.auth.signatures.Verifier; + +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; +import java.util.*; +import java.util.logging.Logger; + +public class MessageVerifier { + private ExceptionHandler exceptionHandler; + + protected static final Logger LOG = LogUtils.getL7dLogger(MessageVerifier.class); + + public MessageVerifier(boolean verifyMessageBody) { + setExceptionHandler(null); + setSecurityProvider(null); + setAlgorithmProvider(null); + this.verifyMessageBody = verifyMessageBody; + } + + public MessageVerifier(PublicKeyProvider publicKeyProvider, + ExceptionHandler exceptionHandler, + SecurityProvider securityProvider, + AlgorithmProvider algorithmProvider, + boolean verifyMessageBody) + { + Objects.requireNonNull(publicKeyProvider, "Public key provider cannot be null"); + this.publicKeyProvider = publicKeyProvider; + this.exceptionHandler = exceptionHandler; + this.securityProvider = securityProvider; + this.algorithmProvider = algorithmProvider; + this.verifyMessageBody = verifyMessageBody; + } + + private PublicKeyProvider publicKeyProvider; + + private SecurityProvider securityProvider; + + private AlgorithmProvider algorithmProvider; + + private boolean verifyMessageBody; + + public void setSecurityProvider(SecurityProvider securityProvider) { + if (securityProvider != null) { + this.securityProvider = securityProvider; + } else { + this.securityProvider = (keyId) -> Security.getProvider("SunRsaSign"); + } + } + + public void setPublicKeyProvider(PublicKeyProvider publicKeyProvider) { + this.publicKeyProvider = publicKeyProvider; + } + + public void setAlgorithmProvider(AlgorithmProvider algorithmProvider) { + if (algorithmProvider != null) { + this.algorithmProvider = algorithmProvider; + } else { + this.algorithmProvider = (keyId) -> "rsa-sha256"; + } + } + + public ExceptionHandler getExceptionHandler() { + return exceptionHandler; + } + + public void setExceptionHandler(ExceptionHandler exceptionHandler) { + if (exceptionHandler != null) { + this.exceptionHandler = exceptionHandler; + } else { + this.exceptionHandler = (exception, type) -> new SignatureException("exception of type: " + type + " occurred"); + } + } + + public void verifyMessage(Map<String, List<String>> messageHeaders, String messageBody) { + if (verifyMessageBody) { + inspectDigest(messageBody, messageHeaders); + } + verifyMessage(messageHeaders); + } + + public void verifyMessage(Map<String, List<String>> messageHeaders) { + inspectIllegalState(); + + inspectMissingSignatureHeader(messageHeaders); + + inspectMultipleSignatureHeaders(messageHeaders); + + Signature signature = extractSignature(messageHeaders.get("Signature").get(0)); + + String providedAlgorithm = algorithmProvider.getAlgorithmName(signature.getKeyId()); + Objects.requireNonNull(providedAlgorithm, "provided algorithm is null"); + + String signatureAlgorithm = signature.getAlgorithm().toString(); + if (!providedAlgorithm.equals(signatureAlgorithm)) { + throw exceptionHandler.handle(new SignatureException("algorithm from header and provided are different"), + SignatureExceptionType.DIFFERENT_ALGORITHMS); + } + + // Replace the algorithm provided by the headers with the algorithm given by the algorithm provider + Signature newSignature = + Signature.fromString(replaceAlgorithm(signature.toString(), signatureAlgorithm, providedAlgorithm)); + + Key key = publicKeyProvider.getKey(signature.getKeyId()); + Objects.requireNonNull(key, "provided public key is null"); + + runVerifier(messageHeaders, key, newSignature); + } + + private String replaceAlgorithm(String signatureString, String oldAlgorithm, String newAlgorithm) { + return signatureString.replaceFirst("algorithm=\"" + oldAlgorithm, "algorithm=\"" + newAlgorithm); + } + + private void inspectIllegalState() { + if (publicKeyProvider == null) { + throw new IllegalStateException("public key provider is not set"); + } + if (securityProvider == null) { + throw new IllegalStateException("security provider is not set"); + } + if (algorithmProvider == null) { + throw new IllegalStateException("algorithm provider is not set"); + } + } + + private void inspectDigest(String messageBody, Map<String, List<String>> responseHeaders) { + LOG.info("Starting digest verification"); Review comment: reduce verbosity to debug ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services