GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Assinar XML com certificado digital


#1

Bom galera, eu preciso assinar alguns arquivos .xml com assinatura digital através de certificados digitais (Arquivo, Token, SmartCard) consegui montar a seguinte classe:

public void assinarXML(String arquivoXML) {
String tokenCaminho;
String tokenNomeAmigavel;
String tokenSenha;

    try {
        //CERTIFICADO DIGITAL EM ARQUIVO
        tokenCaminho = "caminhoDoCertificado\\CertificadoDigital.pfx";
        tokenNomeAmigavel = "NomeAmigavelDoCertificado";
        tokenSenha = "senhaDoCertificado";
        
        //CERTIFICADO DIGITAL EM SMARTCARD
        //tokenCaminho = "";
        //tokenNomeAmigavel = "";
        //tokenSenha = "";
        
        //CORRIGI BUG DO TRANSFORM
        System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
        //Create a DOM XMLSignatureFactory that will be used to generate the
        //enveloped signature.
        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
        //Create a Reference to the enveloped document (in this case, you
        //are signing the whole document, so a URI of "" signifies that,
        //and also specify the SHA1 digest algorithm and the ENVELOPED Transform.            
        Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null),
                Collections.singletonList(fac.newTransform(Transform.ENVELOPED,
                        (TransformParameterSpec) null)), null, null);
        //Create the SignedInfo.
        SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
                (C14NMethodParameterSpec) null),
                fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                Collections.singletonList(ref));
        // Load the KeyStore and get the signing key and certificate.
        KeyStore ks = KeyStore.getInstance("PKCS12");            
        ks.load(new FileInputStream(tokenCaminho), tokenSenha.toCharArray());
        KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(tokenNomeAmigavel, new KeyStore.PasswordProtection(tokenSenha.toCharArray()));
        X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
        // Create the KeyInfo containing the X509Data.
        KeyInfoFactory kif = fac.getKeyInfoFactory();
        List x509Content = new ArrayList();
        x509Content.add(cert.getSubjectX500Principal().getName());
        x509Content.add(cert);
        X509Data xd = kif.newX509Data(x509Content);
        KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
        // Instantiate the document to be signed.
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(arquivoXML));
        // Create a DOMSignContext and specify the RSA PrivateKey and
        // location of the resulting XMLSignature's parent element.
        DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc.getDocumentElement());
        // Create the XMLSignature, but don't sign it yet.
        XMLSignature signature = fac.newXMLSignature(si, ki);
        // Marshal, generate, and sign the enveloped signature.
        signature.sign(dsc);
        // Output the resulting document.            
        OutputStream os = new FileOutputStream(arquivoXML);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        trans.transform(new DOMSource(doc), new StreamResult(os));
    } catch (NoSuchAlgorithmException | ParserConfigurationException | SAXException | KeyStoreException | CertificateException | UnrecoverableEntryException | InvalidAlgorithmParameterException | MarshalException | XMLSignatureException | TransformerConfigurationException e) {
        Logger.getLogger(MenuFiscal.class.getName()).log(Level.SEVERE, null, e);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(MenuFiscal.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException | TransformerException ex) {
        Logger.getLogger(MenuFiscal.class.getName()).log(Level.SEVERE, null, ex);
    } 
}

Para certificados do tipo arquivo (.pfx e .p12) ele está funcionando perfeitamente, porém não consigo efetuar a assinatura usando um SmartCard, estou tentando alterar o código para efetuar ambas validações mas não obtive sucesso, toda ajuda é valida já revirei a internet. Agradeço desde já.


#2

Alguma dica, ideia? Qualquer coisa que possa me ajudar.


#3

Possivelmente tem que abrir outra KeyStrore:

KeyStore keyStore = KeyStore.getInstance("Windows-MY");