创建具有以base 64编码的字节数组的私钥和公钥

时间:2011-12-09 20:17:01

标签: java encryption public-key private-key

我的私钥(llave)为byte[],公钥为byte[](certificado =。

我需要在PrivateKeyPublicKey对象(分别)中转换这两个值,以便稍后使用它们以数字方式签署xml文档。

我尝试过使用KeyStore但我无法做到。我还尝试使用以下代码KeyFactory

import java.io.StringWriter;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Collections;

import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class GeneraXMLCancelacion {
public static void main (String [] args) {
    byte[] certificado = args[0].getBytes();
    byte[] llave = args[1].getBytes();
    String uuids = args[2];
    String rfc = args[3];
    String fecha = args[4];

    String [] uuid = uuids.split("/");

    //GENERAR XML
    try {
        //Crear un document XML vacío
        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
        dbfac.setNamespaceAware(true);
        DocumentBuilder docBuilder;
        docBuilder = dbfac.newDocumentBuilder();
        Document doc = docBuilder.newDocument();
        doc.setXmlVersion("1.0");
        doc.setXmlStandalone(true);

        Element cancelacion = doc.createElementNS("http://cancelacfd.sat.gob.mx","Cancelacion");
        cancelacion.setAttribute("RfcEmisor", rfc);
        cancelacion.setAttribute("Fecha", fecha);
        doc.appendChild(cancelacion);

        Element folios = doc.createElementNS("http://cancelacfd.sat.gob.mx", "Folios");
        cancelacion.appendChild(folios);
        for (int i=0; i<uuid.length; i++) {
            Element u = doc.createElementNS("http://cancelacfd.sat.gob.mx","UUID");
            u.setTextContent(uuid[i]);
            folios.appendChild(u);
        }

        //create a keyfactory - use whichever algorithm and provider
        KeyFactory kf = KeyFactory.getInstance("DSA");
        //for private keys use PKCS8EncodedKeySpec; for public keys use X509EncodedKeySpec
        PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(llave);
        PrivateKey privateKey = kf.generatePrivate(ks);
        X509EncodedKeySpec x = new X509EncodedKeySpec(certificado);
        PublicKey publicKey = kf.generatePublic(x);


        DOMSignContext dsc = new DOMSignContext (privateKey, doc.getDocumentElement()); 
        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

        Reference ref = fac.newReference ("", fac.newDigestMethod(DigestMethod.SHA1, null), 
                    Collections.singletonList
                    (fac.newTransform(Transform.ENVELOPED,
                    (TransformParameterSpec) null)), null, null);
        KeyInfoFactory kif = fac.getKeyInfoFactory();
        KeyValue kv = kif.newKeyValue(publicKey);
        KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv)); 

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

        KeyInfoFactory kif2 = fac.getKeyInfoFactory();
        KeyValue kv2 = kif2.newKeyValue(publicKey);
        KeyInfo ki2 = kif.newKeyInfo(Collections.singletonList(kv)); 

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

        signature.sign(dsc);

        //IMPRIMIR EL DOCUMENTO XML
        TransformerFactory transfac = TransformerFactory.newInstance();
        Transformer trans = transfac.newTransformer();
        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        trans.setOutputProperty(OutputKeys.VERSION, "1.0");
        trans.setOutputProperty(OutputKeys.INDENT, "yes");

        //CREAR STRING DEL ARBOL XML
        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);
        DOMSource source = new DOMSource(doc);
        trans.transform(source, result);
        String xmlString = sw.toString();
        System.out.println(xmlString);
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (TransformerConfigurationException e) {
        e.printStackTrace();
    } catch (TransformerException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }

}
}

运行程序时出现此错误:

java.security.spec.InvalidKeySpecException: Inappropriate key specification: invalid key format
at sun.security.provider.DSAKeyFactory.engineGeneratePrivate(Unknown Source)
at java.security.KeyFactory.generatePrivate(Unknown Source)
at vital.cancelaciones.GeneraXMLCancelacion.main(GeneraXMLCancelacion.java:85)

第85行对应于:

  

PrivateKey privateKey = kf.generatePrivate(ks);

如果有人有更好的解决方案,我将非常感谢您的帮助。

1 个答案:

答案 0 :(得分:6)

我有类似的代码,我知道它有效,它与你的相似:

 public KeyPair createKeyPair(byte[] encodedPrivateKey, byte[] encodedPublicKey) {
    try {
        EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
        KeyFactory generator = KeyFactory.getInstance(ASYM_ALGORITHM);
        PrivateKey privateKey = generator.generatePrivate(privateKeySpec);

        EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
        PublicKey publicKey = generator.generatePublic(publicKeySpec);
        return new KeyPair(publicKey, privateKey);
    } catch (Exception e) {
        throw new IllegalArgumentException("Failed to create KeyPair from provided encoded keys", e);
    }
}

我认为密钥的字节数组是错误的。你如何将它传递给main方法?