gpt4 book ai didi

c# - Java 等效于 C# XML 签名方法

转载 作者:数据小太阳 更新时间:2023-10-29 01:56:48 28 4
gpt4 key购买 nike

我编写了以下 .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));
}
}

关于c# - Java 等效于 C# XML 签名方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5330049/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com