how to generate digital signature with x509 certif

2020-07-16 09:03发布

问题:

How do we get and append x509data and x509certificate tag to the xml produced by the following code

 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")));

the output of the above code looks like this and i want ti insert x509 tags inside the keyinfo tag.

   <?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>

and how is the x509certificate created ?

回答1:

I know it's been a while since the question was asked, but I had the same issue, and I solved it, so I would like to share the solution It uses a keystore obtained from a security token using iaik pkcs tools:

the trick vas to replace the singletonList in

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

for a list with the certificate and the keyvalue.

the code with the whole magic (hope it helps someone):

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