Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Hi, I need generate an XML document with a digital signature.
Example of XML document that I must sign and verify your signature:
https://www.efactura.dgi.gub.uy/files/ejemplo-de-sobre?es
I am a programmer (PHP, C++, Python, NodeJs, etc..), but I do not work with the Java language.
How can I generate plugins for the designer of Talend Data Integration could sign my XMl document and the signature is verified. Any recommendation.
Guide translated from Spanish - http://www.efactura.dgi.gub.uy/files/guias-en-el-uso-de-xmlencryption-11062014-pdf?es
Using the XMLEncryption standard (http://www.w3.org/2001/04/xmlenc).
It should be used as an asymmetric algorithm rsa-pkcs1 (http://www.w3.org/2001/04/xmlenc#rsa-1_5) and
as a symmetric algorithm: 3DES-CBC (http://www.w3.org/2001/04/xmlenc#tripledes-cbc).
Finally, as a key name (KeyName), CERT_DGI_EFACTURA must be used.
The public and private keys are generated in the following way:
1- As a first step, we create the private key pair (cakey.pem) and public key (cacert.pem) of our CA using the RSA algorithm (since DSA only serves to sign). A bit length (2048) is chosen according to the security that a CA needs.
openssl req -x509 -newkey rsa:4096 -days 3650 -keyout ca\private\cakey.pem -out ca\cacert.pem -config openssl.cfg
2- The pair of private keys (clientkey.pem) and CSR (client.cert.req) that will be sent to the CA are created for the Client (CSR stands for Certificate Signing Request or Certificate Signing Request).
openssl req -newkey rsa:1024 -keyout client\private\clientkey.pem -out client\csr\client.cert.req -config openssl.cfg
3- From the Client's CSR (client.cert.req), a signed X509 certificate (version 3) is created with the private key of the CA (clientcert.pem).
openssl ca -days 3650 -in client\csr\client.cert.req -out client\signed\clientcert.pem -config openssl.cfg
4- Finally, the client's private key (clientkey.pem) and its certificate issued by the CA (clientcert.pem) are exported to PKCS # 12 (client.p12).
openssl pkcs12 -export -out client\client.p12 -inkey client\private\clientkey.pem -in client\signed\clientcert.pem
Example implementation in Java.
import java.security.PrivateKey; import java.security.PublicKey; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.xml.security.encryption.EncryptedData; import org.apache.xml.security.encryption.EncryptedKey; import org.apache.xml.security.encryption.XMLCipher; import org.apache.xml.security.keys.KeyInfo; import org.apache.xml.security.utils.EncryptionConstants; import org.w3c.dom.Document; import org.w3c.dom.Element; public class XMLEncryptionSample { static { org.apache.xml.security.Init.init(); } private static Document parseFile(String fileName) throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); return db.parse(fileName); } private static SecretKey generateSymmetricKey() throws Exception { String jceAlgorithmName = "DESede"; KeyGenerator keyGenerator = KeyGenerator.getInstance(jceAlgorithmName); return keyGenerator.generateKey(); } private static void writeDocToFile(Document doc, String fileName) throws Exception { FileOutputStream outStream = new FileOutputStream(new File(fileName)); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); DOMSource source = new DOMSource(doc); transformer.transform(source, new StreamResult(outStream)); outStream.close(); } public static void encrypt(String source, String target, String ns, String element, Key publicKey, String keyName) throws Exception { // Read XML from file Document document = parseFile(source); // Generates symmetric key for 3Des Key symmetricKey = generateSymmetricKey(); // Initialize cipher to encrypt the symmetric key XMLCipher keyCipher = XMLCipher.getInstance(XMLCipher.RSA_v1dot5); keyCipher.init(XMLCipher.WRAP_MODE, publicKey); // Encrypts the symmetric key EncryptedKey encryptedKey = keyCipher .encryptKey(document, symmetricKey); // Specifies the element of the XML document to be encrypted Element rootElement = document.getDocumentElement(); Element elementToEncrypt = rootElement; if (element != null) { elementToEncrypt = (Element) rootElement.getElementsByTagNameNS( ns, element).item(0); if (elementToEncrypt == null) { System.err.println("The element is not found: " + element); } } // Initialize cipher to encrypt the XML Element XMLCipher xmlCipher = XMLCipher.getInstance(XMLCipher.TRIPLEDES); xmlCipher.init(XMLCipher.ENCRYPT_MODE, symmetricKey); // Add information from the encryption key EncryptedData encryptedDataElement = xmlCipher.getEncryptedData(); KeyInfo innerKeyInfo = new KeyInfo(document); innerKeyInfo.addKeyName(keyName); encryptedKey.setKeyInfo(innerKeyInfo); KeyInfo keyInfo = new KeyInfo(document); keyInfo.add(encryptedKey); encryptedDataElement.setKeyInfo(keyInfo); // Cipher xmlCipher.doFinal(document, elementToEncrypt); // Write the result in the destination file writeDocToFile(document, target); } public static void decrypt(String source, String target, Key privateKey) throws Exception { // Read XML from file Document document = parseFile(source); // Get the XML Element with encrypted data String namespaceURI = EncryptionConstants.EncryptionSpecNS; String localName = EncryptionConstants._TAG_ENCRYPTEDDATA; Element encryptedDataElement = (Element) document .getElementsByTagNameNS(namespaceURI, localName).item(0); // The symmetric key is decrypted XMLCipher xmlCipher = XMLCipher.getInstance(); xmlCipher.init(XMLCipher.DECRYPT_MODE, null); xmlCipher.setKEK(privateKey); // The encrypted node is replaced with the decrypted information xmlCipher.doFinal(document, encryptedDataElement); // Write the result in the destination file writeDocToFile(document, target); } }
Loading the private and public key from a keystore (# PCKS12) named client.p12 whose alias is client, can be programmed as follows:
PrivateKey privateKey = null; PublicKey publicKey = null; .... .... KeyStore keystore = KeyStore.getInstance("PKCS12"); String p12Password = "secreto"; keystore.load(new FileInputStream("client.p12"), p12Password.toCharArray()); privateKey = (PrivateKey) keystore.getKey("client", p12Password.toCharArray()); publicKey = keystore.getCertificate("client").getPublicKey();
Finally, to perform a test, the encrypt / decrypt methods can be used as follows:
encrypt("Unencrypted.xml", "Encrypted.xml", "http://cfe.dgi.gub.uy", "Compl_Fiscal_Data", publicKey, "CERT_DGI_EFACTURA"); decrypt("Encrypted.xml", "Decrypted.xml", privateKey);
Excuse me if my English is not understood correctly.
Thank you, I hope that I can integrate this into my project in Talend Data Integration with your help.
Regards.
Could someone give me an example, how to implement it.? Thank you very much.
Hi Dertin,
I have a similar need, were you able to solve the issue? If Yes, please share the solution