如何以编程方式生成自签名证书?

我有一个由HSM生成的RSA公钥(2048位),该密钥已保存在一个文件中(大小为256字节)并被编码为DER。

是否有可能以编程方式使用JDK API(没有BouncyCastle)从该文件开始创建自签名证书?

我坚持第一步,因为我正在尝试加载密钥文件来创建一个PublicKey对象:

import java.io.FileInputStream; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import org.apache.commons.io.IOUtils; public class Crypto { public static void main(String[] args) throws Exception { byte[] byteArray = IOUtils.toByteArray(new FileInputStream("/tmp/pub.key")); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(byteArray); KeyFactory kf = KeyFactory.getInstance("RSA"); PublicKey pub = kf.generatePublic(spec); .... } } 

但我得到这个例外:

 Exception in thread "main" java.security.spec.InvalidKeySpecException: Only RSAPublicKeySpec and X509EncodedKeySpec supported for RSA public keys at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:289) at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:184) at java.security.KeyFactory.generatePublic(KeyFactory.java:304) at org.alex.Crypto.main(Crypto.java:17) 

有没有办法做到这一点?

请改用X509EncodedKeySpec (内部实际使用X509EncodedKeySpec密钥的PKCS#1编码)。 保持其余代码相同。 PKCS#8用于私钥,而不是公钥(因为它使用了用另一个密钥包装密钥所需的PKCS#8内部结构,并且包装公钥没有意义)。

例外是告诉你这个问题! => Only RSAPublicKeySpec and X509EncodedKeySpec supported for RSA public keys

您正在尝试使用不受支持的PKCS8EncodedKeySpec ,创建X509EncodedKeySpecX509EncodedKeySpec

 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); byte[] input = new byte[] { (byte) 0xbe, (byte) 0xef }; Cipher cipher = Cipher.getInstance("RSA/None/NoPadding", "BC"); KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC"); RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger( "12345678", 16), new BigInteger("11", 16)); RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(new BigInteger( "12345678", 16), new BigInteger("12345678", 16)); RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(pubKeySpec); RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privKeySpec); cipher.init(Cipher.ENCRYPT_MODE, pubKey);