RSA加密:InvalidKeyException:无效的密钥格式

3

我需要读取pem密钥文件以获取RSA公钥,然后使用它们进行加密。我可以使用openssl将pem文件转换为der文件来实现这一点。然后使用X509EncodedKeySpec和PKCS8EncodedKeySpec加载我的密钥。但我不想这样做,因为pem是用户密钥交换格式。用户可以像这样注册自己的密钥:

--BEGIN PUBLIC KEY-- MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgGi0/vKrSIIQMOm4atiw+2s8tSojOKHsWJU3oPTm

b1a5UQIH7CM3NgtLvUF5DqhsP2jTqgYSsZSl+W2RtqCFTavZTWvmc0UsuK8tTzvnCXETsnpjeL13

Hul9JIpxZVej7b6KxgyxFAhuz2AGscvCXnepElkVh7oGOqkUKL7gZSD7AgMBAAE=

--END PUBLIC KEY--

这个密钥以以下格式存储在数据库中...

这是我尝试过的代码...

File pubKeyFile=new File("D:/public_key.pem");
DataInputStream dis = new DataInputStream(new FileInputStream(pubKeyFile));
byte[] pubKeyBytes = new byte[(int)pubKeyFile.length()];
dis.readFully(pubKeyBytes);
dis.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKeyBytes);
RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(pubSpec);

我遇到了异常,错误信息如下:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format

由于我完全不了解加密概念,是否有人能帮我解决这个异常?

非常感谢。

3个回答

3
你已经接近成功了,使用标准提供程序即可。你只需要去掉页头和页脚行:
List<String> lines = Files.readAllLines(Paths.get(path), StandardCharsets.US_ASCII);
if (lines.size() < 2) 
    throw new IllegalArgumentException("Insufficient input");
if (!lines.remove(0).startsWith("--"))
    throw new IllegalArgumentException("Expected header");
if (!lines.remove(lines.size() - 1).startsWith("--")) 
    throw new IllegalArgumentException("Expected footer");
byte[] raw = Base64.getDecoder().decode(String.join("", lines));
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey pub = factory.generatePublic(new X509EncodedKeySpec(raw));

3

使用bouncycastle,可以这样实现:

CertificateFactory cf = CertificateFactory.getInstance("X509", "BC");
InputStream is = new FileInputStream("D:/public_key.pem");
X509Certificate certificate = (X509Certificate) cf.generateCertificate(is);
is.close();
RSAPublicKey pubKey = (RSAPublicKey)certificate.getPublicKey();

+1,我以为你必须使用PEMReader类,没想到你可以只是指定“BC”提供程序给CertificateFactory。 - President James K. Polk

0

尝试使用BouncyCastle的PemReader。

PublicKey getPublicKey(String pubKeyStr) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { 
    PemObject pem = new PemReader(new StringReader(pubKeyStr)).readPemObject();
    byte[] pubKeyBytes = pem.getContent();
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKeyBytes);
    RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(pubSpec);
    return pubKey;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接