跳到主要内容
ecdsa.com
Ruby openssl gemRuby

错误信息

Could not parse PKey (OpenSSL::PKey::PKeyError)

也可能输出为

  • OpenSSL::PKey::PKeyError: Could not parse PKey
  • Neither PUB key nor PRIV key (OpenSSL::PKey::RSAError)
  • invalid curve name (OpenSSL::PKey::ECError)

异常未被捕获时,Ruby 会打印“…: Could not parse PKey (OpenSSL::PKey::PKeyError)”。各个类专用的构造函数会抛出 `OpenSSL::PKey::RSAError` / `ECError`,并带有各自的文本。

Ruby openssl gem — OpenSSL::PKey.read / OpenSSL::PKey::RSA.new / OpenSSL::PKey::EC.new

含义

`OpenSSL::PKey.read` 尝试了 OpenSSL 支持的所有密钥格式(PEM 和 DER、公钥和私钥、用给定密码加密的密钥),全都失败了。Ruby 不会转述 OpenSSL 给出的具体原因,因此同一条文本既可能表示 PEM 损坏,也可能表示密码短语错误,还可能表示数据根本不是密钥。针对特定算法的构造函数也会以类似方式失败:`RSA.new` 报出“Neither PUB key nor PRIV key”,`EC.new` 报出“invalid curve name”(它会把无法解析的输入当作曲线名称)。

原因

修复方法

  1. 1.

    恢复换行符,并检查加载的内容

    把 `\n` 序列还原为换行符,在启动时读取一次密钥,并断言它的类型以及是否为私钥。

    ruby
    pem = ENV.fetch("JWT_PUBLIC_KEY").gsub("\\n", "\n")   # restore real newlines
    key = OpenSSL::PKey.read(pem)
    raise "expected a public EC key" if key.private? || !key.is_a?(OpenSSL::PKey::EC)
  2. 2.

    把多行密钥存放在不会被破坏的地方

    与单行的环境变量不同,Rails 加密凭证或挂载的机密文件能原样保留 PEM。

    ruby
    # Rails: keep multi-line keys in encrypted credentials instead of ENV
    # bin/rails credentials:edit
    #   jwt:
    #     public_key: |
    #       -----BEGIN PUBLIC KEY-----
    #       ...
    key = OpenSSL::PKey.read(Rails.application.credentials.dig(:jwt, :public_key))

相关错误

浏览完整的签名错误库