我在使用Apache xmlsec库对XML文档进行数字签名时遇到了一些麻烦。基于很少的文档和网上的一些例子,我把以下代码放在一起:
public class SOAPTester
{
private static final TransformerFactory transformerFactory = TransformerFactory.newInstance();
public static void main(String[] args)
{
//RESOURCES
String uuid = UUID.randomUUID().toString();
File soapFile = null;
File ksFile = null;
FileInputStream fis = null;
MessageFactory mf = null;
SOAPMessage msg = null;
XMLSignatureFactory sf = null;
XMLSignature sig = null;
X509CertificateDetails x5dts = null;
try
{
//INITIALIZE THE SIGNING LIBRARY
if(!Init.isInitialized()) Init.init();
System.out.println("SOAPTester.main: Initialized Santuario.");
//GET INPUT SOAP MESSAGE
soapFile = new File("SOAPTEST.xml");
fis = new FileInputStream(soapFile);
//CONSTRUCT SOAP ENVELOPE
mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
msg = mf.createMessage(null, fis);
IOUtils.closeQuietly(fis);
System.out.println("SOAPTester.main: Parsed SOAPMessage from File.");
//LOAD KEYSTORE
ksFile = new File("xml-sign.jks");
x5dts = Cryptographer.loadXMLSigningCertificate(ksFile);
System.out.println("SOAPTester.main: Loaded KeyStore.");
//VALIDATE MESSAGE
if(msg != null)
{
System.out.println("SOAPTester.main: SOAPMessage Valid.");
//INITIALIZE SIGNATURE MECHANISM
sig = new XMLSignature(msg.getSOAPPart(), "", XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256, Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
//TIMESTAMP REFERENCE
InclusiveNamespaces tsin = new InclusiveNamespaces(msg.getSOAPPart(), "wse wsa soapenv air com hdr sec req");
Transforms tsts = new Transforms(msg.getSOAPPart());
tsts.setSecureValidation(true);
tsts.addTransform(Transforms.TRANSFORM_C14N_EXCL_WITH_COMMENTS, tsin.getElement());
sig.addDocument("#TS-5bbb45be-0a0b-482a-8214-edf06bf70ea7", tsts, "http://www.w3.org/2001/04/xmldsig-more#sha384");
//MANIFEST REFERENCE
InclusiveNamespaces mhin = new InclusiveNamespaces(msg.getSOAPPart(), "wse wsa soapenv com hdr sec req");
Transforms mhts = new Transforms(msg.getSOAPPart());
mhts.setSecureValidation(true);
mhts.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS, mhin.getElement());
sig.addDocument("#MH-5bbb45be-0a0b-482a-8214-edf06bf70ea7", mhts, "http://www.w3.org/2001/04/xmldsig-more#sha384");
//BUSINESS HEADER REFERENCE
InclusiveNamespaces bhin = new InclusiveNamespaces(msg.getSOAPPart(), "wse wsa soapenv air com sec req");
Transforms bhts = new Transforms(msg.getSOAPPart());
bhts.setSecureValidation(true);
bhts.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS, bhin.getElement());
sig.addDocument("#BH-5bbb45be-0a0b-482a-8214-edf06bf70ea7", bhts, "http://www.w3.org/2001/04/xmldsig-more#sha384");
//TODO: SIGN MESSAGE
sig.sign(x5dts.getPrivateKey());
sig.addKeyInfo(x5dts.getX509Certificate());
System.out.println("SOAPTester.main: SOAPMessage Signed.");
XMLUtils.outputDOM(sig.getElement(), System.out);
}else
System.out.println("SOAPTester.main: Unable to Parse SOAP File.");
}catch(SOAPException | IOException | XMLSecurityException | CryptographyException e)
{
e.printStackTrace();
}finally
{
uuid = null;
soapFile = null;
IOUtils.closeQuietly(fis);
fis = null;
mf = null;
msg = null;
}
}
这是包含我要签名的元素的文件:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:air="urn:us:gov:treasury:irs:ext:aca:air:ty17" xmlns:com="urn:us:gov:treasury:irs:common" xmlns:hdr="urn:us:gov:treasury:irs:msg:acabusinessheader" xmlns:req="urn:us:gov:treasury:irs:msg:irsacabulkrequesttransmitter">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wse="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">
<wse:Security>
<wsu:Timestamp wsu:Id="TS-5bbb45be-0a0b-482a-8214-edf06bf70ea7">
<wsu:Created>2018-03-19T19:39:10Z</wsu:Created>
<wsu:Expires>2018-03-19T19:49:10Z</wsu:Expires>
</wsu:Timestamp>
</wse:Security>
<air:ACATransmitterManifestReqDtl wsu:Id="MH-5bbb45be-0a0b-482a-8214-edf06bf70ea7">
<air:PaymentYr>2017</air:PaymentYr>
<air:PriorYearDataInd>0</air:PriorYearDataInd>
<com:EIN>999999999</com:EIN>
<air:TransmissionTypeCd>O</air:TransmissionTypeCd>
<air:TestFileCd>T</air:TestFileCd>
<air:TransmitterForeignEntityInd>0</air:TransmitterForeignEntityInd>
<air:TransmitterNameGrp>
<air:BusinessNameLine1Txt>ETC</air:BusinessNameLine1Txt>
</air:TransmitterNameGrp>
<air:CompanyInformationGrp>
<air:CompanyNm>ETC</air:CompanyNm>
<air:MailingAddressGrp>
<air:USAddressGrp>
<air:AddressLine1Txt>StreetAddress</air:AddressLine1Txt>
<com:CityNm>San Antonio</com:CityNm>
<air:USStateCd>TX</air:USStateCd>
<com:USZIPCd>78232</com:USZIPCd>
</air:USAddressGrp>
</air:MailingAddressGrp>
<air:ContactNameGrp>
<air:PersonFirstNm>FName</air:PersonFirstNm>
<air:PersonMiddleNm>J</air:PersonMiddleNm>
<air:PersonLastNm>MName</air:PersonLastNm>
</air:ContactNameGrp>
<air:ContactPhoneNm>1202101212</air:ContactPhoneNm>
</air:CompanyInformationGrp>
<air:VendorInformationGrp>
<air:VendorCd>I</air:VendorCd>
<air:ContactNameGrp>
<air:PersonFirstNm>FName</air:PersonFirstNm>
<air:PersonMiddleNm>J</air:PersonMiddleNm>
<air:PersonLastNm>LName</air:PersonLastNm>
</air:ContactNameGrp>
<air:ContactPhoneNm>2102101212</air:ContactPhoneNm>
</air:VendorInformationGrp>
<air:TotalPayeeRecordCnt>2</air:TotalPayeeRecordCnt>
<air:TotalPayerRecordCnt>1</air:TotalPayerRecordCnt>
<air:SoftwareId>17A0000000</air:SoftwareId>
<air:FormTypeCd>1094/1095B</air:FormTypeCd>
<com:BinaryFormatCd>application/xml</com:BinaryFormatCd>
<com:ChecksumAugmentationNum>de2d47ac82b0dd09c8a7d531b93c71c2</com:ChecksumAugmentationNum>
<com:AttachmentByteSizeNum>6346</com:AttachmentByteSizeNum>
<air:DocumentSystemFileNm>1094B_Request_BB06G_20180319T143910629Z.xml</air:DocumentSystemFileNm>
</air:ACATransmitterManifestReqDtl>
<hdr:ACABusinessHeader wsu:Id="BH-5bbb45be-0a0b-482a-8214-edf06bf70ea7">
<air:UniqueTransmissionId>5bbb45be-0a0b-482a-8214-edf06bf70ea7:SYS12:BB00X::T</air:UniqueTransmissionId>
<com:Timestamp>2018-03-19T19:39:10Z</com:Timestamp>
</hdr:ACABusinessHeader>
<wsa:Action>BulkRequestTransmitterService</wsa:Action>
</soapenv:Header>
<soapenv:Body xmlns:xop="http://www.w3.org/2004/08/xop/include">
<req:ACABulkRequestTransmitter version="1.0">
<com:BulkExchangeFile>
<xop:Include href="cid:1094B_Request_BB06G_20180319T143910629Z.xml" />
</com:BulkExchangeFile>
</req:ACABulkRequestTransmitter>
</soapenv:Body>
我们需要使用定义的wsu:Id值来签署这三个部分,但是当我调用XMLSignature.sign时,这就是我得到的:
SOAPTester.main: Initialized Santuario.
SOAPTester.main: Parsed SOAPMessage from File.
SOAPTester.main: Loaded KeyStore.
SOAPTester.main: SOAPMessage Valid.
org.apache.xml.security.signature.ReferenceNotInitializedException:
Could not find a resolver for URI TS-5bbb45be-0a0b-482a-8214-edf06bf70ea7 and Base
Original Exception was org.apache.xml.security.utils.resolver.ResourceResolverException: Could not find a resolver for URI TS-5bbb45be-0a0b-482a-8214-edf06bf70ea7 and Base
at org.apache.xml.security.signature.Reference.getContentsBeforeTransformation(Reference.java:432)
at org.apache.xml.security.signature.Reference.calculateDigest(Reference.java:717)
at org.apache.xml.security.signature.Reference.generateDigestValue(Reference.java:409)
at org.apache.xml.security.signature.Manifest.generateDigestValues(Manifest.java:205)
at org.apache.xml.security.signature.XMLSignature.sign(XMLSignature.java:640)
at com.etc.test.SOAPTester.main(SOAPTester.java:108)
Caused by: org.apache.xml.security.utils.resolver.ResourceResolverException: Could not find a resolver for URI TS-5bbb45be-0a0b-482a-8214-edf06bf70ea7 and Base
at org.apache.xml.security.utils.resolver.ResourceResolver.internalGetInstance(ResourceResolver.java:113)
at org.apache.xml.security.utils.resolver.ResourceResolver.getInstance(ResourceResolver.java:169)
at org.apache.xml.security.signature.Reference.getContentsBeforeTransformation(Reference.java:425)
... 5 more
显然,我错过了一些关于如何告诉图书馆文件元素需要签名的内容,但我无法弄清楚如何做到这一点。我试图首先获得基本签名,但最终,这是我们试图让它产生的:
<wsse:Security 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">
<ds:Signature Id="SIG-E68EBBF1696C5DD4AA143353323390579" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#TS-E68EBBF1696C5DD4AA143353323390073">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces PrefixList="wsse wsa soapenv urn urn1 urn2 urn3" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>?TimestampDigestValue?</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#id-E68EBBF1696C5DD4AA143353323390577">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces PrefixList="wsa soapenv urn1 urn2 urn3" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>?ACATransmitterManifestReqDtlDigestValue?
</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#id-E68EBBF1696C5DD4AA143353323390578">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces PrefixList="wsa soapenv urn urn1 urn3" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>?ACABusinessHeaderDigestValue?</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>?SignatureValue?</ds:SignatureValue>
<ds:KeyInfo Id="KI-E68EBBF1696C5DD4AA143353323390475">
<wsse:SecurityTokenReference wsu:Id="STR-E68EBBF1696C5DD4AA143353323390476">
<wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wsssoap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509- token-profile-1.0#X509v3">?CertificateValue?</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<wsu:Timestamp wsu:Id="TS-E68EBBF1696C5DD4AA143353323390073">
<wsu:Created>2016-03-05T19:40:33.900Z</wsu:Created>
<wsu:Expires>2016-03-05T19:50:33.900Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
非常感谢任何帮助。