我在Java 1.6中做了一些xml签名,但是当我在Java 1.7中运行相同的例子时,我得到了这种异常:
javax.xml.crypto.dsig.XMLSignatureException:
javax.xml.crypto.URIReferenceException:
com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException:
Cannot resolve element with ID data
我的xml:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:fu="http://www.fu.gov.si/" xmlns:xd="http://www.w3.org/2000/09/xmldsig#">
<soapenv:Body>
<fu:BusinessPremiseRequest Id="data">
<fu:Header>
<fu:MessageID>24A4BACB-2355-0564-E053-AB02010AD740</fu:MessageID>
<fu:DateTime>2015-11-16T09:22:58</fu:DateTime>
</fu:Header>
</fu:BusinessPremiseRequest>
</soapenv:Body>
</soapenv:Envelope>
这是我的源代码:
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
Document doc = (Document) dbFactory.newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes()));
NodeList nl = doc.getElementsByTagName("fu:BusinessPremiseRequest");
Node node = nl.item(0);
KeyStore p12 = KeyStore.getInstance("pkcs12");
p12.load(new FileInputStream("c:/cert/testfurs.p12"), "Geslo123#".toCharArray());
Enumeration e = p12.aliases();
String alias = (String) e.nextElement();
System.out.println("Alias certifikata:" + alias);
Key privateKey = p12.getKey(alias, "Geslo123#".toCharArray());
KeyStore.PrivateKeyEntry keyEntry
= (KeyStore.PrivateKeyEntry) p12.getEntry(alias, new KeyStore.PasswordProtection("Geslo123#".toCharArray()));
X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
PublicKey publicKey = cert.getPublicKey();
final XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
// Create a Reference to the enveloped document
Reference ref = sigFactory.newReference("#data",
sigFactory.newDigestMethod(DigestMethod.SHA256, null),
Collections.singletonList(sigFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)),
null,
null);
SignedInfo si = sigFactory.newSignedInfo(sigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null), sigFactory.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null), Collections.singletonList(ref));
// Create a KeyValue containing the RSA PublicKey
KeyInfoFactory keyInfoFactory = sigFactory.getKeyInfoFactory();
X509IssuerSerial x509IssuerSerial = keyInfoFactory.newX509IssuerSerial(cert.getSubjectX500Principal().getName(), cert.getSerialNumber());
List x509Content = new ArrayList();
x509Content.add(cert.getSubjectX500Principal().getName());
x509Content.add(x509IssuerSerial);
KeyValue keyValue = keyInfoFactory.newKeyValue(publicKey);
X509Data xd = keyInfoFactory.newX509Data(x509Content);
// Create a KeyInfo and add the KeyValue to it
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(xd));
// Create a DOMSignContext and specify the RSA PrivateKey and
// location of the resulting XMLSignature's parent element
DOMSignContext dsc = new DOMSignContext(
privateKey,
node
);
答案 0 :(得分:2)
尝试这样(来源:https://slo-tech.com/forum/t652679/449):
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
Document doc = (Document) dbFactory.newDocumentBuilder().parse(new ByteArrayInputStream(vhodniXml.getBytes()));
//Node node = doc.getElementsByTagName("fu:BusinessPremiseRequest").item(0);
Enumeration e = p12.aliases();
String alias = (String) e.nextElement();
System.out.println("Alias certifikata:" + alias);
Key privateKey = p12.getKey(alias, geslo.toCharArray());
KeyStore.PrivateKeyEntry keyEntry
= (KeyStore.PrivateKeyEntry) p12.getEntry(alias, new KeyStore.PasswordProtection(geslo.toCharArray()));
X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
PublicKey publicKey = cert.getPublicKey();
final XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
// Create a Reference to the enveloped document
Reference ref = sigFactory.newReference("#data",
sigFactory.newDigestMethod(DigestMethod.SHA256, null),
Collections.singletonList(sigFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)),
null,
null);
SignedInfo si = sigFactory.newSignedInfo(sigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null), sigFactory.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null), Collections.singletonList(ref));
// Create a KeyValue containing the RSA PublicKey
KeyInfoFactory keyInfoFactory = sigFactory.getKeyInfoFactory();
X509IssuerSerial x509IssuerSerial = keyInfoFactory.newX509IssuerSerial(cert.getSubjectX500Principal().getName(), cert.getSerialNumber());
List x509Content = new ArrayList();
x509Content.add(cert.getSubjectX500Principal().getName());
x509Content.add(x509IssuerSerial);
KeyValue keyValue = keyInfoFactory.newKeyValue(publicKey);
X509Data xd = keyInfoFactory.newX509Data(x509Content);
// Create a KeyInfo and add the KeyValue to it
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(xd));
NodeList nl = doc.getElementsByTagName("fu:BusinessPremiseRequest");
Node node = nl.item(0);
// Create a DOMSignContext and specify the RSA PrivateKey and
// location of the resulting XMLSignature's parent element
DOMSignContext dsc = new DOMSignContext(
privateKey,
node
);
((Element) node).setIdAttribute("Id", true);
// Create the XMLSignature (but don't sign it yet)
XMLSignature signature = sigFactory.newXMLSignature(si, keyInfo);
// Marshal, generate (and sign) the enveloped signature
signature.sign(dsc);