我有以下代码对输入XML文件进行数字签名。出于某种原因,它适用于Windows和Solaris,但无论XML内容是什么,它总是在AIX上失败。
public class Test {
public static void main(String[] args) throws Exception {
KeyStore keyStore = KeyStore.getInstance("JKS");
FileInputStream fileInputStream = new FileInputStream(args[0]);
keyStore.load(fileInputStream, "password".toCharArray());
String alias = keyStore.aliases().nextElement();
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, "password".toCharArray());
byte[] signed = createDigitalSignature(args[1], null, privateKey);
FileOutputStream fileOutputStream = new FileOutputStream(args[2]);
fileOutputStream.write(signed);
fileOutputStream.close();
}
public static byte[] createDigitalSignature(String inputFileName, String certificateFileName, PrivateKey privateKey) throws Exception {
XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
Transform transform = signatureFactory.newTransform("http://www.w3.org/2001/10/xml-exc-c14n#", (TransformParameterSpec) null);
Reference reference = signatureFactory.newReference("#XXX", signatureFactory.newDigestMethod("http://www.w3.org/2001/04/xmlenc#sha256", null), Collections.singletonList(transform), null, null);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
Document document = documentBuilderFactory.newDocumentBuilder().parse(new FileInputStream(inputFileName));
XMLStructure structure = new DOMStructure(document.getDocumentElement());
XMLObject object = signatureFactory.newXMLObject(Collections.singletonList(structure), "XXX", null, null);
SignatureMethod signatureMethod = signatureFactory.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null);
CanonicalizationMethod canonicalizationMethod = signatureFactory.newCanonicalizationMethod("http://www.w3.org/2001/10/xml-exc-c14n#", (C14NMethodParameterSpec)null);
SignedInfo signedInfo = signatureFactory.newSignedInfo(canonicalizationMethod, signatureMethod, Collections.singletonList(reference));
KeyInfo keyInfo = null;
if (certificateFileName != null) {
FileInputStream fileInputStream = new FileInputStream(certificateFileName);
CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate) factory.generateCertificate(fileInputStream);
ArrayList<Object> x509Content = new ArrayList<Object>();
x509Content.add(certificate.getSubjectX500Principal().getName());
x509Content.add(certificate);
KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
X509Data xd = keyInfoFactory.newX509Data(x509Content);
keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(xd));
}
XMLSignature signature = signatureFactory.newXMLSignature(signedInfo, keyInfo, Collections.singletonList(object), null, null);
DOMSignContext signContext = new DOMSignContext(privateKey, document);
signature.sign(signContext);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
transformer.transform(new DOMSource(document), new StreamResult(byteArrayOutputStream));
return byteArrayOutputStream.toByteArray();
}
}
我得到的例外是:
Exception in thread "main" org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at org.apache.xerces.dom.CoreDocumentImpl.insertBefore(Unknown Source)
at com.ibm.xml.crypto.dsig.dom.XMLSignatureImpl.sign(XMLSignatureImpl.java:158)
它被抛出线:signature.sign(signContext);
可能是什么问题?我有一个像
这样简单的XML文件<?xml version="1.0" encoding="UTF-8" ?>
<a>
</a>
但它仍然失败,仅在AIX上!