问题
I have the following codes which digitally signs an input XML file. For some reason, it works on Windows and Solaris, but it always fail on AIX no matter what the XML content is.
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();
}
}
The exception that I'm getting is:
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)
It's thrown at the line: signature.sign(signContext);
What could be the problem? I have an XML file as simple as
<?xml version="1.0" encoding="UTF-8" ?>
<a>
</a>
but it still fails, only on AIX!
来源:https://stackoverflow.com/questions/28670003/digital-signing-code-fails-only-on-aix