Java 11加载椭圆曲线加密私钥报DER input, Integer tag error如何解决
报错原因
- 报错的核心原因是你提取的私钥是加密状态的PKCS8私钥(对应PEM头为
-----BEGIN ENCRYPTED PRIVATE KEY-----),该内容是被你导出时输入的PEM pass phrase加密后的结果,不是明文的DER编码PKCS8私钥结构。你直接将加密后的二进制内容传入PKCS8EncodedKeySpec,JDK无法识别加密后的DER格式,因此抛出DER标签解析错误。
修复方案
有两种可选修复方式,推荐优先使用第一种,操作更简单,代码复杂度更低:
方案1:导出明文PKCS8格式私钥(推荐)
使用openssl命令直接导出未加密的EC私钥,命令如下:openssl pkcs12 -in file.p12 -nocerts -nodes -out ec_private_plain.pem
参数说明:
-nocerts:只导出私钥,忽略证书内容-nodes:不对导出的私钥进行加密处理
导出后打开ec_private_plain.pem,你会看到头为-----BEGIN PRIVATE KEY-----的明文私钥块,提取块内的Base64内容、移除换行符后,直接使用你原来的Java代码即可正常生成私钥。
注意:明文私钥文件泄露会导致身份被盗用,请严格控制该文件的访问权限。
方案2:Java代码中解密加密私钥
如果你必须使用已有的加密私钥,不需要重新导出,可以在代码中先解密私钥再解析,示例代码如下:
import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import javax.crypto.EncryptedPrivateKeyInfo; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; public class ECPrivateKeyLoader { public static void main(String[] args) throws Exception { // 加密的私钥Base64内容 String encryptedKeyBase64 = "MI[...]0="; // 导出私钥时设置的PEM pass phrase char[] pemPassword = "你设置的PEM密码".toCharArray(); // 解码Base64得到加密的私钥二进制 byte[] encryptedKeyBytes = Base64.getDecoder().decode(encryptedKeyBase64); // 解析加密私钥结构 EncryptedPrivateKeyInfo encryptedInfo = new EncryptedPrivateKeyInfo(encryptedKeyBytes); // 生成解密密钥 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(encryptedInfo.getAlgName()); PBEKeySpec pbeKeySpec = new PBEKeySpec(pemPassword); // 解密得到明文PKCS8私钥规范 PKCS8EncodedKeySpec plainKeySpec = encryptedInfo.getKeySpec(keyFactory.generateSecret(pbeKeySpec)); // 生成EC私钥 KeyFactory ecKeyFactory = KeyFactory.getInstance("EC"); PrivateKey privateKey = ecKeyFactory.generatePrivate(plainKeySpec); } }
内容的提问来源于stack exchange,提问作者PatPanda
相关产品推荐
相关产品推荐

