相当于Java C#XML签名法 [英] Java equivalent of C# XML signing method

查看:230
本文介绍了相当于Java C#XML签名法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了下面的.NET Framework 3.5的C#方法,需要一个XML文档和X509数字证书的对象表示(与私钥)的位置,并返回XML文档的XML签名的对象( XMLDSIG)嵌入根的第一个子元素。



的事情是,我direly需要能够做同样的程序与Java SE 6中,但我有不是写在年龄任何Java和不知道从哪里开始。



任何人都可以提供在Java代码中的对应方法产生的的确切的相同XML输出​​?

 私有静态的XmlDocument SignXmlDocument(字符串xmlFilePath,X509Certificate2证书)
{
//负荷从磁盘保留空格
XmlDocument的XmlDocument的XML =新的XmlDocument {PreserveWhitespace =真};
XMLDocument.load方法(xmlFilePath);

//创建一个包含笼罩签名变换
SignedXml signedXml =新SignedXml(XMLDOCUMENT){SigningKey = certificate.PrivateKey}同一文档的参考签名的XML;
参考参考=新的参考{乌里=};
XmlDsigEnvelopedSignatureTransform ENV =新XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(ENV);
signedXml.AddReference(参考);

//嵌入公钥信息,签名验证的目的
的密钥信息的密钥信息=新的密钥信息();
KeyInfoX509Data keyInfoX509Data =新KeyInfoX509Data(证书,X509IncludeOption.ExcludeRoot);
keyInfo.AddClause(keyInfoX509Data);
signedXml.KeyInfo =密钥信息;

//计算从其获取签名XML
signedXml.ComputeSignature();
的XmlElement xmldsigXmlElement = signedXml.GetXml();

//插入签名XML到XML文档的根元素
xmlDocument.DocumentElement.PrependChild的第一个孩子(xmlDocument.ImportNode(xmldsigXmlElement,真实));

返回XmlDocument的;
}


解决方案

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

 进口的java.util。*; 
进口java.io. *;
进口java.security.KeyStore中;
进口java.security.KeyStore.PrivateKeyEntry;
进口java.security.cert.X509Certificate;
进口javax.xml.crypto.dsig中的*。
进口javax.xml.crypto.dsig.dom.DOMSignContext;
进口javax.xml.crypto.dsig.keyinfo *。
进口javax.xml.crypto.dsig.spec中*。
进口javax.xml.parsers.DocumentBuilderFactory中;
进口javax.xml.transform中*。
进口javax.xml.transform.dom.DOMSource中;
javax.xml.transform.stream.StreamResult中的进口;
org.w3c.dom.Document中的进口;

公共类XMLSigner {

公共静态无效signXmlDocumentOnDisk(字符串fileToBeSignedPath,字符串signedFileSavePath,字符串pkcs12CertificateFilePath,字符串密码)抛出异常{
面对XMLSignatureFactory FAC = getXMLSignatureFactory() ;
基准REF = getSHA1WholeDocumentEnvelopedTransformReference(FAC);
的SignedInfo SI = getSignedInfo(FAC,REF);
PrivateKeyEntry keyentry指南= loadPKCS12KeyStoreAndGetSigningKeyEntry(pkcs12CertificateFilePath,密码);
的密钥信息き= getKeyInfoWithX509Data(keyentry指南,FAC);
文档的DOC = instantiateDocumentToBeSigned(fileToBeSignedPath);
signDocumentAndPlaceSignatureAsFirstChildElement(DOC,keyentry指南,FAC,SI,KI);
writeResultingDocument(DOC,signedFileSavePath);
}

私有静态面对XMLSignatureFactory getXMLSignatureFactory(){
返回XMLSignatureFactory.getInstance(DOM);
}

私有静态参考getSHA1WholeDocumentEnvelopedTransformReference(面对XMLSignatureFactory FAC)抛出异常{
返回
fac.newReference(

FAC。 newDigestMethod(DigestMethod.SHA1,空),
Collections.singletonList(fac.newTransform(Transform.ENVELOPED,(TransformParameterSpec)NULL)),
空,

);
}

私有静态的SignedInfo getSignedInfo(FAC面对XMLSignatureFactory,参考文献)抛出异常{
返回
fac.newSignedInfo(
fac.newCanonicalizationMethod(
CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec)空

fac.newSignatureMethod(SignatureMethod.RSA_SHA1,空),
Collections.singletonList(REF)
) ;
}

私有静态PrivateKeyEntry loadPKCS12KeyStoreAndGetSigningKeyEntry(字符串pkcs12CertificateFilePath,字符串密码)抛出异常{
密钥库KS = KeyStore.getInstance(PKCS12);
ks.load(新的FileInputStream(pkcs12CertificateFilePath),password.toCharArray());
回报(PrivateKeyEntry)ks.getEntry(ks.aliases()nextElement(),新KeyStore.PasswordProtection(password.toCharArray()));
}

私有静态密钥信息getKeyInfoWithX509Data(PrivateKeyEntry keyentry指南,面对XMLSignatureFactory FAC){
的X509Certificate证书=(x509证书)keyEntry.getCertificate();
KeyInfoFactory的KIF = fac.getKeyInfoFactory();
名单x509Content =新的ArrayList();
x509Content.add(cert.getSubjectX500Principal()的getName());
x509Content.add(CERT);
X509Data XD = kif.newX509Data(x509Content);
返回kif.newKeyInfo(Collections.singletonList(XD));
}

私有静态文档instantiateDocumentToBeSigned(字符串fileToBeSignedPath)抛出异常{
的DocumentBuilderFactory DBF = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(真);
返回dbf.newDocumentBuilder()解析(新的FileInputStream(fileToBeSignedPath));
}

私有静态无效signDocumentAndPlaceSignatureAsFirstChildElement(DOC文件,PrivateKeyEntry keyentry指南,面对XMLSignatureFactory FAC,SI的SignedInfo,密钥信息き)抛出异常{
DOMSignContext DSC =新DOMSignContext(keyEntry.getPrivateKey( ),doc.getDocumentElement(),doc.getDocumentElement()getFirstChild())。
的XMLSignature签名= fac.newXMLSignature(SI,KI);
signature.sign(DSC);
}

私有静态无效writeResultingDocument(DOC文件,字符串signedFileSavePath)抛出异常{
的OutputStream OS =新的FileOutputStream(signedFileSavePath);
的TransformerFactory TF = TransformerFactory.newInstance();
变压器反= tf.newTransformer();
trans.transform(新DOMSource的(文件),新的StreamResult(OS));
}
}


I have written the following .NET Framework 3.5 C# method which takes the location of an XML document and an object representation of an X509 digital certificate (with a private key) and returns the XML document as an object with the XML Signature (XMLDsig) embedded as first child element of the root.

The thing is that I direly need to be able to do the exact same procedure with Java SE 6, but I have not written any Java in ages and have no clue where to begin.

Can anyone provide the equivalent method in Java code that produces the exact same XML output?

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;
}

解决方案

The following does the same thing in Java. It requires a PKCS12 certificate file on disk.

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 C#XML签名法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆