java - 如何使用x509证书生成数字签名?

标签 java xml x509certificate digital-signature digital-certificate

我们如何获取 x509data 和 x509certificate 标记并将其附加到由以下代码生成的 xml

 String providerName = System.getProperty("jsr105Provider",
   "org.jcp.xml.dsig.internal.dom.XMLDSigRI");

 XMLSignatureFactory fac =
   XMLSignatureFactory.getInstance("DOM",
   (Provider) Class.forName(providerName).newInstance());

 Reference ref =
   fac.newReference("",
       fac.newDigestMethod(DigestMethod.SHA1, null),
           Collections.singletonList(
               fac.newTransform(Transform.ENVELOPED,(XMLStructure) null)), 
       null, null);

   SignedInfo si = fac.newSignedInfo
       (fac.newCanonicalizationMethod
         (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, 
            (XMLStructure) null), 
        fac.newSignatureMethod(SignatureMethod.RSA_SHA1, 
            null),
        Collections.singletonList(ref));

   KeyPairGenerator kpg = 
       KeyPairGenerator.getInstance("RSA");
   kpg.initialize(512);
   KeyPair kp = kpg.generateKeyPair();

   KeyInfoFactory kif = fac.getKeyInfoFactory();
   KeyValue kv = kif.newKeyValue(kp.getPublic());

   KeyInfo ki = 
       kif.newKeyInfo(Collections.singletonList(kv));

   DocumentBuilderFactory dbf =
       DocumentBuilderFactory.newInstance();
   dbf.setNamespaceAware(true);
   Document doc1 = 
       dbf.newDocumentBuilder().
       parse(new FileInputStream("C:/Documents and Settings/sbtho/Desktop/downloads/samp.xml"));

   DOMSignContext dsc = new DOMSignContext
    (kp.getPrivate(), doc.getDocumentElement());


   XMLSignature signature = fac.newXMLSignature(si, ki);
      signature.sign(dsc);

   TransformerFactory tf = TransformerFactory.newInstance();
   Transformer trans = tf.newTransformer();

   trans.transform(
       new DOMSource(doc),
       new StreamResult(
           new FileOutputStream("C:/Documents and Settings/sbtho/Desktop/downloads/signedsamp.xml")));

上面代码的输出看起来像这样,我想在 keyinfo 标签中插入 x509 标签。

   <?xml version="1.0" encoding="UTF-8" standalone="no" ?> 
  <questionset>
   <question category="graph" /> 
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
  <SignedInfo>
   <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" /> 
   <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> 
    <Reference URI="">
    <Transforms>
    <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> 
    </Transforms>
    <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> 
    <DigestValue>Kjgj/nVt41Q8gfDwSdfTGW42FQ8=</DigestValue> 
    </Reference>
    </SignedInfo>
      <SignatureValue>nhdbvODcXYvc5w65todyDBkVJJW/VgN3sxMjILO+qavIln0np57qSYvC6CjavLEdD5KZ0uLoD7r/ o07X9k3I5Q==</SignatureValue> 
 <KeyInfo>
 <KeyValue>
 <RSAKeyValue>
   <Modulus>qc/XQnBZ2/waPw+wUmdFiYUEY8RDLpaDn+Xmm56WoHn9jKKB0BCrYxz33q+z4O7VwQdv1eAdv9cK eTHEEpJpIQ==</Modulus> 
  <Exponent>AQAB</Exponent> 
  </RSAKeyValue>
  </KeyValue>
  </KeyInfo>
  </Signature>
  </questionset>

x509 证书是如何创建的?

最佳答案

我知道问这个问题已经有一段时间了,但我遇到了同样的问题,我解决了它,所以我想分享解决方案它使用使用 iaik pkcs 工具从安全 token 中获取的 keystore :

替换 singletonList 的技巧 vas

KeyInfo ki = 
   kif.newKeyInfo(Collections.singletonList(kv));

用于包含证书和 key 值的列表。

具有全部魔力的代码(希望它对某人有所帮助):

public void generateSignatureforResumen(String originalXmlFilePath,
        String destnSignedXmlFilePath, IAIKPkcs11 pkcs11Provider_, KeyStore tokenKeyStore, String pin) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException, GeneralSecurityException, TokenException  {
    //Get the XML Document object
    Document doc = getXmlDocument(originalXmlFilePath);
    //Create XML Signature Factory
    PrivateKey signatureKey_ = null;
    PublicKey pubKey_ = null;
    X509Certificate signingCertificate_ = null;
    Boolean prik = false;
    Boolean pubk = false;
    Enumeration aliases = tokenKeyStore.aliases();
    while (aliases.hasMoreElements()) {
      String keyAlias = aliases.nextElement().toString();
      java.security.Key key = tokenKeyStore.getKey(keyAlias, pin.toCharArray());
      if (key instanceof java.security.interfaces.RSAPrivateKey) {
        Certificate[] certificateChain = tokenKeyStore.getCertificateChain(keyAlias);
        X509Certificate signerCertificate = (X509Certificate) certificateChain[0];
        boolean[] keyUsage = signerCertificate.getKeyUsage();
        // check for digital signature or non-repudiation,
        // but also accept if none is set
        if ((keyUsage == null) || keyUsage[0] || keyUsage[1]) {
          signatureKey_ = (PrivateKey) key;
          signingCertificate_ = signerCertificate;
          prik = true;
          pubKey_ = signerCertificate.getPublicKey();
          break;
        }
      } 
    }


    if (signatureKey_ == null) {
      throw new GeneralSecurityException(
          "Found no signature key. Ensure that a valid card is inserted.");
    }

     XMLSignatureFactory xmlSigFactory = XMLSignatureFactory.getInstance("DOM");
        Reference ref = null;
        SignedInfo signedInfo = null;
        try {
            ref = xmlSigFactory.newReference("", xmlSigFactory.newDigestMethod(DigestMethod.SHA1, null),
                    Collections.singletonList(xmlSigFactory.newTransform(Transform.ENVELOPED,
                    (TransformParameterSpec) null)), null, null);
            signedInfo = xmlSigFactory.newSignedInfo(
                    xmlSigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
                    (C14NMethodParameterSpec) null),
                    xmlSigFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                    Collections.singletonList(ref));


        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        } 
        KeyInfoFactory kif = xmlSigFactory.getKeyInfoFactory();
        X509Data x509data = kif.newX509Data(Collections.nCopies(1, signingCertificate_));
        KeyValue kval = kif.newKeyValue(pubKey_);
        List keyInfoItems = new ArrayList();
        keyInfoItems.add(kval);
        keyInfoItems.add(x509data);
        //Object list[];
        KeyInfo keyInfo = kif.newKeyInfo(keyInfoItems);
//Create a new XML Signature
    XMLSignature xmlSignature = xmlSigFactory.newXMLSignature(signedInfo, keyInfo);



    DOMSignContext domSignCtx = new DOMSignContext((Key) signatureKey_, doc.getDocumentElement());


    try {
        //Sign the document
        xmlSignature.sign(domSignCtx);
    } catch (MarshalException ex) {
        ex.printStackTrace();
    } catch (XMLSignatureException ex) {
        ex.printStackTrace();
    }
    //Store the digitally signed document inta a location
    storeSignedDoc(doc, destnSignedXmlFilePath);

关于java - 如何使用x509证书生成数字签名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17402810/

相关文章:

java - 使用 Glassfish3/4 或 Tomcat 8 和自签名证书的双向(相互)SSL

java - Android - 将 pkcs12 证书字符串转换为 bks keystore 的 x509 证书对象

XML 回车符在发布后消失了

java - 处理大型 xml 文件

java - Android:ListView 在 getView() 中添加标签?

SSL 握手失败,出现 'Certificate Unknown'

java - Hibernate 给出 'table is not mapped' 异常

java - 自动验证数百个独立 Java 程序的最佳方法是什么?

java - 如何在 Java 中比较字符串?

java - 如何让 jfreechart 在 Eclipse 中工作 (Windows 7)