如何将PEM格式字符串私钥转换为Java的PrivateKey类型?
我有一个2048位的PEM格式私钥字符串,需要传给getSignedText函数(接收PrivateKey类型参数)来签名数据,但尝试了多种转换方法都失败,问题已经困扰我一个月,求解决。
私钥内容:
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDMsFHds+5f72yW
hhzhCL8svzk7IAoSFZqPnTYoGNz8nN82sKwY5dhkB2x0Hw7dlJhs2V2+Y8nlS13E
fQQVT3NofdPVbZdCnwzrzz4VsT/0Yhg10FXNwXRzk4QTECQWaz5ZUqm2oXOBKG9R
DvgLKiuQVIgnRPrh57o7njkCxtnrJg3fOqRTAIopODrZbpDd1WRpYGJMD1eRLzfj
ZfXcuDypb4hRZ4P4qm7W7OIuwjzmaDiG9uvf7SYn8oLaGNMaX9TmiaPVqBWH5BLO
vtR+eRfq6LFpq/pyj8q7C8ODF3n6G8dhEXmScrkOn3QxWQUmlG6Fu5KItbJW72TD
iz/CflfPAgMBAAECggEACu+AmtpPafYIqcy7I5VWtrVLVsqnab/tugPULjWQg459
/mtXRnKWf6xF3GOsZPouCo1dDMbtX8AJtRhYwiq0fRNRNfMyRETrE84cAFyv5gaM
9JMPgnv2FMFU1Q/lCFhCbyiTbfEXkqxDsOOegjoxNEzP2V6TaMOl7M7PN5ltcGVH
jxG7mii3gj16czLX+R5XF8/exoEvrsA951gj8ZoetkRwBsPDgARgrlUr++CMd+pB
PX2YvHkLulPRmjzYjSNG9KcK4IdIqVz3yCUDkBwi03Oj6BvTLLU93nj5VpVnrnJt
AkDx4EFjz8wVZ5E2oS6UAbmsy/fUppVi1mrkLjXSQQKBgQDV6w29D581bV3nH/pT
3xQEBUZdUk+PNvg+5nBC8mTz7MITAqe7qsI1oHsAkuW4FepucY4c0UEnskb6mu6m
L7ohv+oc1ZKC/ERJs/xy2uHOfAjFNN2volB8A3D2EEhYJ/M1x8IlMXNhucWhUg2G
SlAq//3yEXcoljBvNLarWH+j2wKBgQD09HiNfGL2vESicbTut1LPqTKwedl06I0B
ZvkpuL+qldeyfXXqu6+hU0NO6YTzVJToIM2LcfpbzNs1VIfA84f1pFUU+OhAahEt
JFowhWRhDhXIQIYbZV8YPjiMv+pcOezZZZi6Qx9oytFBJ7sm8oC3UHzPCrIcrwym
UMzJK9jYHQKBgB4zBMl//xXnzq3mUcytXYIDzJ84E4tAU2Nt3MNWvPHCptNQOKXB
wZEYisTV+CA419OnrExdLjmQbXzLio1jh39kPIS9keVz/5/4DNeaFu6zi/lrMTCu
VXZsdfIG8m+flDIvdTUS+hr9wuy3TLl8nDy1zv/xf0T3jvbkFjWyVLKpAoGBALZv
ZWGq5GHzMgLyQNkRvCFhWJlLBwQlNu92a9gA+u7njrAm9K2Qf2vdgWHCVfyMYCLK
W4uhpd69If4EKN8yAW6Xp65o+0EOPiCq1GkS0AHg5aQxOjApPbvmi2N4g+mQUrBP
FIKU/02i0FqAZsjJD8h3r5zb0G/Ah+FOiFbDy0qZAoGAAezuaIyUIpdlZnZiroOh
ji4CWx3mxTwWSC7HNm8e85v+QFv/p/aIrH9Xhm2KboLVWPUGugsvd1E/jQMhiDwk
B7X1qlvbVpGvkE2nssP08uLpvfoUr53ONwRmaTEM5VvM150qY+dC5yn1bJSjcRjT
Kj460FDLWtMiX7uhKq1HkS8=
-----END PRIVATE KEY-----
签名函数代码:
public static String getSignedText( String text, String algorithm, PrivateKey privateKey) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { byte[] data = text.getBytes("UTF8"); Signature sig = Signature.getInstance(algorithm == null ? "SHA256WITHRSA" : algorithm); sig.initSign(privateKey); sig.update(data); byte[] signatureBytes = sig.sign(); return Base64.getEncoder().encodeToString(signatureBytes); }
你的私钥是PKCS#8格式的PEM(从BEGIN PRIVATE KEY标识可判断),Java标准库可直接解析,无需额外依赖。以下是完整的转换实现:
转换工具代码
import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; public class PrivateKeyConverter { public static PrivateKey convertPemToPrivateKey(String pemPrivateKey) throws Exception { // 清理PEM格式:移除头部、尾部及所有空白字符 String cleanPem = pemPrivateKey .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s+", ""); // Base64解码得到密钥字节数组 byte[] keyBytes = Base64.getDecoder().decode(cleanPem); // 通过PKCS8规范生成PrivateKey实例 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(spec); } }
使用示例
public class Main { public static void main(String[] args) { String pemKey = "你的PEM私钥字符串"; try { PrivateKey privateKey = PrivateKeyConverter.convertPemToPrivateKey(pemKey); String signedText = getSignedText("需要签名的内容", null, privateKey); System.out.println("签名结果:" + signedText); } catch (Exception e) { e.printStackTrace(); } } }
注意事项
- 确保使用Java 8及以上版本(自带
Base64类),若为Java 7及以下,可替换为javax.xml.bind.DatatypeConverter.parseBase64Binary()或Apache Commons Codec的Base64工具类。 - 若转换时抛出
InvalidKeySpecException,检查私钥字符串是否完整,无多余或缺失字符。 - 你的签名函数默认使用
SHA256WITHRSA算法,与RSA私钥完全兼容,无需修改。
内容的提问来源于stack exchange,提问作者nima tehrani

