Java 是否可以从PEM文件中读取私钥,而无需遍历所有可能的算法或编写ASN.1解析器?
我正在研究从PEM编码的DER文件中读取一个或多个私钥,我想知道这是否可以在不尝试所有可能的算法(这是丑陋和粗暴的)或编写ASN.1解析器的情况下可靠地完成 除了标准Java库之外,我试图在没有任何依赖项的情况下完成这项工作。我相信BouncyCastle可以做到这一点,但我对开箱即用Java的可能性感兴趣 PEM编码的DER文件是一种比较常见的文件,其外观如下:Java 是否可以从PEM文件中读取私钥,而无需遍历所有可能的算法或编写ASN.1解析器?,java,private-key,pki,Java,Private Key,Pki,我正在研究从PEM编码的DER文件中读取一个或多个私钥,我想知道这是否可以在不尝试所有可能的算法(这是丑陋和粗暴的)或编写ASN.1解析器的情况下可靠地完成 除了标准Java库之外,我试图在没有任何依赖项的情况下完成这项工作。我相信BouncyCastle可以做到这一点,但我对开箱即用Java的可能性感兴趣 PEM编码的DER文件是一种比较常见的文件,其外观如下: -----BEGIN EC PRIVATE KEY----- [base64-encoded DER data] -----END
-----BEGIN EC PRIVATE KEY-----
[base64-encoded DER data]
-----END EC PRIVATE KEY-----
-----BEGIN PRIVATE KEY-----
[base64 encoded DER data]
-----END PRIVATE KEY-----
在上面的示例中,文本表示密钥的类型:它是椭圆曲线密钥,因此我们可以向Java请求EC密钥工厂:
byte[] keyBytes = // get DER bytes
KeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("EC");
PrivateKey key = kf.generateKey(spec);
但也有可能该文件不公布其内容,如下所示:
-----BEGIN EC PRIVATE KEY-----
[base64-encoded DER data]
-----END EC PRIVATE KEY-----
-----BEGIN PRIVATE KEY-----
[base64 encoded DER data]
-----END PRIVATE KEY-----
在这种情况下,我只看到两种明显的可能性:
KeyFactory
byte[] keyBytes = // get DER bytes
KeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey key = null;
for(String algorithm : new String[] { "EC", "RSA", "DSA" }) {
try {
KeyFactory kf = KeyFactory.getInstance(algorithm);
key = kf.generatePrivateKey(keyBytes);
} catch (....) {
// Ignore "wrong algorithm" exceptions
}
}
// "key" is either null (couldn't read/interpret) or non-null and OK
这也可能会耗费大量时间,尽管通常密钥设置是一个“罕见”的操作,因此性能并不十分重要
我唯一能想到的另一个选择是检查数据,以准确了解数据表示的内容,然后使用正确的类型:
byte[] keyBytes = // get DER bytes
KeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
ASN1Parser a1p = new ASN1Parser();
String algorithm = a1p.parse(keyBytes).getAlgorithm();
KeyFactory kf = KeyFactory.getInstance(algorithm);
PrivateKey key = fk.generatePrivateKey(spec);
与阅读X.509证书相比,您不必了解加载证书的算法:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
cf.generateCertificate(new ByteArrayInputStream(certBytes));
我是否在API中遗漏了允许这种“只为我做”机制的内容,或者在加载关键材料之前必须知道算法
编写ASN.1解析器并不简单,尽管它们存在于第三方库中,但我希望尽可能地限制依赖关系。您的第一个示例
BEGIN/END EC私钥
不是PKCS8密钥,任何JCAKeyFactory
都无法读取。对于PKCS8 clear格式的开始/结束私钥
您的ASN1Parser方法几乎是可行的;您需要.getAlgorithmIdentifier().getAlgorithm[AsString]()
CertificateFactory
(或者更确切地说是它背后的“引擎”)实际上为X.509 SPKI而不是PKCS8做了等效的工作。请记住,PKCS8和“传统”私钥PEM文件都可以使用非常不同的方法进行加密,这增加了复杂性。@dave_thompson_085我不想通过引入私钥加密使问题更加复杂。我没有意识到“BEGIN EC私钥”不是PKCS8,而是一个单独的标准(RFC5915)。