我的私钥和公钥在base64中的字符串中,该字符串使用ANS1 DER进行编码。我尝试创建Java PrivateKey和的实例PublicKey:
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)。
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
我猜我应该对公共密钥做类似的事情,就像在第2行和第3行中对私有密钥做一样。因为证书也是加密的。有什么建议?
为了测试您的方案,我创建了一个RSA私钥openssl。
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
-topk8
-in
-inform
-outform
-out
-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 { // 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"))); }
主要问题是您拥有证书而不是公共密钥。证书包含公钥,但是不能加载X509EncodedKeySpec(...),这就是为什么CertificateFactory必须使用的原因。
X509EncodedKeySpec(...)
CertificateFactory
(顺便说一下,这里有一篇很棒的文章/教程openssl以及Java密码学的用法。我的信息部分来自那里。)