java - 是否可以从 PEM 文件中读取私钥而无需遍历所有可能的算法或编写 ASN.1 解析器?
问题描述
我正在考虑从 PEM 编码的 DER 文件中读取一个或多个私钥,我想知道它是否可以在不尝试所有可能的算法(丑陋且蛮力)或编写 ASN.1 解析器的情况下稳健地完成?
我试图在没有标准 Java 库以外的任何依赖项的情况下做到这一点。我确信 BouncyCastle 可以做到这一点,但我对开箱即用的 Java 的可能性感兴趣。
PEM 编码的 DER 文件是有点熟悉的文件,如下所示:
-----BEGIN EC PRIVATE KEY-----
[base64-encoded DER data]
-----END EC 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 PRIVATE KEY-----
[base64 encoded DER data]
-----END PRIVATE KEY-----
在这种情况下,给定 API,我只看到两种明显的可能性:
遍历所有支持的算法,尝试所有算法并忽略某些错误
实现一个 ASN.1 解析器来确定密钥的实际类型,然后使用正确的
KeyFactory
循环似乎很简单,但 IMO 令人反感:
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 解析器并非易事,尽管它们存在于第三方库中,但我想尽可能地限制依赖关系。
解决方案
推荐阅读
- php - Laravel 忽略查询中的多种类型的对象
- matlab - Multiply each element of a vector by each element of another vector
- reactjs - 如何控制 React 应用程序中受保护页面的路由?
- c - 康威的生命游戏缓冲下溢
- ios - 如何从相机胶卷中选择多个图像和视频并将它们显示在collectionView中?
- android - 可访问的 TextInputLayout
- reactjs - AJAX 响应后显示消息 n 秒
- ruby-on-rails - 如何使用 ruby on rails 在 SQL Server 中存储文件
- cakephp - 将数组转换为对象或实体并在 cakephp 3 中传递到分页
- delphi - C++Builder 中是否有类似 Delphi 的扩展 RTTI?