Assinar XML com certificado digital

2 respostas
G

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 Respostas

G

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

J

Possivelmente tem que abrir outra KeyStrore:

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

Criado 25 de agosto de 2017
Ultima resposta 14 de jan. de 2019
Respostas 2
Participantes 2