Java 使用DER格式从字符串base64编码创建PrivateKey和PublicKey

Java 使用DER格式从字符串base64编码创建PrivateKey和PublicKey,java,encryption,private-key,der,Java,Encryption,Private Key,Der,我在base64中的字符串中有我的私钥和公钥,其中使用ANS1 DER进行编码。我尝试创建javaPrivateKey和PublicKey的实例: byte [] llave2 = DatatypeConverter.parseBase64Binary(key); PKCS8Key pkcs8 = new PKCS8Key( llave2, password.toCharArray()); //line 2 llave2 = pkcs8.getDecryptedBytes();

我在base64中的字符串中有我的私钥和公钥,其中使用ANS1 DER进行编码。我尝试创建java
PrivateKey
PublicKey
的实例:

byte [] llave2 = DatatypeConverter.parseBase64Binary(key);
PKCS8Key pkcs8 = new PKCS8Key( llave2, password.toCharArray()); //line 2
llave2 = pkcs8.getDecryptedBytes();                             //line 3
certificado = DatatypeConverter.parseBase64Binary(cer);

KeyFactory kf = KeyFactory.getInstance("RSA");  
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(llave2);
PrivateKey privateKey = kf.generatePrivate(ks);
X509EncodedKeySpec x = new X509EncodedKeySpec(certificado);
PublicKey publicKey = kf.generatePublic(x);
我在
PublicKey PublicKey=kf.generatePublic(x)
中遇到以下错误

java.security.spec.InvalidKeySpecException:java.security.InvalidKeyException:IOException:ObjectIdentifier()--数据不是对象ID(标记=-96)
位于sun.security.rsa.RSAKeyFactory.EngineeGeneratePublic(未知源)
位于java.security.KeyFactory.generatePublic(未知源)
位于vital.cancelacions.GeneraXMLCancelacion.main(GeneraXMLCancelacion.java:118)
原因:java.security.InvalidKeyException:IOException:ObjectIdentifier()--数据不是对象ID(标记=-96)
在sun.security.x509.X509Key.decode(未知源)
在sun.security.x509.X509Key.decode(未知源)
位于sun.security.rsa.RSAPublicKeyImpl(未知来源)
位于sun.security.rsa.RSAKeyFactory.generatePublic(未知源)
... 3个以上

我想我应该像第2行和第3行中使用私钥一样使用公钥。因为证书也是加密的。有什么建议吗?

为了测试您的场景,我使用
openssl
创建了一个RSA私钥

openssl genrsa -out private.pem 1024
然后我将此密钥转换为PKCS#8 DER格式

openssl pkcs8 -topk8 -inform PEM -in private.pem -outform DER -out private.der -nocrypt
openssl
手册将PKCS#8和DER作为两种格式,就我而言,会发生以下情况:

  • pkcs8
    告诉
    openssl
    我想使用PKCS#8格式的私钥
  • -topk8
    告诉它我将在
    -in
    中指定的私钥不在PKCS#8中(否则它将假定它在PKCS#8中)
  • -通知
    -在
    中指定我要将(PEM)私钥转换为PKCS#8(如果没有
    -topk8
    ,它将尝试将PKCS#8格式的密钥转换为标准密钥格式)
  • -outform
    -out
    告诉它我想要一个DER格式的键作为输出
  • -nocrypt
    告诉它我不想加密密钥
然后,用我的RSA密钥(标准格式)创建了一个证书

openssl req -new -x509 -keyform PEM -key private.pem -outform DER -out public.der
证书包含与我的私钥对应的公钥

在所有这些之后,我用Base64对私钥和证书进行了编码

base64 private.der > private.der.b64
base64 public.der > public.der.b64
生成了以下文件

private.pem      # standard
private.der      # pkcs8/DER
private.der.b64 
public.der       # x509/DER
public.der.b64   
publicstaticvoidmain(String[]args)抛出IOException、GeneralSecurityException{
//获取base64编码密钥和证书的句柄
File privateKeyFile=新文件(“private.der.b64”);
File publicKeyFile=新文件(“public.der.b64”);
//把它们拉成阵列
byte[]privateKeyBytes=toByteArray(privateKeyFile);
字节[]publicKeyBytes=toByteArray(publicKeyFile);
//破译
privateKeyBytes=ToDecodeBase64ByteArray(privateKeyBytes);
publicKeyBytes=ToDecodeBase64ByteArray(publicKeyBytes);
//获取私钥
KeyFactory-KeyFactory=KeyFactory.getInstance(“RSA”);
KeySpec privateKeySpec=新的PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey PrivateKey=keyFactory.generatePrivate(privateKeySpec);
//获取公钥
CertificateFactory CertificateFactory=CertificateFactory.getInstance(“X509”);
Certificate=certificateFactory.generateCertificate(新的ByteArrayInputStream(publicKeyBytes));
PublicKey PublicKey=certificate.getPublicKey();
}
私有静态字节[]toByteArray(文件)引发IOException{
//Java7的try with resources语句
try(FileInputStream in=newfileinputstream(file);
FileChannel=in.getChannel()){
ByteArrayOutputStream out=新建ByteArrayOutputStream();
channel.transferTo(0,channel.size(),Channels.newChannel(out));
return out.toByteArray();
}
}
专用静态字节[]ToDecodeBase64ByteArray(字节[]base64EncodedByteArray){
返回DatatypeConverter.parseBase64Binary(
新字符串(base64EncodedByteArray,Charset.forName(“UTF-8”));
}
主要问题是您有一个证书而不是公钥。证书包含公钥,但不能使用
X509EncodedKeySpec(…)
加载,这就是为什么必须使用
CertificateFactory


(顺便说一句,这是一篇关于
openssl
和Java加密用法的优秀文章/教程。我的部分信息来自于此。)

我的密钥存储在base64中,但当我尝试实现以下代码来解密它时:
PKCS8Key pkcs8=new PKCS8Key(llave,password.tocharray())我得到以下错误:
org.apache.commons.ssl.ProbablyNotPKCS8Exception:asn1解析失败:java.lang.ClassCastException:org.apache.commons.ssl.asn1.DERApplicationSpecific无法强制转换为org.apache.commons.ssl.asn1.DERSequence
。我应该怎么做呢?@user1084509我链接的页面在顶部附近说,输入流可以是DER(原始ASN.1)或PEM(base64)。你说过你有一把DER格式的钥匙。如果您将此原始DER密钥编码为Base64,那么首先您必须对其进行解码(可能)。如果您使用的是JDK 6,那么您可以使用。我会用一个例子更新我的答案。哇!非常感谢你!这对我的私钥很有效。现在,公钥出现了问题,因为我使用parseBase64Binary(…)函数对其进行解码,但是否存在
PKCS8Key pkcs8=new PKCS8Key(llave2,password.toCharArray())的等价性;llave2=pkcs8.getDecryptedBytes()
对于同样是DER编码但具有X509格式的公钥?@user1084509现在问题与公钥有关,因为我使用parseBase64Binary(…)函数对其进行解码。它是否像您的私钥一样以Base64编码?如果是,你应该解码它;否则就不行了。使用PKCS8Key类的唯一原因是如果您的私钥已加密
private.pem      # standard
private.der      # pkcs8/DER
private.der.b64 
public.der       # x509/DER
public.der.b64