从 NodeJS 中的输入键控 material 创建 EC 私钥

Create EC private key from input keying material in NodeJS

我想从输入键控 material(主密钥)中导出椭圆曲线私钥。这可能吗?

尝试次数

Node 的加密函数,crypto.generateKeyPair does not accept input keying material, and crypto.createPrivateKey 仅将 .pem 转换为 Node 的本机 KeyObject。

我也找不到使用 ecparam 在 OpenSSL 中执行此操作的方法。 -rand 标志似乎很有前途,但并未广泛使用(它不在我的机器上)。

原因/详情

我需要创建多个密钥,并希望所有密钥都派生自一个主密钥。这类似于 HKDF。

我正在使用曲线 P-384 (secp384r1) 的 ECDSA 密钥。

我很惊讶你认为 ecparam -rand file -genkey ... 很少见;它在 2005 年 至少 到 0.9.8 的每个上游版本中都有,并且它不是构建(配置)选项可以省略的东西之一,所以你的机器必须有一个奇怪的版本。但这没关系,因为 -rand 没有做你想做的事;它 将文件数据添加 到 RNG 'pool' 但不会 替换 它,因此它不会为您提供确定性密钥生成。

正如 Woodstock 评论的那样,出于所有实际目的,原始 P-384 私钥只是来自任何好的随机生成器的 384 位,或者来自任何统一随机函数的确定性。从技术上讲,您应该排除零和大于或等于(子)组阶数 n 的值,但这些排除项相对于 2^384 来说太小了,以至于在地球的生命周期内,一个好的随机选择基本上没有机会击中它们,也许还有宇宙。您可能想看看比特币 'hierarchical deterministic' 密钥派生又名 BIP 32 是如何工作的,当然这对 secp256k1 来说是 256 位密钥。

这给你留下了将原始密钥转换为 nodejs 加密可用的形式的问题(这是 openssl 库的一个相当薄的包装)and/or openssl 命令行。要做到这一点,请遵循 which is in turn based on https://bitcoin.stackexchange.com/questions/66594/signing-transaction-with-ssl-private-key-to-pem 的原则,除了使用 P-384 的 OID 和大小而不是 secp256k1。具体来说,连接

  • 303e0201010430 以十六进制表示的 7 个字节
  • 原始私钥的 48 个字节(384 位)
  • a00706052b81040022(对于 P-384 又名 secp384r1)以十六进制表示的 9 个字节

根据您使用的语言或工具,您可以直接处理这些值,或者连接十六进制表示,然后转换为二进制。结果是算法特定(SEC1)私钥(仅)的 'DER'(二进制)形式,可以由 nodejs 11 或 12 crypto.createPrivateKey( {key:(data), format:'der', type:'sec1'} ) 以及命令行 openssl ec -inform der 读取.

如果您更喜欢类似文本的东西(例如剪切和粘贴),请将上面的 DER 转换为 base64,分成 64 个字符的行(除了最后一个),并在 -----BEGIN EC PRIVATE KEY----- 和 [=15= 之前添加行] 后。这是 PEM 格式,createPrivateKey 无需任何其他选项即可读取,openssl ec 无需任何选项即可读取。