Sure, here is the translation of the provided content: SOAP XML WS-Security signature verification

huangapple go评论74阅读模式
英文:

SOAP XML WS-Security signature verification

问题

I am able to sign the SOAP XML using a certificate for the WS-Security signature. But I am unable to verify its signature. On verifying the signature, it leads to an Exception. Some help will be appreciated to resolve the issue.

SOAP Enveloped WS-Security signature:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
 <s:Header>
  <ws:Security xmlns:ws="http://schemas.xmlsoap.org/..." s:actor="test">
   <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/..." id="Sample">
       ...
   </dsig:Signature>
  </ws:Security>
 </s:Header>
 <s:Body>
  ...
 </s:Body>
</s:Envelope>

When I try to verify the SOAP XML, I am getting the following Exception:

org.apache.xml.security.signature.MissingResourceFailureException: The Reference for URI #Body has no XMLSignatureInput

Java code to verify the signature:

public static boolean isSOAPXmlWSSEDigitalSignatureValid(String signedXmlFilePath, PublicKey publicKey) throws Exception {
    String xmlContent = getFileString(signedXmlFilePath);
    
    Document signedDoc = getDocument(xmlContent.trim(), true);
    // ...
    // (remaining code is not shown due to length constraints)
    // ...
    return signature.checkSignatureValue(publicKey);
}

Java code to sign the XML:

public static SOAPMessage WS_Security_signature(String inputFile, boolean isDataXML) throws Exception {
    // ...
    // (code to create SOAPMessage and add elements)
    // ...
    SOAPElement securityElement = soapHeader.addChildElement("Security", "wsse", WSSE_NS);
    // ...
    // (code to add BinarySecurityToken, Timestamp, Signature)
    // ...
    signature.sign(signContext);
    return soapMsg;
}

Full example code and usage are provided as well, but due to the character limit, I'm not able to display the complete content. If you have specific questions or need assistance with parts of the code, feel free to ask.

英文:

I am able to sign the SOAP XML using a certificate for the WS-Security signature. But i am unable to verify its signature. On verifying the signature it leads to Exception, Some help will be appreciated to resolve the issue

SOAP Enveloped WS-Security signature:

&lt;s:Envelope xmlns:s=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&gt;
 &lt;s:Header&gt;
  &lt;ws:Security xmlns:ws=&quot;http://schemas.xmlsoap.org/...&quot; s:actor=&quot;test&quot;&gt;
   &lt;dsig:Signature xmlns:dsig=&quot;http://www.w3.org/2000/09/...&quot; id=&quot;Sample&quot;&gt;
       ...
   &lt;/dsig:Signature&gt;
  &lt;/ws:Security&gt;
 &lt;/s:Header&gt;
 &lt;s:Body&gt;
  ...
 &lt;/s:Body&gt;
&lt;/s:Envelope&gt;

When i try to verify the SOAP XML i am getting the following Exception:
> org.apache.xml.security.signature.MissingResourceFailureException: The Reference for URI #Body has no XMLSignatureInput

public static boolean isSOAPXmlWSSEDigitalSignatureValid(String signedXmlFilePath, PublicKey publicKey) throws Exception {
	String xmlContent = getFileString(signedXmlFilePath);
	
	Document signedDoc = getDocument(xmlContent.trim(), true);
	signedDoc.createElementNS(DSIG_NS, &quot;ds&quot;); // qualifiedName = &quot;ds&quot;;
	signedDoc.createElementNS(WSU_NS, &quot;wsu&quot;);
	signedDoc.createElementNS(WSSE_NS, &quot;wsse&quot;);
	
	// load signature
	NodeList signatureNodes = signedDoc.getElementsByTagNameNS(javax.xml.crypto.dsig.XMLSignature.XMLNS, &quot;Signature&quot;);
	if (signatureNodes.getLength() == 0) {
		throw new Exception(&quot;No XML Digital Signature Found, document is discarded&quot;);
	}
	
	Element sigElement = (Element) signatureNodes.item(0);
	if (sigElement == null) 
		throw new Exception(&quot;Signature element is null!&quot;);
		
	org.apache.xml.security.Init.init();
	org.apache.xml.security.signature.XMLSignature signature = new XMLSignature(sigElement, &quot;&quot;);
	return signature.checkSignatureValue(publicKey);
}

By Using the following function i am able to sign the XML

public static SOAPMessage WS_Security_signature(String inputFile, boolean isDataXML) throws Exception {
	SOAPMessage soapMsg;
	Document docBody;
	if (isDataXML) {
		System.out.println(&quot;Sample DATA xml - Create SOAP Message&quot;);
		MessageFactory messageFactory = MessageFactory.newInstance();
		SOAPMessage soapMessage = messageFactory.createMessage();
		soapMsg = soapMessage;
		
		String xmlContent = getFileString(inputFile);
		docBody = getDocument(xmlContent.trim(), true);
		System.out.println(&quot;Data Document: &quot;+docBody.getDocumentElement());
	} else {
		System.out.println(&quot;SOAP XML with Envelope&quot;);
		
		Document doc = getDocument(inputFile, false); // SOAP MSG removing comment elements
		String docStr = toStringDocument(doc); // https://stackoverflow.com/a/2567443/5081877
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(docStr.getBytes());
		
		MimeHeaders mimeHeaders = new MimeHeaders();
		// SOAPMessage message = MessageFactory.newInstance().createMessage(null, fileInputStream);
		SOAPMessage message = MessageFactory.newInstance(&quot;SOAP 1.2 Protocol&quot;).createMessage(mimeHeaders, byteArrayInputStream);
		soapMsg = message;
		
		docBody = soapMsg.getSOAPBody().extractContentAsDocument();
		System.out.println(&quot;SOAP DATA Document: &quot;+docBody.getDocumentElement());
	}
	// A new SOAPMessage object contains: •SOAPPart object •SOAPEnvelope object •SOAPBody object •SOAPHeader object 
	SOAPPart soapPart = soapMsg.getSOAPPart();
	SOAPEnvelope soapEnv = soapPart.getEnvelope();
	SOAPHeader soapHeader = soapEnv.getHeader(); // soapMessage.getSOAPHeader();
	SOAPBody soapBody = soapEnv.getBody(); // soapMessage.getSOAPBody()
	
	soapBody.addDocument(docBody);
	soapBody.addAttribute(soapEnv.createName(&quot;Id&quot;, &quot;wsu&quot;, WSU_NS), &quot;Body&quot;);
	
	if (soapHeader == null) {
		soapHeader = soapEnv.addHeader();
		System.out.println(&quot;Provided SOAP XML does not contains any Header part. So creating it.&quot;);
	}
	// &lt;wsse:Security&gt; element adding to Header Part
	SOAPElement securityElement = soapHeader.addChildElement(&quot;Security&quot;, &quot;wsse&quot;, WSSE_NS);
	securityElement.addNamespaceDeclaration(&quot;wsu&quot;, WSU_NS);

	String certEncodedID = &quot;X509Token&quot;, timeStampID = &quot;TS&quot;, signedBodyID = &quot;Body&quot;;
	// (ii) Add Binary Security Token.
	// &lt;wsse:BinarySecurityToken EncodingType=&quot;...#Base64Binary&quot; ValueType=&quot;...#X509v3&quot; wsu:Id=&quot;X509Token&quot;&gt;The base64 encoded value of the ROS digital certificate.&lt;/wsse:BinarySecurityToken&gt;
	SOAPElement binarySecurityToken = securityElement.addChildElement(&quot;BinarySecurityToken&quot;, &quot;wsse&quot;);
	binarySecurityToken.setAttribute(&quot;ValueType&quot;, binarySecurityToken_Value);
	binarySecurityToken.setAttribute(&quot;EncodingType&quot;, binarySecurityToken_Encoding);
	binarySecurityToken.setAttribute(&quot;wsu:Id&quot;, certEncodedID);
		byte[] certByte = loadPublicKeyX509.getEncoded();
		String encodeToString = Base64.getEncoder().encodeToString(certByte);
	binarySecurityToken.addTextNode(encodeToString);
	
	//(iii) Add TimeStamp element - &lt;wsu:Timestamp wsu:Id=&quot;TS&quot;&gt;
	SOAPElement timestamp = securityElement.addChildElement(&quot;Timestamp&quot;, &quot;wsu&quot;);
	timestamp.addAttribute(soapEnv.createName(&quot;Id&quot;, &quot;wsu&quot;, WSU_NS), timeStampID);
		String DATE_TIME_PATTERN = &quot;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSX&quot;;
		DateTimeFormatter timeStampFormatter = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
	timestamp.addChildElement(&quot;Created&quot;, &quot;wsu&quot;).setValue(timeStampFormatter.format(ZonedDateTime.now().toInstant().atZone(ZoneId.of(&quot;UTC&quot;))));
	timestamp.addChildElement(&quot;Expires&quot;, &quot;wsu&quot;).setValue(timeStampFormatter.format(ZonedDateTime.now().plusSeconds(30).toInstant().atZone(ZoneId.of(&quot;UTC&quot;))));

	// (iv) Add signature element
	// &lt;wsse:Security&gt; &lt;ds:Signature&gt; &lt;ds:KeyInfo&gt; &lt;wsse:SecurityTokenReference&gt;
	SOAPElement securityTokenReference = securityElement.addChildElement(&quot;SecurityTokenReference&quot;, &quot;wsse&quot;);
	SOAPElement reference = securityTokenReference.addChildElement(&quot;Reference&quot;, &quot;wsse&quot;);
	reference.setAttribute(&quot;URI&quot;, &quot;#&quot;+certEncodedID); // &lt;wsse:BinarySecurityToken wsu:Id=&quot;X509Token&quot;
	
	// &lt;ds:SignedInfo&gt;
	String providerName = System.getProperty(&quot;jsr105Provider&quot;, &quot;org.jcp.xml.dsig.internal.dom.XMLDSigRI&quot;);
	XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance(&quot;DOM&quot;, (Provider) Class.forName(providerName).newInstance());

	//Digest method - &lt;ds:SignatureMethod Algorithm=&quot;http://www.w3.org/2000/09/xmldsig#rsa-sha1&quot;/&gt;
	javax.xml.crypto.dsig.DigestMethod digestMethod = xmlSignatureFactory.newDigestMethod(digestMethodAlog_SHA1, null);
	
	ArrayList&lt;Transform&gt; transformList = new ArrayList&lt;Transform&gt;();
	//Transform - &lt;ds:Reference URI=&quot;#Body&quot;&gt;
	Transform envTransform = xmlSignatureFactory.newTransform(transformAlog, (TransformParameterSpec) null);
	transformList.add(envTransform);
		//References &lt;ds:Reference URI=&quot;#Body&quot;&gt;
		ArrayList&lt;Reference&gt; refList = new ArrayList&lt;Reference&gt;();
			Reference refTS   = xmlSignatureFactory.newReference(&quot;#&quot;+timeStampID,  digestMethod, transformList, null, null);
			Reference refBody = xmlSignatureFactory.newReference(&quot;#&quot;+signedBodyID, digestMethod, transformList, null, null);
		refList.add(refBody);
		refList.add(refTS);

	javax.xml.crypto.dsig.CanonicalizationMethod cm = xmlSignatureFactory.newCanonicalizationMethod(canonicalizerAlog, (C14NMethodParameterSpec) null);

	javax.xml.crypto.dsig.SignatureMethod sm = xmlSignatureFactory.newSignatureMethod(signatureMethodAlog_SHA1, null);
	SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(cm, sm, refList);

	DOMSignContext signContext = new DOMSignContext(privateKey, securityElement);
	signContext.setDefaultNamespacePrefix(&quot;ds&quot;);
	signContext.putNamespacePrefix(DSIG_NS, &quot;ds&quot;);
	signContext.putNamespacePrefix(WSU_NS, &quot;wsu&quot;);

	signContext.setIdAttributeNS(soapBody, WSU_NS, &quot;Id&quot;);
	signContext.setIdAttributeNS(timestamp, WSU_NS, &quot;Id&quot;);

	KeyInfoFactory keyFactory = KeyInfoFactory.getInstance();
	DOMStructure domKeyInfo = new DOMStructure(securityTokenReference);
	javax.xml.crypto.dsig.keyinfo.KeyInfo keyInfo = keyFactory.newKeyInfo(java.util.Collections.singletonList(domKeyInfo));
	javax.xml.crypto.dsig.XMLSignature signature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo);
	signContext.setBaseURI(&quot;&quot;);

	signature.sign(signContext);
	return soapMsg;
}

Full Example which uses the Certificate And Private Key Baeldung.cer, Baeldung.p12 (password = “password”)

// dependency: groupId:xml-security, artifactId:xmlsec, version:1.3.0
// dependency: groupId:xalan, artifactId:xalan, version:2.7.1
public class SOAP_Security_Signature {
	static final String 
	WSSE_NS = &quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd&quot;,
	WSU_NS	= &quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot;,
	DSIG_NS = &quot;http://www.w3.org/2000/09/xmldsig#&quot;, // javax.xml.crypto.dsig.XMLSignature.XMLNS, Constants.SignatureSpecNS
	
	binarySecurityToken_Encoding = &quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary&quot;,
	binarySecurityToken_Value = &quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3&quot;,
	
	signatureMethodAlog_SHA1 = DSIG_NS + &quot;rsa-sha1&quot;, // XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1
	digestMethodAlog_SHA1  = Constants.ALGO_ID_DIGEST_SHA1, // DSIG_NS + &quot;sha1&quot;, // Constants.ALGO_ID_DIGEST_SHA1
	transformAlog = Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS, //&quot;http://www.w3.org/2001/10/xml-exc-c14n#&quot;;
	canonicalizerAlog = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; //&quot;http://www.w3.org/2001/10/xml-exc-c14n#&quot;; CanonicalizationMethod.EXCLUSIVE
	
	static {
		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
	}
	public static X509Certificate loadPublicKeyX509(InputStream cerFileStream) throws CertificateException, NoSuchProviderException {
		CertificateFactory	certificateFactory = CertificateFactory.getInstance(&quot;X.509&quot;, &quot;BC&quot;);
		X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(cerFileStream);
		return x509Certificate;
	}
	public static PrivateKey loadPrivateKeyforSigning(InputStream cerFileStream, String password) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchProviderException {
		KeyStore keyStore = KeyStore.getInstance(&quot;PKCS12&quot;); //, &quot;BC&quot;);
		keyStore.load(cerFileStream, password.toCharArray());
		
		Enumeration&lt;String&gt; keyStoreAliasEnum = keyStore.aliases();
		PrivateKey privateKey = null;
		String alias = null;
		if ( keyStoreAliasEnum.hasMoreElements() ) {
			alias = keyStoreAliasEnum.nextElement();
			if (password != null) {
				privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
			}
		}
		return privateKey;
	}
	static X509Certificate loadPublicKeyX509;
	static PrivateKey privateKey;
	static String path = &quot;C:/Yash/SOAP/&quot;, privateKeyFilePath = path+&quot;Baeldung.p12&quot;, publicKeyFilePath = path+&quot;Baeldung.cer&quot;,
				  inputFile= path+&quot;Soap1.xml&quot;, outputFile = path+&quot;output.xml&quot;;
	public static void main(String[] args) throws Exception {
		
		InputStream pkcs_FileStream = new FileInputStream(privateKeyFilePath);
		privateKey = loadPrivateKeyforSigning(pkcs_FileStream, &quot;password&quot;);
		System.out.println(&quot;privateKey : &quot;+privateKey);
		
		InputStream cerFileStream = new FileInputStream(publicKeyFilePath);
		loadPublicKeyX509 = loadPublicKeyX509(cerFileStream);
		PublicKey publicKey = loadPublicKeyX509.getPublicKey();
		System.out.println(&quot;loadPublicKey : &quot;+ publicKey);
		
		System.setProperty(&quot;javax.xml.soap.MessageFactory&quot;, &quot;com.sun.xml.internal.messaging.saaj.soap.ver1_2.SOAPMessageFactory1_2Impl&quot;);
		System.setProperty(&quot;javax.xml.bind.JAXBContext&quot;, &quot;com.sun.xml.internal.bind.v2.ContextFactory&quot;);
		
		SOAPMessage soapMsg = WS_Security_signature(inputFile, false);
		outputSOAPMessageToFile(soapMsg);
		
		System.out.println(&quot;Signature Succesfull. Verify the Signature&quot;);
		boolean soapXmlWSSEDigitalSignatureValid = isSOAPXmlWSSEDigitalSignatureValid(outputFile, publicKey);
		System.out.println(&quot;isSOAPXmlDigitalSignatureValid :&quot;+soapXmlWSSEDigitalSignatureValid);
	}
  
	
	public static void outputSOAPMessageToFile(SOAPMessage soapMessage) throws SOAPException, IOException {
		File outputFileNew = new File(outputFile);
		java.io.FileOutputStream fos = new java.io.FileOutputStream(outputFileNew);
		soapMessage.writeTo(fos);
		fos.close();
	}
	
	public static String toStringDocument(Document doc) throws TransformerException {
		StringWriter sw = new StringWriter();
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer transformer = tf.newTransformer();
		transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, &quot;no&quot;);
		transformer.setOutputProperty(OutputKeys.METHOD, &quot;xml&quot;);
		transformer.setOutputProperty(OutputKeys.INDENT, &quot;yes&quot;);
		transformer.setOutputProperty(OutputKeys.ENCODING, &quot;UTF-8&quot;);

		transformer.transform(new DOMSource(doc), new StreamResult(sw));
		return sw.toString();
	}
	public static String getFileString(String xmlFilePath) throws FileNotFoundException {
		File file = new File(xmlFilePath);
		//FileInputStream parseXMLStream = new FileInputStream(file.getAbsolutePath());
		
		Scanner scanner = new Scanner( file, &quot;UTF-8&quot; );
		String xmlContent = scanner.useDelimiter(&quot;\\A&quot;).next();
		scanner.close(); // Put this call in a finally block
		System.out.println(&quot;Str:&quot;+xmlContent);
		return xmlContent;
	}
	public static Document getDocument(String xmlData, boolean isXMLData) throws Exception {
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		dbFactory.setNamespaceAware(true);
		dbFactory.setIgnoringComments(true);
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc;
		if (isXMLData) {
			InputSource ips = new org.xml.sax.InputSource(new StringReader(xmlData));
			doc = dBuilder.parse(ips);
		} else {
			doc = dBuilder.parse( new File(xmlData) );
		}
		return doc;
	}
 
	private void callTheWebServiceFromFile() throws IOException, SOAPException {
		//load the soap request file
		File soapFile = new File(outputFile);
		FileInputStream fis = new FileInputStream(soapFile);
		javax.xml.transform.stream.StreamSource ss = new javax.xml.transform.stream.StreamSource(fis);

		// Create a SOAP Message Object
		SOAPMessage msg = MessageFactory.newInstance().createMessage();
		SOAPPart soapPart = msg.getSOAPPart();

		// Set the soapPart Content with the stream source
		soapPart.setContent(ss);

		// Create a webService connection
		SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
		SOAPConnection soapConnection = soapConnectionFactory.createConnection();

		// Invoke the webService.
		String soapEndpointUrl = &quot;https://softwaretest.ros.ie/paye-employers/v1/soap&quot;;
		SOAPMessage resp = soapConnection.call(msg, soapEndpointUrl);

		// Reading result
		resp.writeTo(System.out);

		fis.close();
		soapConnection.close();
	}
}

Input SOAP XML to Sign:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
&lt;env:Envelope xmlns:env=&quot;http://www.w3.org/2003/05/soap-envelope&quot;&gt;
	&lt;env:Body&gt;
	   &lt;product version=&quot;11.1.2.4.0&quot;&gt; &lt;!-- Data XML --&gt;
		   &lt;name&gt;API Gateway&lt;/name&gt;
		   &lt;company&gt;Oracle&lt;/company&gt;
		   &lt;description&gt;SOA Security and Management&lt;/description&gt;
	   &lt;/product&gt;
	&lt;/env:Body&gt;
&lt;/env:Envelope&gt;

WS-Security Signed XML:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;env:Envelope
    xmlns:env=&quot;http://www.w3.org/2003/05/soap-envelope&quot;&gt;
    &lt;env:Header&gt;
        &lt;wsse:Security
            xmlns:wsse=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd&quot;
            xmlns:wsu=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot;&gt;
            &lt;wsse:BinarySecurityToken EncodingType=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary&quot; ValueType=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3&quot; wsu:Id=&quot;X509Token&quot;&gt;MIIDPjCCAiagAwIBAgIJAPvd1gx14C3CMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzAeFw0xNzEwMTIxMDQzMTRaFw0yNzEwMTMxMDQzMTRaMEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyi5GmOeN4QaH/CP5gSOyHX8znb5TDHWV8wc+ZT7kNU8zt5tGMhjozK6hax155/6tOsBDR0rSYBhL+Dm/+uCVS7qOlRHhf6cNGtzGF1gnNJB2WjI8oMAYm24xpLj1WphKUwKrn3nTMPnQup5OoNAMYl99flANrRYVjjxrLQvDZDUio6IujrCZ2TtXGM0g/gP++28KT7g1KlUui3xtB0u33wx7UN8Fix3JmjOaPHGwxGpwP3VGSjfs8cuhqVwRQaZpCOoHU/P8wpXKw80sSdhz+SRueMPtVYqK0CiLL5/O0h0Y3le4IVwhgg3KG1iTGOWn60UMFn1EYmQ18k5Nsma6UCAwEAAaMtMCswCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBPAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4IBAQC8DDBmJ3p4xytxBiE0s4p1715WT6Dm/QJHp0XC0hkSoyZKDh+XVmrzm+J3SiW1vpswb5hLgPo040YX9jnDmgOD+TpleTuKHxZRYj92UYWmdjkWLVtFMcvOh+gxBiAPpHIqZsqo8lfcyAuh8Jx834IXbknfCUtERDLG/rU9P/3XJhrM2GC5qPQznrW4EYhUCGPyIJXmvATMVvXMWCtfogAL+n42vjYXQXZoAWomHhLHoNbSJUErnNdWDOh4WoJtXJCxA6U5LSBplqb3wB2hUTqw+0admKltvmy+KA1PD7OxoGiY7V544zeGqJam1qxUia7y5BL6uOa/4ShSV8pcJDYz&lt;/wsse:BinarySecurityToken&gt;
            &lt;wsu:Timestamp wsu:Id=&quot;TS&quot;&gt;
                &lt;wsu:Created&gt;2020-08-27T12:03:23.288Z&lt;/wsu:Created&gt;
                &lt;wsu:Expires&gt;2020-08-27T12:03:53.293Z&lt;/wsu:Expires&gt;
            &lt;/wsu:Timestamp&gt;
            &lt;ds:Signature
                xmlns:ds=&quot;http://www.w3.org/2000/09/xmldsig#&quot;&gt;
                &lt;ds:SignedInfo&gt;
                    &lt;ds:CanonicalizationMethod Algorithm=&quot;http://www.w3.org/2001/10/xml-exc-c14n#&quot;/&gt;
                    &lt;ds:SignatureMethod Algorithm=&quot;http://www.w3.org/2000/09/xmldsig#rsa-sha1&quot;/&gt;
                    &lt;ds:Reference URI=&quot;#Body&quot;&gt;
                        &lt;ds:Transforms&gt;
                            &lt;ds:Transform Algorithm=&quot;http://www.w3.org/2001/10/xml-exc-c14n#&quot;/&gt;
                        &lt;/ds:Transforms&gt;
                        &lt;ds:DigestMethod Algorithm=&quot;http://www.w3.org/2000/09/xmldsig#sha1&quot;/&gt;
                        &lt;ds:DigestValue&gt;RU8XbQ1/kx/CPZpgxG9fa/lia8Q=&lt;/ds:DigestValue&gt;
                    &lt;/ds:Reference&gt;
                    &lt;ds:Reference URI=&quot;#TS&quot;&gt;
                        &lt;ds:Transforms&gt;
                            &lt;ds:Transform Algorithm=&quot;http://www.w3.org/2001/10/xml-exc-c14n#&quot;/&gt;
                        &lt;/ds:Transforms&gt;
                        &lt;ds:DigestMethod Algorithm=&quot;http://www.w3.org/2000/09/xmldsig#sha1&quot;/&gt;
                        &lt;ds:DigestValue&gt;YZTSgGN/tvrcpeFZ00aWCpVrXZU=&lt;/ds:DigestValue&gt;
                    &lt;/ds:Reference&gt;
                &lt;/ds:SignedInfo&gt;
                &lt;ds:SignatureValue&gt;hgGYDvkc3YPG1ptb6FMnQJV0t1GExjHIOGsXjAwG6uIYLDvkt10ve+AOynBAiSP0CR1NDI6mlXd+
5v5oa2XLEcbuO62v8yj0o1Kr+gkiaf1zo/qZkpwyT5iBkmabNcEzRE8iDCKwTOfFkG4PVRkCOE0D
Q4I84AeYnLAHaoF9IGpbjk0MdXKFIsSTmAmR92BHnjsOyUi1CD6N/7GDscNLfYoEtMEwovFbupUP
qbJNaq+M/bi5dnTEVqG/TIGftc/me8NVXQiohRq6U8sSAMbLdF5P+iGivcqlLD5xthXfBPHpwruK
euXNan7Jxc9cc5QFx3Rcirvqg/iJ0sPAHRuPGQ==&lt;/ds:SignatureValue&gt;
                &lt;ds:KeyInfo&gt;
                    &lt;wsse:SecurityTokenReference&gt;
                        &lt;wsse:Reference URI=&quot;#X509Token&quot;/&gt;
                    &lt;/wsse:SecurityTokenReference&gt;
                &lt;/ds:KeyInfo&gt;
            &lt;/ds:Signature&gt;
        &lt;/wsse:Security&gt;
    &lt;/env:Header&gt;
    &lt;env:Body
        xmlns:wsu=&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot; wsu:Id=&quot;Body&quot;&gt;
        &lt;product version=&quot;11.1.2.4.0&quot;&gt;
            &lt;name&gt;API Gateway&lt;/name&gt;
            &lt;company&gt;Oracle&lt;/company&gt;
            &lt;description&gt;SOA Security and Management&lt;/description&gt;
        &lt;/product&gt;
    &lt;/env:Body&gt;
&lt;/env:Envelope&gt;

For SOAP XML digital signature i am able to sign and verify.

SOAP XML Enveloped Signature:

&lt;s:Envelope xmlns:s=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&gt;
 &lt;s:Header&gt;
   &lt;dsig:Signature xmlns:dsig=&quot;http://www.w3.org/2000/09/...&quot; id=&quot;Sample&quot;&gt;
       ...
   &lt;/dsig:Signature&gt;
 &lt;/s:Header&gt;
 &lt;s:Body&gt;
  ...
 &lt;/s:Body&gt;
&lt;/s:Envelope&gt;

答案1

得分: 0

在您的 isSOAPXmlWSSEDigitalSignatureValid 方法中,您需要为每个 Reference 元素显式设置 Id 属性作为元素的 id 属性,而这些属性不会默认被假定:https://issues.apache.org/jira/browse/SANTUARIO-312

  public static boolean isSOAPXmlWSSEDigitalSignatureValid(String signedXmlFilePath, PublicKey publicKey) throws Exception {
    String xmlContent = getFileString(signedXmlFilePath);

    Document signedDoc = getDocument(xmlContent, true);
    signedDoc.createElementNS(DSIG_NS, "ds"); // qualifiedName = "ds";
    signedDoc.createElementNS(WSU_NS, "wsu");
    signedDoc.createElementNS(WSSE_NS, "wsse");

    // 为 SOAP Body 元素注册 XML ID
    NodeList soapBodyElements = signedDoc.getElementsByTagNameNS("http://www.w3.org/2003/05/soap-envelope", "Body");
    if (soapBodyElements.getLength() == 0) {
      throw new Exception("找不到 SOAP Body 元素");
    }

    Element soapBodyElement = (Element) soapBodyElements.item(0);
    soapBodyElement.setIdAttributeNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id", true);

    // 为 Timestamp 元素注册 XML ID
    NodeList timestamps = signedDoc.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Timestamp");
    if (timestamps.getLength() == 0) {
      throw new Exception("找不到 Timestamp 元素");
    }

    Element timestampElement = (Element) timestamps.item(0);
    timestampElement.setIdAttributeNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id", true);

    // 加载签名
    NodeList signatureNodes = signedDoc.getElementsByTagNameNS(javax.xml.crypto.dsig.XMLSignature.XMLNS, "Signature");
    if (signatureNodes.getLength() == 0) {
      throw new Exception("未找到 XML 数字签名,文档已被丢弃");
    }

    Element sigElement = (Element) signatureNodes.item(0);
    if (sigElement == null)
      throw new Exception("签名元素为空!");

    Init.init();
    XMLSignature signature = new XMLSignature(sigElement, "");
    return signature.checkSignatureValue(publicKey);
  }
英文:

In your isSOAPXmlWSSEDigitalSignatureValid method you need to set explicitly the Id attribute as the element id attribute for every Referenced element, they are not assumed by default: https://issues.apache.org/jira/browse/SANTUARIO-312

  public static boolean isSOAPXmlWSSEDigitalSignatureValid(String signedXmlFilePath, PublicKey publicKey) throws Exception {
    String xmlContent = getFileString(signedXmlFilePath);

    Document signedDoc = getDocument(xmlContent, true);
    signedDoc.createElementNS(DSIG_NS, &quot;ds&quot;); // qualifiedName = &quot;ds&quot;;
    signedDoc.createElementNS(WSU_NS, &quot;wsu&quot;);
    signedDoc.createElementNS(WSSE_NS, &quot;wsse&quot;);

    // Register XML ID for SOAP Body element
    NodeList soapBodyElements = signedDoc.getElementsByTagNameNS(&quot;http://www.w3.org/2003/05/soap-envelope&quot;, &quot;Body&quot;);
    if (soapBodyElements.getLength() == 0) {
      throw new Exception(&quot;Element SOAP Body not found&quot;);
    }

    Element soapBodyElement = (Element) soapBodyElements.item(0);
    soapBodyElement.setIdAttributeNS(&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot;, &quot;Id&quot;, true);

    // Register XML ID for Timestamp element
    NodeList timestamps = signedDoc.getElementsByTagNameNS(&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot;, &quot;Timestamp&quot;);
    if (timestamps.getLength() == 0) {
      throw new Exception(&quot;Element Timestamp not found&quot;);
    }

    Element timestampElement = (Element) timestamps.item(0);
    timestampElement.setIdAttributeNS(&quot;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd&quot;, &quot;Id&quot;, true);

    // load signature
    NodeList signatureNodes = signedDoc.getElementsByTagNameNS(javax.xml.crypto.dsig.XMLSignature.XMLNS, &quot;Signature&quot;);
    if (signatureNodes.getLength() == 0) {
      throw new Exception(&quot;No XML Digital Signature Found, document is discarded&quot;);
    }

    Element sigElement = (Element) signatureNodes.item(0);
    if (sigElement == null)
      throw new Exception(&quot;Signature element is null!&quot;);

    Init.init();
    XMLSignature signature = new XMLSignature(sigElement, &quot;&quot;);
    return signature.checkSignatureValue(publicKey);
  }

huangapple
  • 本文由 发表于 2020年8月27日 20:23:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/63615930.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定