erlang - 升级到 OTP 18 会破坏 public_key 库的使用

标签 erlang elixir elliptic-curve

在 Elixir 中构建 pem 文件需要几个步骤,包括构建实体。在 OTP 17 中,可以执行以下操作:

{public, private} = :crypto.generate_key(:ecdh, :secp256k1)
ec_entity = {:ECPrivateKey,                                                                                                                                                                                             
  1,                                                                                                                                                                                                        
  :binary.bin_to_list(private),                                                                                                                                                                             
  {:namedCurve, {1, 3, 132, 0, 10}},                                                                                                                                                                        
  {0, public}}
der_encoded = :public_key.der_encode(:ECPrivateKey, ec_entity)
pem = public_key.pem_encode([{:ECPrivateKey, der_encoded, :not_encrypted}])

但是使用OTP 18,会出现以下错误:

{public, private} = :crypto.generate_key(:ecdh, :secp256k1)
ec_entity = {:ECPrivateKey,                                                                                                                                                                                             
  1,                                                                                                                                                                                                        
  :binary.bin_to_list(private),                                                                                                                                                                             
  {:namedCurve, {1, 3, 132, 0, 10}},                                                                                                                                                                        
  {0, public}}
der_encoded = :public_key.der_encode(:ECPrivateKey, ec_entity)
** (MatchError) no match of right hand side value: {:error, {:asn1, :badarg}}
public_key.erl:253: :public_key.der_encode/2

这个错误的根源是什么?

最佳答案

错误的根源在于 OTP 17 和 OTP 18 之间构造 public_key 实体的方式发生了变化。如果我们从 pem 文件开始反转该过程,我们可以看到差异。

OTP 17:

iex(6)> pem = "-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIJniJF4vtTqE4wS5AkhmMZsHIbil0l3XfRButkw5IJYFoAcGBSuBBAAK\noUQDQgAEtxm+jijBB0JxZTceHnCHE0HpMXJp1ScVUZ5McvDUVsS/Dek8IdAsMOPz\nnnVALflZzXtH/wU9p2LrFdJeuXwL8g==\n-----END EC PRIVATE KEY-----\n\n"
"-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIJniJF4vtTqE4wS5AkhmMZsHIbil0l3XfRButkw5IJYFoAcGBSuBBAAK\noUQDQgAEtxm+jijBB0JxZTceHnCHE0HpMXJp1ScVUZ5McvDUVsS/Dek8IdAsMOPz\nnnVALflZzXtH/wU9p2LrFdJeuXwL8g==\n-----END EC PRIVATE KEY-----\n\n"
iex(7)> [{type, decoded, _}] = :public_key.pem_decode(pem)
[{:ECPrivateKey,
  <<48, 116, 2, 1, 1, 4, 32, 153, 226, 36, 94, 47, 181, 58, 132, 227, 4, 185, 2, 72, 102, 49, 155, 7, 33, 184, 165, 210, 93, 215, 125, 16, 110, 182, 76, 57, 32, 150, 5, 160, 7, 6, 5, 43, 129, 4, 0, 10, ...>>, 
  :not_encrypted}]
iex(8)> :public_key.der_decode(type, decoded)
{:ECPrivateKey, 1,
 [153, 226, 36, 94, 47, 181, 58, 132, 227, 4, 185, 2, 72, 102, 49, 155, 7, 33,
  184, 165, 210, 93, 215, 125, 16, 110, 182, 76, 57, 32, 150, 5],
 {:namedCurve, {1, 3, 132, 0, 10}},
 {0,
  <<4, 183, 25, 190, 142, 40, 193, 7, 66, 113, 101, 55, 30, 30, 112, 135, 19, 65, 233, 49, 114, 105, 213, 39, 21, 81, 158, 76, 114, 240, 212, 86, 196, 191, 13, 233, 60, 33, 208, 44, 48, 227, 243, 158, 117, ...>>}}

OTP 18:

iex(5)> [{type, decoded, _}] = :public_key.pem_decode(pem)
[{:ECPrivateKey,
  <<48, 116, 2, 1, 1, 4, 32, 153, 226, 36, 94, 47, 181, 58, 132, 227, 4, 185, 2, 72, 102, 49, 155, 7, 33, 184, 165, 210, 93, 215, 125, 16, 110, 182, 76, 57, 32, 150, 5, 160, 7, 6, 5, 43, 129, 4, 0, 10, ...>>, 
  :not_encrypted}]
iex(6)> entity = :public_key.der_decode(type, decoded)
{:ECPrivateKey, 1,
 <<153, 226, 36, 94, 47, 181, 58, 132, 227, 4, 185, 2, 72, 102, 49, 155, 7, 33, 184, 165, 210, 93, 215, 125, 16, 110, 182, 76, 57, 32, 150, 5>>,
 {:namedCurve, {1, 3, 132, 0, 10}},
 <<4, 183, 25, 190, 142, 40, 193, 7, 66, 113, 101, 55, 30, 30, 112, 135, 19, 65, 233, 49, 114, 105, 213, 39, 21, 81, 158, 76, 114, 240, 212, 86, 196, 191, 13, 233, 60, 33, 208, 44, 48, 227, 243, 158, 117, 64, ...>>}

区别在于公钥和私钥的表示方式。

ECPrivateKey 记录的签名是: ECPrivateKey'{版本,私钥,参数,公钥}

在 Erlang 18 中,两个值都以普通二进制表示,在 17 中,私钥是一个列表,公钥是元组的一部分,{0, binary}

因此,为了正确构建 pem 文件,必须更改实体表示。

{public, private} = :crypto.generate_key(:ecdh, :secp256k1)
entity = {:ECPrivateKey,                                                                                                                                                                                             
  1,                                                                                                                                                                                                        
  private,                                                                                                                                                                                                  
  {:namedCurve, {1, 3, 132, 0, 10}},                                                                                                                                                                        
  public}      

使用新的记录表示将解决问题。

关于erlang - 升级到 OTP 18 会破坏 public_key 库的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38944582/

相关文章:

python - 哪个适用于 python 和 Erlang 的 Actor 模型库/框架?

erlang - 是否可以在不编译的情况下运行erlang?

erlang - 元组模块是该语言的官方文档功能吗?

rabbitmq - RabbitMQ 升级到 3.11.12 后无 AMQP 连接

ios - ios/swift 中的椭圆曲线 Diffie Hellman

Javascript椭圆点乘算法

java - 根据 RFC 测试 vector 计算 Java 中的 ECDSA 签名

cryptography - 如何在 Elixir 中进行 AES-256-ECB 加密?

elixir - 在 Elixir 异常退出后,有没有办法重新启动具有不同配置的 GenServer?

elixir - 使用保护子句自省(introspection)函数