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

我需要分别在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);


如果有人有更好的解决方案,我们将不胜感激。

最佳答案

我有一个类似的代码,我知道它可以工作,并且类似于您的代码:

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

关于java - 创建具有以base 64编码的字节数组的私钥和公钥,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8451205/

10-11 00:28