Java相当于C#XML签名方法

我编写了以下.NET Framework 3.5 C#方法,该方法获取XML文档的位置和X509数字证书的对象表示(使用私钥),并将XML文档作为对象返回,并嵌入XML签名(XMLDsig)作为根的第一个子元素。

问题是我需要能够使用Java SE 6执行完全相同的过程,但我还没有编写任何Java,并且不知道从哪里开始。

任何人都可以在Java代码中提供产生完全相同 XML输出的等效方法吗?

private static XmlDocument SignXmlDocument(string xmlFilePath, X509Certificate2 certificate) { // load xml from disk preserving whitespaces XmlDocument xmlDocument = new XmlDocument { PreserveWhitespace = true }; xmlDocument.Load(xmlFilePath); // create signed xml with a same-document reference containing an enveloped-signature transform SignedXml signedXml = new SignedXml(xmlDocument) { SigningKey = certificate.PrivateKey }; Reference reference = new Reference { Uri = "" }; XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(env); signedXml.AddReference(reference); // embed public key information for signature validation purposes KeyInfo keyInfo = new KeyInfo(); KeyInfoX509Data keyInfoX509Data = new KeyInfoX509Data(certificate, X509IncludeOption.ExcludeRoot); keyInfo.AddClause(keyInfoX509Data); signedXml.KeyInfo = keyInfo; // compute and retreive the signature xml signedXml.ComputeSignature(); XmlElement xmldsigXmlElement = signedXml.GetXml(); // insert the signature xml into the xml document as first child of the root element xmlDocument.DocumentElement.PrependChild(xmlDocument.ImportNode(xmldsigXmlElement, true)); return xmlDocument; } 

以下在Java中做同样的事情。 它需要磁盘上的PKCS12证书文件。

 import java.util.*; import java.io.*; import java.security.KeyStore; import java.security.KeyStore.PrivateKeyEntry; import java.security.cert.X509Certificate; import javax.xml.crypto.dsig.*; import javax.xml.crypto.dsig.dom.DOMSignContext; import javax.xml.crypto.dsig.keyinfo.*; import javax.xml.crypto.dsig.spec.*; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; public class XMLSigner { public static void signXmlDocumentOnDisk(String fileToBeSignedPath, String signedFileSavePath, String pkcs12CertificateFilePath, String password) throws Exception { XMLSignatureFactory fac = getXMLSignatureFactory(); Reference ref = getSHA1WholeDocumentEnvelopedTransformReference(fac); SignedInfo si = getSignedInfo(fac, ref); PrivateKeyEntry keyEntry = loadPKCS12KeyStoreAndGetSigningKeyEntry(pkcs12CertificateFilePath, password); KeyInfo ki = getKeyInfoWithX509Data(keyEntry, fac); Document doc = instantiateDocumentToBeSigned(fileToBeSignedPath); signDocumentAndPlaceSignatureAsFirstChildElement(doc, keyEntry, fac, si, ki); writeResultingDocument(doc, signedFileSavePath); } private static XMLSignatureFactory getXMLSignatureFactory() { return XMLSignatureFactory.getInstance("DOM"); } private static Reference getSHA1WholeDocumentEnvelopedTransformReference(XMLSignatureFactory fac) throws Exception { return fac.newReference( "", fac.newDigestMethod(DigestMethod.SHA1, null), Collections.singletonList(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null, null ); } private static SignedInfo getSignedInfo(XMLSignatureFactory fac, Reference ref) throws Exception { return fac.newSignedInfo( fac.newCanonicalizationMethod( CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null ), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref) ); } private static PrivateKeyEntry loadPKCS12KeyStoreAndGetSigningKeyEntry(String pkcs12CertificateFilePath, String password) throws Exception { KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(new FileInputStream(pkcs12CertificateFilePath), password.toCharArray()); return (PrivateKeyEntry)ks.getEntry(ks.aliases().nextElement(), new KeyStore.PasswordProtection(password.toCharArray())); } private static KeyInfo getKeyInfoWithX509Data(PrivateKeyEntry keyEntry, XMLSignatureFactory fac) { X509Certificate cert = (X509Certificate) keyEntry.getCertificate(); KeyInfoFactory kif = fac.getKeyInfoFactory(); List x509Content = new ArrayList(); x509Content.add(cert.getSubjectX500Principal().getName()); x509Content.add(cert); X509Data xd = kif.newX509Data(x509Content); return kif.newKeyInfo(Collections.singletonList(xd)); } private static Document instantiateDocumentToBeSigned(String fileToBeSignedPath) throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); return dbf.newDocumentBuilder().parse(new FileInputStream(fileToBeSignedPath)); } private static void signDocumentAndPlaceSignatureAsFirstChildElement(Document doc, PrivateKeyEntry keyEntry, XMLSignatureFactory fac, SignedInfo si, KeyInfo ki) throws Exception { DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc.getDocumentElement(), doc.getDocumentElement().getFirstChild()); XMLSignature signature = fac.newXMLSignature(si, ki); signature.sign(dsc); } private static void writeResultingDocument(Document doc, String signedFileSavePath) throws Exception { OutputStream os = new FileOutputStream(signedFileSavePath); TransformerFactory tf = TransformerFactory.newInstance(); Transformer trans = tf.newTransformer(); trans.transform(new DOMSource(doc), new StreamResult(os)); } } 

查看Java XML数字签名API: http : //java.sun.com/developer/technicalArticles/xml/dig_signature_api/

 public static bool VerifyXml(string fileNFe) { //carregar o XML da NF-e XmlDocument xml = new XmlDocument(); xml.PreserveWhitespace = true; xml.Load(fileNFe); //pegar a Tag "NFe", à que contem assinatura dig. XmlNodeList nodeNFe = xml.GetElementsByTagName("NFe"); string NFe = nodeNFe[0].OuterXml.ToString(); //carregar o XML da NFe XmlDocument xmlNFe = new XmlDocument(); xmlNFe.PreserveWhitespace = true; xmlNFe.LoadXml(NFe); //Carregar a assinatura SignedXml signedXml = new SignedXml(xmlNFe); XmlNodeList nodeList = xmlNFe.GetElementsByTagName("Signature"); signedXml.LoadXml((XmlElement)nodeList[0]); //buscar o KeyInfo da assinatura IEnumerator keyInfoItems = signedXml.KeyInfo.GetEnumerator(); keyInfoItems.MoveNext(); KeyInfoX509Data keyInfoX509 = (KeyInfoX509Data)keyInfoItems.Current; //buscar o certificado do KeyInfo X509Certificate2 keyInfoCert = (X509Certificate2)keyInfoX509.Certificates[0]; //Validar se assinatura é valida bool isSigValid = signedXml.CheckSignature(keyInfoCert.PublicKey.Key); if (isSigValid) { MessageBox.Show("Assinatura digital é válida."); return true; } else { MessageBox.Show("Assinatura digital não é válida."); return false; } }