protected abstract SignatureVerifier newSignatureVerifier()

in src/main/java/org/apache/xml/security/stax/impl/processor/input/AbstractSignatureInputHandler.java [245:418]


    protected abstract SignatureVerifier newSignatureVerifier(InputProcessorChain inputProcessorChain,
                                                              XMLSecurityProperties securityProperties,
                                                              final SignatureType signatureType) throws XMLSecurityException;

/*
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature-1022834285">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <ds:Reference URI="#id-1612925417">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <ds:DigestValue>cy/khx5N6UobCJ1EbX+qnrGID2U=</ds:DigestValue>
            </ds:Reference>
            <ds:Reference URI="#Timestamp-1106985890">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <ds:DigestValue>+p5YRII6uvUdsJ7XLKkWx1CBewE=</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
            Izg1FlI9oa4gOon2vTXi7V0EpiyCUazECVGYflbXq7/3GF8ThKGDMpush/fo1I2NVjEFTfmT2WP/
            +ZG5N2jASFptrcGbsqmuLE5JbxUP1TVKb9SigKYcOQJJ8klzmVfPXnSiRZmIU+DUT2UXopWnGNFL
            TwY0Uxja4ZuI6U8m8Tg=
        </ds:SignatureValue>
        <ds:KeyInfo Id="KeyId-1043455692">
            <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
            xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-1008354042">
                <wsse:Reference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                URI="#CertId-3458500" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
            </wsse:SecurityTokenReference>
        </ds:KeyInfo>
    </ds:Signature>
     */

    public abstract class SignatureVerifier {

        private final SignatureType signatureType;
        private final InboundSecurityToken inboundSecurityToken;

        private SignerOutputStream signerOutputStream;
        private OutputStream bufferedSignerOutputStream;
        private Transformer transformer;

        public SignatureVerifier(SignatureType signatureType, InboundSecurityContext inboundSecurityContext,
                                 XMLSecurityProperties securityProperties) throws XMLSecurityException {
            this.signatureType = signatureType;

            InboundSecurityToken inboundSecurityToken =
                retrieveSecurityToken(signatureType, securityProperties, inboundSecurityContext);
            this.inboundSecurityToken = inboundSecurityToken;

            createSignatureAlgorithm(inboundSecurityToken, signatureType);
        }

        protected abstract InboundSecurityToken retrieveSecurityToken(SignatureType signatureType,
                                                 XMLSecurityProperties securityProperties,
                                                 InboundSecurityContext inboundSecurityContext) throws XMLSecurityException;

        public InboundSecurityToken getInboundSecurityToken() {
            return inboundSecurityToken;
        }

        protected void createSignatureAlgorithm(InboundSecurityToken inboundSecurityToken, SignatureType signatureType)
                throws XMLSecurityException {

            Key verifyKey;
            final String algorithmURI = signatureType.getSignedInfo().getSignatureMethod().getAlgorithm();
            if (inboundSecurityToken.isAsymmetric()) {
                verifyKey = inboundSecurityToken.getPublicKey(algorithmURI, XMLSecurityConstants.Asym_Sig, signatureType.getId());
            } else {
                verifyKey = inboundSecurityToken.getSecretKey(
                        algorithmURI, XMLSecurityConstants.Sym_Sig, signatureType.getId());
                if (verifyKey != null) {
                    verifyKey = XMLSecurityUtils.prepareSecretKey(algorithmURI, verifyKey.getEncoded());
                }
            }

            if (verifyKey == null) {
                throw new XMLSecurityException("KeyInfo.nokey", new Object[]{"the inbound security token"});
            }

            try {
                SignatureAlgorithm signatureAlgorithm =
                        SignatureAlgorithmFactory.getInstance().getSignatureAlgorithm(
                                algorithmURI);
                if (XMLSignature.ALGO_ID_SIGNATURE_RSA_PSS.equals(algorithmURI)) {
                    PSSParameterSpec spec = rsaPSSParameterSpec(signatureType);
                    signatureAlgorithm.engineSetParameter(spec);
                }
                signatureAlgorithm.engineInitVerify(verifyKey);
                signerOutputStream = new SignerOutputStream(signatureAlgorithm);
                bufferedSignerOutputStream = new UnsyncBufferedOutputStream(signerOutputStream);

                final CanonicalizationMethodType canonicalizationMethodType =
                        signatureType.getSignedInfo().getCanonicalizationMethod();
                InclusiveNamespaces inclusiveNamespacesType =
                        XMLSecurityUtils.getQNameType(
                                canonicalizationMethodType.getContent(),
                                XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces
                        );

                Map<String, Object> transformerProperties = null;
                if (inclusiveNamespacesType != null) {
                    transformerProperties = new HashMap<>();
                    transformerProperties.put(
                            Canonicalizer20010315_Excl.INCLUSIVE_NAMESPACES_PREFIX_LIST,
                            inclusiveNamespacesType.getPrefixList());
                }
                transformer = XMLSecurityUtils.getTransformer(
                        null,
                        this.bufferedSignerOutputStream,
                        transformerProperties,
                        canonicalizationMethodType.getAlgorithm(),
                        XMLSecurityConstants.DIRECTION.IN);
            } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
                throw new XMLSecurityException(e);
            }

            // Clean the secret key from memory now that we're done with it
            if (verifyKey instanceof Destroyable) {
                try {
                    ((Destroyable)verifyKey).destroy();
                } catch (DestroyFailedException e) {
                    LOG.log(Level.DEBUG, "Error destroying key: {0}", e.getMessage());
                }
            }
        }

        private PSSParameterSpec rsaPSSParameterSpec(SignatureType signatureType) throws XMLSecurityException {
            SignatureMethodType signatureMethod = signatureType.getSignedInfo().getSignatureMethod();
            RSAPSSParamsType rsapssParams = null;
            for (Object o : signatureMethod.getContent()) {
                if (o instanceof RSAPSSParamsType) {
                    rsapssParams = (RSAPSSParamsType) o;
                    break;
                }
            }
            if (rsapssParams == null) {
                throw new XMLSecurityException("algorithms.MissingRSAPSSParams");
            }

            String digestMethod = rsapssParams.getDigestMethod() == null ? SHA256.getXmlDigestAlgorithm() : rsapssParams.getDigestMethod().getAlgorithm();
            String maskGenerationDigestMethod = rsapssParams.getMaskGenerationFunction() == null ? SHA256.getXmlDigestAlgorithm() : rsapssParams.getMaskGenerationFunction().getDigestMethod().getAlgorithm();
            DigestAlgorithm digestAlgorithm = fromXmlDigestAlgorithm(digestMethod);

            int saltLength = rsapssParams.getSaltLength() == null ? digestAlgorithm.getSaltLength() : rsapssParams.getSaltLength();
            int trailerField = rsapssParams.getTrailerField() == null ? 1 : rsapssParams.getTrailerField();
            String maskDigestAlgorithm = fromXmlDigestAlgorithm(maskGenerationDigestMethod).getDigestAlgorithm();

            return new PSSParameterSpec(digestAlgorithm.getDigestAlgorithm(), "MGF1",
                                        new MGF1ParameterSpec(maskDigestAlgorithm), saltLength, trailerField);
        }

        protected void processEvent(XMLSecEvent xmlSecEvent) throws XMLStreamException {
            transformer.transform(xmlSecEvent);
        }

        protected void doFinal() throws XMLSecurityException {
            try {
                transformer.doFinal();
                bufferedSignerOutputStream.close();
            } catch (IOException | XMLStreamException e) {
                throw new XMLSecurityException(e);
            }
            if (!signerOutputStream.verify(signatureType.getSignatureValue().getValue())) {
                throw new XMLSecurityException("errorMessages.InvalidSignatureValueException");
            }
        }
    }