Problem verifying xml signature
We have a problem with verifying XML Signatures which are part of a SOAP message. Thanks a lot for helping! Hope my problem is understandable - otherwise ask.
We use the following enviroment:
Java6
Axis 2 V1.2 with XML Beans
Step 1:
The Java 6 XML Signature is an enveloped signature over an element called payload with exclusive XML canonicalization. We sign the payload and send the payload including signature to the server. At first I discovered the following namespace problem.
DigesterOutputstream Create Signature:
FEINER: <Payload Id="c623c3be-529b-4d6d-8f1e-a4a29660f344"><Parameter Encoding="base64"><Name>VSD</Name><Value>PFBlcmZvcm1VcGRhdGVzIHhtbG5zPSJodHRwOi8vd3MuZ2VtYXRpay5kZS9jbS9jYy9DbUNjU2VydmljZVJlcXVlc3QvdjEuMiIgeG1sbnM6djE9Imh0dHA6Ly93cy5nZW1hdGlrLmRlL2NtL2NvbW1vbi9DbUNvbW1vbi92MS4yIj4NCiAgPHYxOkljY3NuPjgwMjc2MDAxMDQwMDAwMDAyNDAwPC92MTpJY2Nzbj4NCiAgPHYxOlVwZGF0ZUlkPjAxPC92MTpVcGRhdGVJZD4NCjwvUGVyZm9ybVVwZGF0ZXM+</Value></Parameter><MessageID>urn:uuid:34D51D9DE4B7A19DD411938151524022</MessageID><Timestamp><Created>UNDO</Created></Timestamp></Payload>
DigesterOutput Verify Signature:
FEINER: <Payload xmlns="http://ws.gematik.de/Schema/Telematik/Transport/V1" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" Id="c623c3be-529b-4d6d-8f1e-a4a29660f344"><Parameter Encoding="base64"><Name>VSD</Name><Value>PFBlcmZvcm1VcGRhdGVzIHhtbG5zPSJodHRwOi8vd3MuZ2VtYXRpay5kZS9jbS9jYy9DbUNjU2VydmljZVJlcXVlc3QvdjEuMiIgeG1sbnM6djE9Imh0dHA6Ly93cy5nZW1hdGlrLmRlL2NtL2NvbW1vbi9DbUNvbW1vbi92MS4yIj4NCiAgPHYxOkljY3NuPjgwMjc2MDAxMDQwMDAwMDAyNDAwPC92MTpJY2Nzbj4NCiAgPHYxOlVwZGF0ZUlkPjAxPC92MTpVcGRhdGVJZD4NCjwvUGVyZm9ybVVwZGF0ZXM+</Value></Parameter><MessageID>urn:uuid:34D51D9DE4B7A19DD411938151524022</MessageID><Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><Created>UNDO</Created></Timestamp></Payload>
31.10.2007 08:25:48 org.jcp.xml.dsig.internal.dom.DOMReference validate
FEIN: Expected digest: 71PfJ/xxn38TtQrpZOpRdqTZsBw=
31.10.2007 08:25:48 org.jcp.xml.dsig.internal.dom.DOMReference validate
FEIN: Actual digest: B1Qdei/0yW1mqR2T50LXKFfxhl0=
Soap request with payload:
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><TelematikHeader xmlns="http://ws.gematik.de/Schema/Telematik/Transport/V1"><MessageID>urn:uuid:34D51D9DE4B7A19DD411938151524022</MessageID><ConversationID /><ServiceLocalization><Type>VSD</Type><Provider>101575519</Provider></ServiceLocalization><MessageType><Component>VSD</Component><Operation>PerformUpdates</Operation></MessageType><RoleDataProcessor /></TelematikHeader><TransportHeader xmlns="http://ws.gematik.de/Schema/Telematik/Transport/V1"><InterfaceVersion>0.0.24.3</InterfaceVersion></TransportHeader></soapenv:Header><soapenv:Body><TelematikExecute xmlns="http://ws.gematik.de/Schema/Telematik/Transport/V1"><Payload Id="c623c3be-529b-4d6d-8f1e-a4a29660f344"><Parameter Encoding="base64"><Name>VSD</Name><Value>PFBlcmZvcm1VcGRhdGVzIHhtbG5zPSJodHRwOi8vd3MuZ2VtYXRpay5kZS9jbS9jYy9DbUNjU2VydmljZVJlcXVlc3QvdjEuMiIgeG1sbnM6djE9Imh0dHA6Ly93cy5nZW1hdGlrLmRlL2NtL2NvbW1vbi9DbUNvbW1vbi92MS4yIj4NCiAgPHYxOkljY3NuPjgwMjc2MDAxMDQwMDAwMDAyNDAwPC92MTpJY2Nzbj4NCiAgPHYxOlVwZGF0ZUlkPjAxPC92MTpVcGRhdGVJZD4NCjwvUGVyZm9ybVVwZGF0ZXM+</Value></Parameter><MessageID>urn:uuid:34D51D9DE4B7A19DD411938151524022</MessageID><Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><Created>UNDO</Created></Timestamp><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI="#c623c3be-529b-4d6d-8f1e-a4a29660f344"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>71PfJ/xxn38TtQrpZOpRdqTZsBw=</DigestValue></Reference></SignedInfo><SignatureValue>FuhOdrz9kHR0MeAUq9Rxkg6w++7foR77s9AYQUQxb8qPJ44Ba6By8R/H+CCn5JP5cPFz8/mGOgOD NGKLgZp66xbVSWe1UeehmZLH1a2kvHsx/VvYo3Lr5foHsl6YikUBMXCBdhI4ukKJTuwBOK/7m3lu 7Zl07SFo0zWL73gUTxc=</SignatureValue><KeyInfo><X509Data><X509SubjectName>CN=Harris Knafla,OU=IP,O=TK,ST=Hamburg,C=DE</X509SubjectName><X509Certificate>MIIC0DCCAjmgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMCREUxEDAOBgNVBAgT B0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxCzAJBgNVBAoTAlRLMQswCQYDVQQLEwJJUDEUMBIG A1UEAxMLTmlscyBLbmFmbGExKjAoBgkqhkiG9w0BCQEWG0RyLk5pbHMuS25hZmxhQHRrLW9ubGlu ZS5kZTAeFw0wNzA2MjkxNzQ2MzBaFw0wODA2MjgxNzQ2MzBaMFExCzAJBgNVBAYTAkRFMRAwDgYD VQQIEwdIYW1idXJnMQswCQYDVQQKEwJUSzELMAkGA1UECxMCSVAxFjAUBgNVBAMTDUhhcnJpcyBL bmFmbGEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJMjAnKFGjXjbPbi4X1vnI/H7ArNfayv HO7+QbuV1FqIR+aZuAYZeR5v0s8NKyGOcMxscAQk59ZrdfqaaIiwtcXk2fNHphtSVqLqR4NLWO2q xJKXwBcAxIn7byjq/DqjiUr5nmw1cMWJtK1xwB6pVMvCv97KGg2Z8peronBxg6mVAgMBAAGjezB5 MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl MB0GA1UdDgQWBBRaMTzoUhWt1wguyvPlPuUUV8VRtTAfBgNVHSMEGDAWgBQuZ2A4G1XF+GvL7vai Zst6RUCqYjANBgkqhkiG9w0BAQUFAAOBgQAr3rtJIVNchr3pMEfFcSzbJJWo/c0LRkUnWkP1gD6f MqLoLFUbl8k6tKJ9V4P0Oe2BODRIfNyTFjKLzD1lHAFFRz9pzYUx+hq4VDWooA3MsewNDDyJwupi vlmHcM+Y8Cv97q9pERiqAY88TRMZxntl/b98W61KARAO+HUDhTnA1g==</X509Certificate></X509Data></KeyInfo></Signature></Payload></TelematikExecute></soapenv:Body></soapenv:Envelope>
The problem is the namespaces under the elements payload and timestamp. For verification the namespaces are inherited from parent element. I wonder why this happens - I thought this should not happen when using exclusive canonicalization, or?
Step 2:
Then I added the namespaces before creating the signature , e.g.
payloadElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://ws.gematik.de/Schema/Telematik/Transport/V1");
for all attributes that are not part of the create signature log. Then the xml signature was verify successfully when I tested this against my own server. See log files:
DigesterOutputstream for create signature:
31.10.2007 11:16:00 org.jcp.xml.dsig.internal.DigesterOutputStream write
FEINER: <Payload xmlns="http://ws.gematik.de/Schema/Telematik/Transport/V1" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Id="c623c3be-529b-4d6d-8f1e-a4a29660f344"><Parameter Encoding="base64"><Name>VSD</Name><Value>PFBlcmZvcm1VcGRhdGVzIHhtbG5zPSJodHRwOi8vd3MuZ2VtYXRpay5kZS9jbS9jYy9DbUNjU2VydmljZVJlcXVlc3QvdjEuMiIgeG1sbnM6djE9Imh0dHA6Ly93cy5nZW1hdGlrLmRlL2NtL2NvbW1vbi9DbUNvbW1vbi92MS4yIj4NCiAgPHYxOkljY3NuPjgwMjc2MDAxMDQwMDAwMDMwMjI5PC92MTpJY2Nzbj4NCiAgPHYxOlVwZGF0ZUlkPjAxPC92MTpVcGRhdGVJZD4NCjwvUGVyZm9ybVVwZGF0ZXM+</Value></Parameter><MessageID>urn:uuid:9E0D31C48FDB63BBCD11938257462232</MessageID><Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><Created>UNDO</Created></Timestamp></Payload>
DigesterOutputstream verify signature:
31.10.2007 11:19:00 org.jcp.xml.dsig.internal.DigesterOutputStream write
FEINER: <Payload xmlns="http://ws.gematik.de/Schema/Telematik/Transport/V1" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Id="c623c3be-529b-4d6d-8f1e-a4a29660f344"><Parameter Encoding="base64"><Name>VSD</Name><Value>PFBlcmZvcm1VcGRhdGVzIHhtbG5zPSJodHRwOi8vd3MuZ2VtYXRpay5kZS9jbS9jYy9DbUNjU2VydmljZVJlcXVlc3QvdjEuMiIgeG1sbnM6djE9Imh0dHA6Ly93cy5nZW1hdGlrLmRlL2NtL2NvbW1vbi9DbUNvbW1vbi92MS4yIj4NCiAgPHYxOkljY3NuPjgwMjc2MDAxMDQwMDAwMDMwMjI5PC92MTpJY2Nzbj4NCiAgPHYxOlVwZGF0ZUlkPjAxPC92MTpVcGRhdGVJZD4NCjwvUGVyZm9ybVVwZGF0ZXM+</Value></Parameter><MessageID>urn:uuid:9E0D31C48FDB63BBCD11938257462232</MessageID><Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><Created>UNDO</Created></Timestamp></Payload>
The whole soap request:
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1"><wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="CertId-3596382">MIIC0DCCAjmgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxCzAJBgNVBAoTAlRLMQswCQYDVQQLEwJJUDEUMBIGA1UEAxMLTmlscyBLbmFmbGExKjAoBgkqhkiG9w0BCQEWG0RyLk5pbHMuS25hZmxhQHRrLW9ubGluZS5kZTAeFw0wNzA2MjkxNzQ2MzBaFw0wODA2MjgxNzQ2MzBaMFExCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMQswCQYDVQQKEwJUSzELMAkGA1UECxMCSVAxFjAUBgNVBAMTDUhhcnJpcyBLbmFmbGEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJMjAnKFGjXjbPbi4X1vnI/H7ArNfayvHO7+QbuV1FqIR+aZuAYZeR5v0s8NKyGOcMxscAQk59ZrdfqaaIiwtcXk2fNHphtSVqLqR4NLWO2qxJKXwBcAxIn7byjq/DqjiUr5nmw1cMWJtK1xwB6pVMvCv97KGg2Z8peronBxg6mVAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRaMTzoUhWt1wguyvPlPuUUV8VRtTAfBgNVHSMEGDAWgBQuZ2A4G1XF+GvL7vaiZst6RUCqYjANBgkqhkiG9w0BAQUFAAOBgQAr3rtJIVNchr3pMEfFcSzbJJWo/c0LRkUnWkP1gD6fMqLoLFUbl8k6tKJ9V4P0Oe2BODRIfNyTFjKLzD1lHAFFRz9pzYUx+hq4VDWooA3MsewNDDyJwupivlmHcM+Y8Cv97q9pERiqAY88TRMZxntl/b98W61KARAO+HUDhTnA1g==</wsse:BinarySecurityToken><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature-8331318"> <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-28000914"> <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>Q2LregRFO//cXlkcThu9Bx0jal4=</ds:DigestValue> </ds:Reference> <ds:Reference URI="#id-10464309"> <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>BX651XEWk4u4pGgshQhocYxPkSo=</ds:DigestValue> </ds:Reference> <ds:Reference URI="#Timestamp-7651652"> <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>ezisLn/pGWNqMHbT6UlHyM4Ez64=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> Xl4SSEwrtyUnsqf8xOmfzojLLU18tOrikOhK+HRyqHqv0lPF+AqANLU6yygNdhbfI5qyef9BLr6I CmSPIX4QQR+Hq45l/Ewa+M2K1OOjqvBUGYyQqrKCqUFtsISr9xPudB8ZmaVfaUu5chjIvy/sPYYx TuYv2Ma6uEwek1YZpbE= </ds:SignatureValue> <ds:KeyInfo Id="KeyId-1823783"> <wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-17125267"><wsse:Reference URI="#CertId-3596382" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" /></wsse:SecurityTokenReference> </ds:KeyInfo> </ds:Signature><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-7651652"><wsu:Created>2007-10-31T10:16:00.474Z</wsu:Created><wsu:Expires>2007-10-31T10:21:00.474Z</wsu:Expires></wsu:Timestamp></wsse:Security><TelematikHeader xmlns="http://ws.gematik.de/Schema/Telematik/Transport/V1" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-10464309"><MessageID>urn:uuid:9E0D31C48FDB63BBCD11938257462232</MessageID><ConversationID /><ServiceLocalization><Type>VSD</Type><Provider>101575519</Provider></ServiceLocalization><MessageType><Component>VSD</Component><Operation>PerformUpdates</Operation></MessageType><RoleDataProcessor /></TelematikHeader><TransportHeader xmlns="http://ws.gematik.de/Schema/Telematik/Transport/V1"><InterfaceVersion>0.0.24.3</InterfaceVersion></TransportHeader></soapenv:Header><soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-28000914"><TelematikExecute xmlns="http://ws.gematik.de/Schema/Telematik/Transport/V1"><Payload Id="c623c3be-529b-4d6d-8f1e-a4a29660f344"><Parameter Encoding="base64"><Name>VSD</Name><Value>PFBlcmZvcm1VcGRhdGVzIHhtbG5zPSJodHRwOi8vd3MuZ2VtYXRpay5kZS9jbS9jYy9DbUNjU2VydmljZVJlcXVlc3QvdjEuMiIgeG1sbnM6djE9Imh0dHA6Ly93cy5nZW1hdGlrLmRlL2NtL2NvbW1vbi9DbUNvbW1vbi92MS4yIj4NCiAgPHYxOkljY3NuPjgwMjc2MDAxMDQwMDAwMDMwMjI5PC92MTpJY2Nzbj4NCiAgPHYxOlVwZGF0ZUlkPjAxPC92MTpVcGRhdGVJZD4NCjwvUGVyZm9ybVVwZGF0ZXM+</Value></Parameter><MessageID>urn:uuid:9E0D31C48FDB63BBCD11938257462232</MessageID><Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><Created>UNDO</Created></Timestamp><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI="#c623c3be-529b-4d6d-8f1e-a4a29660f344"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>XHIiHK4NYczByvAJSZH8u3hSvuQ=</DigestValue></Reference></SignedInfo><SignatureValue>JQnTQJ1TidrMuWmSmpHE3ZR5M728A3tlvKjrM3GxFPuy5YOmmybxR0T7xe72WSdWsqvFT9QGE+iP GL5POuc3s8lLc1QGZRKhZvjHAKFldDNyxAMWRL7ZXmhpjsRXT3HethKWew3669SKjJFkZ1IYEnZz QrJOmgt1MMjWx99CgaQ=</SignatureValue><KeyInfo><X509Data><X509SubjectName>CN=Harris Knafla,OU=IP,O=TK,ST=Hamburg,C=DE</X509SubjectName><X509Certificate>MIIC0DCCAjmgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMCREUxEDAOBgNVBAgT B0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxCzAJBgNVBAoTAlRLMQswCQYDVQQLEwJJUDEUMBIG A1UEAxMLTmlscyBLbmFmbGExKjAoBgkqhkiG9w0BCQEWG0RyLk5pbHMuS25hZmxhQHRrLW9ubGlu ZS5kZTAeFw0wNzA2MjkxNzQ2MzBaFw0wODA2MjgxNzQ2MzBaMFExCzAJBgNVBAYTAkRFMRAwDgYD VQQIEwdIYW1idXJnMQswCQYDVQQKEwJUSzELMAkGA1UECxMCSVAxFjAUBgNVBAMTDUhhcnJpcyBL bmFmbGEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJMjAnKFGjXjbPbi4X1vnI/H7ArNfayv HO7+QbuV1FqIR+aZuAYZeR5v0s8NKyGOcMxscAQk59ZrdfqaaIiwtcXk2fNHphtSVqLqR4NLWO2q xJKXwBcAxIn7byjq/DqjiUr5nmw1cMWJtK1xwB6pVMvCv97KGg2Z8peronBxg6mVAgMBAAGjezB5 MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl MB0GA1UdDgQWBBRaMTzoUhWt1wguyvPlPuUUV8VRtTAfBgNVHSMEGDAWgBQuZ2A4G1XF+GvL7vai Zst6RUCqYjANBgkqhkiG9w0BAQUFAAOBgQAr3rtJIVNchr3pMEfFcSzbJJWo/c0LRkUnWkP1gD6f MqLoLFUbl8k6tKJ9V4P0Oe2BODRIfNyTFjKLzD1lHAFFRz9pzYUx+hq4VDWooA3MsewNDDyJwupi vlmHcM+Y8Cv97q9pERiqAY88TRMZxntl/b98W61KARAO+HUDhTnA1g==</X509Certificate></X509Data></KeyInfo></Signature></Payload></TelematikExecute></soapenv:Body></soapenv:Envelope>
As you can see in the soap request on top of the xml signature there is a Webservice Security signature (WSSE) over three elements. This should be no problem altough WSSE adds the wsu:id attribute to the body element. WSSE was omitted in step 1 for simplicity.
I wonder that the attributes which have been set to the payloadElement are not part of the actual message. But it works!
Step 3:
The same request was sent to an external webservice server and the server reports a xml signature verification problem. I don't have any logs or further information. But I have to get this to work against this server.
Java Files for Create + Verify Signature. For Create I get a DOM Node from a XML Bean. For step 1 the attribute setting should be in comments. I use VerifySignature for step 1 + 2.
SignPayload.java:
package de.tk.signature;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.ExcC14NParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.apache.xmlbeans.XmlObject;
import de.tk.schemaTools.TkSchemaHandler;
import de.tk.util.ClientProperties;
public class SignPayload {
public static void signDocument(XmlObject telematikExecuteXmlObject, String payloadId) {
try {
// get Document
org.w3c.dom.Node node = telematikExecuteXmlObject.getDomNode();
Document documentTo = node.getOwnerDocument();
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
Reference ref = fac.newReference("#"+payloadId, fac.newDigestMethod(DigestMethod.SHA1, null), Collections.singletonList(fac
.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null, null);
// Create the SignedInfo.
SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Collections.singletonList(ref));
KeyStore keyStore = KeyStore.getInstance("JKS");
String keyStoreFilename = ClientProperties.getKeystorefile();
FileInputStream keyStoreFile = new FileInputStream(keyStoreFilename);
keyStore.load(keyStoreFile, "storePwd".toCharArray());
keyStoreFile.close();
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry("harris", new KeyStore.PasswordProtection("keyPwd".toCharArray()));
X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
// Create the KeyInfo containing the X509Data.
KeyInfoFactory kif = fac.getKeyInfoFactory();
List x509Content = new ArrayList();
x509Content.add(cert.getSubjectX500Principal().getName());
x509Content.add(cert);
X509Data xd = kif.newX509Data(x509Content);
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
Node payloadNode = new TkSchemaHandler().getNode(documentTo, "Payload");
String prefix = payloadNode.getPrefix();
NamedNodeMap nameNodeMap = payloadNode.getAttributes();
// String baseUri = payloadNode.getBaseURI(); not implemented
boolean attributes = payloadNode.hasAttributes();
Element payloadElement = (Element) payloadNode;
//xmlns is the prefix and first parameter the namespaceURI
// xmlns existiert ohne WSSE, beim Create XMLOutputter ausgegeben
payloadElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://ws.gematik.de/Schema/Telematik/Transport/V1");
// existiert ohne WSSE
// bei Create nicht; aber bei Verify im DigestOutputter mit drin
payloadElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
// existiert nur bei WSSE
payloadElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
Node timestampNode = new TkSchemaHandler().getNode(documentTo, "Timestamp");
Element timestampElement = (Element) timestampNode;
// existiert ohne WSSE
// beim Create Outputter angegeben sowie beim Verify
timestampElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
// existiert nur bei WSSE, war wohl nur notwendig da bei WSSE Signature auf falschen Timestamp zugegriffen worden ist.
// Create a DOMSignContext and specify the RSA PrivateKey and
// location of the resulting XMLSignature's parent element.
DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(),payloadNode);
// Create the XMLSignature, but don't sign it yet.
XMLSignature signature = fac.newXMLSignature(si, ki);
// DomInfo.visualize(document);
SAXBuilderDemo2.print(documentTo);
// Marshal, generate, and sign the enveloped signature.
signature.sign(dsc);
} catch (Exception exc) {
throw new RuntimeException(exc.getMessage());
}
}
}
VerifySignature.java:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class VerifySignature {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
String filename = args[0];
System.out.println("Verify Document: " + filename);
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf
.newDocumentBuilder()
.parse(
new FileInputStream(filename));
// Find Signature element.
// NodeList nl =
// doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
Node node = TkSchemaHandler.getNode(doc,"/*[local-name()='Envelope' and namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/']/*[local-name()='Body' and namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'][1]/*[local-name()='TelematikExecute' and namespace-uri()='http://ws.gematik.de/Schema/Telematik/Transport/V1'][1]/*[local-name()='Payload' and namespace-uri()='http://ws.gematik.de/Schema/Telematik/Transport/V1'][1]/*[local-name()='Signature' and namespace-uri()='http://www.w3.org/2000/09/xmldsig#'][1]");
/*
if (nl.getLength() == 0) {
throw new Exception("Cannot find Signature element");
}
Node node = nl.item(0); */
// Create a DOMValidateContext and specify a KeySelector
// and document context.
DOMValidateContext valContext = new DOMValidateContext
(new X509KeySelector(), node);
// Unmarshal the XMLSignature.
XMLSignature signature = fac.unmarshalXMLSignature(valContext);
// Validate the XMLSignature.
boolean coreValidity = signature.validate(valContext);
// sample 6
// Check core validation status.
if (coreValidity == false) {
System.err.println("Signature failed core validation");
boolean sv = signature.getSignatureValue().validate(valContext);
System.out.println("signature validation status: " + sv);
if (sv == false) {
// Check the validation status of each Reference.
Iterator i = signature.getSignedInfo().getReferences().iterator();
for (int j=0; i.hasNext(); j++) {
boolean refValid = ((Reference) i.next()).validate(valContext);
System.out.println("ref["+j+"] validity status: " + refValid);
}
}
} else {
System.out.println("OK! Signature passed core validation!");
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
Questions:
1. Do I really have to set all the namespace attributes? I thought with exclusive xml this should not be necessary. Is there any other solution?
2. Do you think I got all the settings right in SignPayload.java?
Thanks a lot in advance.
Cheers !
Nils