为了测试您的方案,我创建了一个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
告诉它我会指定用私钥-in
是 不是 在PKCS#8(否则它会假设它是)。-inform
并-in
指定我要将(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.b64base64 public.der > public.der.b64
生成了以下文件。
private.pem # standardprivate.der # pkcs8/DERprivate.der.b64 public.der # x509/DERpublic.der.b64public static void main(String[] args) throws IOException, GeneralSecurityException { // get a handle on the base64 enpred 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); // depre them privateKeyBytes = toDepredbase64ByteArray(privateKeyBytes); publicKeyBytes = toDepredbase64ByteArray(publicKeyBytes); // get the private key KeyFactory keyFactory = KeyFactory.getInstance("RSA"); KeySpec privateKeySpec = new PKCS8EnpredKeySpec(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[] toDepredbase64ByteArray(byte[] base64EnpredByteArray) { return DatatypeConverter.parsebase64Binary( new String(base64EnpredByteArray, Charset.forName("UTF-8")));}主要问题是您拥有证书而不是公共密钥。证书包含公钥,但是不能加载
X509EnpredKeySpec(...),这就是为什么
CertificateFactory必须使用的原因。
(顺便说一下,这里有一篇很棒的文章/教程
openssl以及Java密码学的用法。我的信息部分来自那里。)



