从DER格式的String base64编码创建PrivateKey和PublicKey [英] Create PrivateKey and PublicKey from a String base64 encoding with DER format
问题描述
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(tag = -96)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(未知来源)
在java.security.KeyFactory.generatePublic(未知来源)
at vital.cancelaciones .GeneraXMLCancelacion.main(GeneraXMLCancelacion.java:118)
导致:java.security.InvalidKeyException:IOException:ObjectIdentifier() - 数据不是对象ID(tag = -96)
在太阳$。$ )
at sun.security.rsa.RSAKeyFactory.generatePublic(未知来源)
... 3更多
我想我应该像第2行和第3行中的私钥那样做公共密钥。因为证书te也是加密的。任何建议?
要测试您的方案,我已经创建了一个RSA私钥, openssl
。
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
告诉它私人我要在PKCS#8中用-in
指定不(否则它会假设是)。 -
-inform
和-in
指定我要转换(PEM)私钥到PKCS#8(没有-topk8
它将尝试将一个已经以PKCS#8格式转换为标准格式的密钥) / li>
-
-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
public static void main(String [] args)throws IOException,GeneralSecurityException {
//获取base64编码密钥和证书上的句柄
文件privateKeyFile = new File(private.der。 B64\" );
文件publicKeyFile = new File(public.der.b64);
//将它们拉入数组
byte [] privateKeyBytes = toByteArray(privateKeyFile);
byte [] publicKeyBytes = toByteArray(publicKeyFile);
//解码他们
privateKeyBytes = toDecodedBase64ByteArray(privateKeyBytes);
publicKeyBytes = toDecodedBase64ByteArray(publicKeyBytes);
//获取私钥
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
KeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
//获取公钥
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
证书证书= certificateFactory.generateCertificate(新的ByteArrayInputStream(publicKeyBytes));
PublicKey publicKey = certificate.getPublicKey();
}
private static byte [] toByteArray(File file)throws IOException {
// java 7的try-with-resources语句
try(FileInputStream in = new FileInputStream(file);
FileChannel channel = in.getChannel()){
ByteArrayOutputStream out = new ByteArrayOutputStream();
channel.transferTo(0,channel.size(),Channels.newChannel(out));
return out.toByteArray();
}
}
private static byte [] toDecodedBase64ByteArray(byte [] base64EncodedByteArray){
return DatatypeConverter.parseBase64Binary(
new String(base64EncodedByteArray,Charset .forName( UTF-8)));
}
主要问题是您有证书而不是公钥。证书包含公钥,但不能使用 X509EncodedKeySpec(...)
加载,这就是为什么 CertificateFactory
必须使用。
(顺便说一下这里是一篇关于 openssl
和Java加密用法的伟大文章/教程,我从那里获得了我的信息。 )
I have my Private and Public keys in a String in base64 which where encoded using ANS1 DER. I tried creating the instance of a java PrivateKey
and 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);
I get the following error in PublicKey publicKey = kf.generatePublic(x)
.
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(Unknown Source)
at java.security.KeyFactory.generatePublic(Unknown Source)
at vital.cancelaciones.GeneraXMLCancelacion.main(GeneraXMLCancelacion.java:118)
Caused by: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
at sun.security.x509.X509Key.decode(Unknown Source)
at sun.security.x509.X509Key.decode(Unknown Source)
at sun.security.rsa.RSAPublicKeyImpl.<init>(Unknown Source)
at sun.security.rsa.RSAKeyFactory.generatePublic(Unknown Source)
... 3 more
I guess I should do something similar with the public key as done with the private key in lines 2 and 3. Because the certificate is also encrypted. Any suggestions?
To test your scenario, I've created an RSA private key with openssl
.
openssl genrsa -out private.pem 1024
Then I've converted this key to PKCS#8 DER format.
openssl pkcs8 -topk8 -inform PEM -in private.pem -outform DER -out private.der -nocrypt
The manual of openssl
refers to PKCS#8 and DER both as formats, so as far as I'm concerned the following happens:
pkcs8
tellsopenssl
that I want to work with private keys in PKCS#8 format.-topk8
tells it that the private key I'm going to specify with-in
is not in PKCS#8 (otherwise it'll assume it is).-inform
and-in
specify that I want to convert the (PEM) private key to PKCS#8 (without-topk8
it'll try to convert a key already in PKCS#8 format to a standard key format).-outform
and-out
tells it I want a DER formatted key as output.-nocrypt
tells it that I don't want to encrypt the key.
Then, with my RSA key (in standard format) I've created a certificate.
openssl req -new -x509 -keyform PEM -key private.pem -outform DER -out public.der
The certificate contains the public key corresponding to my private key.
After all of these, I've encoded both the private key and the certificate with Base64.
base64 private.der > private.der.b64
base64 public.der > public.der.b64
The following files were generated.
private.pem # standard
private.der # pkcs8/DER
private.der.b64
public.der # x509/DER
public.der.b64
public static void main(String[] args) throws IOException, GeneralSecurityException {
// get a handle on the base64 encoded key and certificate
File privateKeyFile = new File("private.der.b64");
File publicKeyFile = new File("public.der.b64");
// pull them into arrays
byte[] privateKeyBytes = toByteArray(privateKeyFile);
byte[] publicKeyBytes = toByteArray(publicKeyFile);
// decode them
privateKeyBytes = toDecodedBase64ByteArray(privateKeyBytes);
publicKeyBytes = toDecodedBase64ByteArray(publicKeyBytes);
// get the private key
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
KeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
// get the public key
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
Certificate certificate = certificateFactory.generateCertificate(new ByteArrayInputStream(publicKeyBytes));
PublicKey publicKey = certificate.getPublicKey();
}
private static byte[] toByteArray(File file) throws IOException {
// java 7's try-with-resources statement
try (FileInputStream in = new FileInputStream(file);
FileChannel channel = in.getChannel()) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
channel.transferTo(0, channel.size(), Channels.newChannel(out));
return out.toByteArray();
}
}
private static byte[] toDecodedBase64ByteArray(byte[] base64EncodedByteArray) {
return DatatypeConverter.parseBase64Binary(
new String(base64EncodedByteArray, Charset.forName("UTF-8")));
}
The main problem was that you had a certificate instead of a public key. The certificate contains the public key, but it cannot be loaded with X509EncodedKeySpec(...)
, this is why the CertificateFactory
has to be used instead.
(By the way here is a great article/tutorial on openssl
and Java cryptography usage. I've got my info partly from there.)
这篇关于从DER格式的String base64编码创建PrivateKey和PublicKey的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!