跳转至

openssl:基于 FFI 的 OpenSSL 绑定,用于 nginx-module-lua

安装

如果您尚未设置 RPM 仓库订阅,请注册。然后您可以按照以下步骤进行操作。

CentOS/RHEL 7 或 Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-openssl

CentOS/RHEL 8+、Fedora Linux、Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-openssl

要将此 Lua 库与 NGINX 一起使用,请确保已安装 nginx-module-lua

本文档描述了 lua-resty-openssl v1.9.0, 该版本于 2026 年 8 月 14 日发布。


基于 FFI 的 OpenSSL 绑定,适用于 LuaJIT,支持 OpenSSL 3、4 以及 1.1.1 系列。

对 OpenSSL 1.1.0、1.0.2 和 BoringSSL 的支持已被移除,但仍可在 0.x 分支 中找到。

构建状态 luarocks opm

描述

lua-resty-openssl 是一个基于 FFI 的 OpenSSL 绑定库,目前支持 OpenSSL 3.x4.x 以及 1.1.1 系列。

概要

该库深受 luaossl 的启发,并采用了更接近原始 OpenSSL API 的命名转换方式。 例如,OpenSSL C API 中名为 X509_set_pubkey 的函数被暴露为 resty.openssl.x509:set_pubkeyCamelCase 命名被替换为 下划线命名,例如 X509_set_serialNumber 变为 resty.openssl.x509:set_serial_number。与 luaossl 的另一个区别是,错误不会使用 error() 抛出,而是作为最后一个参数返回。

每个由 new() 返回的 Lua 表都包含一个 cdata 对象 ctx。用户不应手动设置 ffi.gc 或调用 ctx 结构体对应的析构函数(如 *_free 函数)。

resty.openssl

这个元模块提供了针对所链接的 OpenSSL 库的版本健全性检查。

openssl.load_library

语法: name, err = openssl.load_library()

尝试加载 OpenSSL 共享库。此函数会尝试几种已知的库名称模式,并在成功加载时返回 crypto 库的名称,否则返回错误。

当在 resty CLI 或启用了 SSL 的 OpenResty 中运行时,无需调用此函数。

openssl.load_modules

语法: openssl.load_modules()

将所有可用的子模块加载到当前模块中:

  bn = require("resty.openssl.bn"),
  cipher = require("resty.openssl.cipher"),
  digest = require("resty.openssl.digest"),
  hmac = require("resty.openssl.hmac"),
  kdf = require("resty.openssl.kdf"),
  pkey = require("resty.openssl.pkey"),
  objects = require("resty.openssl.objects"),
  rand = require("resty.openssl.rand"),
  version = require("resty.openssl.version"),
  x509 = require("resty.openssl.x509"),
  altname = require("resty.openssl.x509.altname"),
  chain = require("resty.openssl.x509.chain"),
  csr = require("resty.openssl.x509.csr"),
  crl = require("resty.openssl.x509.crl"),
  extension = require("resty.openssl.x509.extension"),
  extensions = require("resty.openssl.x509.extensions"),
  name = require("resty.openssl.x509.name"),
  store = require("resty.openssl.x509.store"),
  ssl = require("resty.openssl.ssl"),
  ssl_ctx = require("resty.openssl.ssl_ctx"),

从 OpenSSL 3.0 开始,providermacctx 也可用。

openssl.luaossl_compat

语法: openssl.luaossl_compat()

提供使用 camelCase 命名的 luaossl 风格 API;用户可以期望直接替换。

例如,pkey:get_parameters 映射到 pkey:getParameters

请注意,并非所有 luaossl API 都已实现,请查看 readme 以获取权威信息。

openssl.get_fips_mode

语法: enabled = openssl.get_fips_mode()

返回一个布尔值,指示 FIPS 模式是否已启用。

openssl.set_fips_mode

语法: ok, err = openssl.set_fips_mode(enabled)

切换 FIPS 模式的开启或关闭。

lua-resty-openssl 支持以下模式:

带有 fips 2.0 模块的 OpenSSL 1.0.2 系列

根据安全策略编译模块,

OpenSSL 3 FIPS provider

参考 https://wiki.openssl.org/index.php/OpenSSL_3.0 第 7 节 根据指南编译 provider,安装与 FIPS provider fips.so 哈希匹配的 fipsmodule.cnf。

从 OpenSSL 3.0 开始,此函数还会开启和关闭 EVP 函数的默认属性。当开启时,所有使用 EVP_* API 的应用程序将被重定向到符合 FIPS 标准的实现,并且无法访问不符合 FIPS 标准的算法。

调用此函数等同于加载 fips provider 并调用 openssl.set_default_properties("fips=yes")

如果 FIPS provider 已加载但未设置默认属性,请使用以下方法显式获取 FIPS 实现。

local provider = require "resty.openssl.provider"
assert(provider.load("fips"))
local cipher = require "resty.openssl.cipher"
local c = assert(cipher.new("aes256"))
print(c:get_provider_name()) -- 打印 "default"
local c = assert(cipher.new("aes256", "fips=yes"))
print(c:get_provider_name()) -- 打印 "fips"

openssl.get_fips_version_text

语法: text, err = openssl.get_fips_version_text()

返回 FIPS 模块的版本文本,适用于 OpenSSL 3.0 或更高版本。

openssl.set_default_properties

语法: ok, err = openssl.set_default_properties(props)

为所有未来的 EVP 算法获取(隐式和显式)设置默认属性。有关隐式和显式获取的信息,请参阅 crypto(7) 中的 "ALGORITHM FETCHING"。

openssl.list_cipher_algorithms

语法: ret = openssl.list_cipher_algorithms(hide_provider?)

以数组形式返回可用的密码算法。设置 hide_providertrue 以从结果中隐藏 provider 名称。

openssl.list_digest_algorithms

语法: ret = openssl.list_digest_algorithms(hide_provider?)

以数组形式返回可用的摘要算法。设置 hide_providertrue 以从结果中隐藏 provider 名称。

openssl.list_mac_algorithms

语法: ret = openssl.list_mac_algorithms(hide_provider?)

以数组形式返回可用的 MAC 算法。设置 hide_providertrue 以从结果中隐藏 provider 名称。

openssl.list_kdf_algorithms

语法: ret = openssl.list_kdf_algorithms(hide_provider?)

以数组形式返回可用的 KDF 算法。设置 hide_providertrue 以从结果中隐藏 provider 名称。

openssl.list_ssl_ciphers

语法: cipher_string, err = openssl.list_ssl_ciphers(cipher_list?, ciphersuites?, protocol?)

以字符串形式返回默认的 SSL 密码套件。cipher_list(TLSv1.3 之前)和 ciphersuites(TLSv1.3)可用于扩展与 protocol 匹配的密码设置。OpenSSL 4.x 拒绝 "SSLv3",因为 SSLv3 支持已被移除。

openssl.list_ssl_ciphers()
openssl.list_ssl_ciphers("ECDHE-ECDSA-AES128-SHA")
openssl.list_ssl_ciphers("ECDHE-ECDSA-AES128-SHA", nil, "TLSv1.2")
openssl.list_ssl_ciphers("ECDHE-ECDSA-AES128-SHA", "TLS_CHACHA20_POLY1305_SHA256", "TLSv1.3")

resty.openssl.ctx

提供 OSSL_LIB_CTX 上下文切换的模块。

OSSL_LIB_CTX 是 OpenSSL 内部库上下文类型。应用程序可以自行分配,但也可以使用 NULL 来使用带有 OSSL_LIB_CTX 参数的函数的默认上下文。

有关更深入的阅读,请参阅 OSSL_LIB_CTX.3

当前上下文对以下模块有效:

此模块适用于 OpenSSL 3.0 或更高版本。

ctx.new

语法: ok, err = ctx.new(request_context_only?, conf_file?)

创建一个新的上下文,并将其用作此模块的默认上下文。当 request_context_only 设置为 true 时,该上下文仅在当前请求的上下文中使用。conf_file 可选地指定用于创建上下文的 OpenSSL conf 文件。

创建的上下文会随着其给定的生命周期自动释放。

-- 仅为当前请求从给定的 provider 实现初始化一个 AES 密码实例,
-- 不干扰其他代码部分或未来请求使用相同的算法。
assert(require("resty.openssl.ctx").new(true))
local p = assert(require("resty.openssl.provider").load("myprovider"))
local c = require("resty.openssl.cipher").new("aes256")
print(c:encrypt(string.rep("0", 32), string.rep("0", 16), "🦢"))
-- 无需释放 provider 和 ctx,它们会被自动 GC

ctx.free

语法: ctx.free(request_context_only?)

释放先前由 ctx.new 创建的上下文。

resty.openssl.err

提供错误消息的模块。

err.format_error

语法: msg = err.format_error(ctx_msg?, return_code?, all_errors?)

语法: msg = err.format_all_errors(ctx_msg?, return_code?)

返回最后一个错误码的最新错误消息。错误格式如下:

[ctx_msg]: https://github.com/fffonion/lua-resty-openssl/blob/1.9.0/code: [return_code]: error:[error code]:[library name]:[func name]:[reason string]:[file name]:[line number]:

对于早于 3.0 的 OpenSSL 版本,错误格式如下:

[ctx_msg]: https://github.com/fffonion/lua-resty-openssl/blob/1.9.0/code: [return_code]: [file name]:[line number]:error:[error code]:[library name]:[func name]:[reason string]:

如果 all_errors 设置为 true,则所有错误(不仅仅是最后一个)将以单个字符串形式返回。此库内部抛出的所有错误仅抛出最新错误。

例如:

local f = io.open("t/fixtures/ec_key_encrypted.pem"):read("*a")
local privkey, err = require("resty.openssl.pkey").new(f, {
    format = "PEM",
    type = "pr",
    passphrase = "wrongpasswrod",
})
ngx.say(err)
-- pkey.new:load_key: error:4800065:PEM routines:PEM_do_header:bad decrypt:crypto/pem/pem_lib.c:467:

err.get_last_error_code

语法: code = err.get_last_error_code()

返回最后一个错误码。

err.get_lib_error_string

语法: lib_error_message = err.get_lib_error_string(code?)

以字符串形式返回最后一个错误码的库名称。如果设置了 code,则返回与提供的错误码对应的库名称。

err.get_reason_error_string

语法: reason_error_message = err.get_reason_error_string(code?)

以字符串形式返回最后一个错误码的原因。如果设置了 code,则返回与提供的错误码对应的原因。

resty.openssl.version

提供版本信息的模块。

resty.openssl.provider

与 providers 交互的模块。此模块仅适用于 OpenSSL 3.0 或更高版本。

provider.load

语法: pro, err = provider.load(name, try?)

加载名为 name 的 provider。如果 try 设置为 true,则当 provider 无法加载和初始化时,OpenSSL 不会禁用后备 providers。但是,如果 provider 加载成功,后备 providers 将被禁用。

默认情况下,此函数将 provider 加载到默认上下文中,这意味着它会影响同一进程中使用默认上下文的其他应用程序。如果不需要这种行为,请考虑使用 ctx 将 provider 仅加载到有限范围内。

provider.istype

语法: ok = pkey.provider(table)

如果 tableprovider 的实例,则返回 true。否则返回 false

provider.is_available

语法: ok, err = provider.is_available(name)

检查指定名称的 provider 是否可用于使用。

provider.set_default_search_path

语法: ok, err = provider.set_default_search_path(name)

指定用于查找 providers 的默认搜索路径。

provider:unload

语法: ok, err = pro:unload(name)

卸载先前由 provider.load 加载的 provider。

provider:self_test

语法: ok, err = pro:self_test(name)

按需运行 provider 的自检。如果自检失败,则 provider 将无法提供任何进一步的服务和算法。

provider:get_params

语法: ok, err = pro:get_params(key1, key2?...)

返回一个或多个 provider 参数值。

local pro = require "resty.openssl.provider"

local p = pro.load("default")

local name = assert(p:get_params("name"))
print(name)
-- 输出 "OpenSSL Default Provider"

local result = assert(p:get_params("name", "version", "buildinfo", "status"))
print(require("cjson").encode(result))
-- 输出 provider 元数据;version 和 buildinfo 因 OpenSSL 版本而异

resty.openssl.pkey

与私钥和公钥(EVP_PKEY)交互的模块。

每种密钥类型可能仅支持部分操作:

密钥类型 加载现有密钥 密钥生成 加密/解密 签名/验证 密钥交换 封装/解封装
RSA 是 (RSASVE, OpenSSL 3.5+)
DH
EC 是 (ECDSA) 是 (ECDH) 是 (DHKEM, OpenSSL 3.5+)
Ed25519 是 (PureEdDSA)
X25519 是 (ECDH) 是 (DHKEM, OpenSSL 3.5+)
Ed448 是 (PureEdDSA)
X448 是 (ECDH) 是 (DHKEM, OpenSSL 3.5+)
ML-DSA (OpenSSL 3.5+)
SLH-DSA (OpenSSL 3.5+)
ML-KEM (OpenSSL 3.5+)
ML-KEM TLS hybrid (OpenSSL 3.5+) 取决于 Provider

EC 和 ECX 密钥不直接支持加密和解密,但可以通过 pkey:derivekdfcipher 实现 ECIES 等过程。

pkey.new

加载现有密钥

语法: pk, err = pkey.new(string, opts?)

支持加载以 PEM、DER 或 JWK 格式作为第一个参数 string 传入的私钥或公钥。

第二个参数 opts 接受一个可选的表来约束密钥加载行为。

  • opts.format:显式设置为 "PEM""DER""JWK" 以加载特定格式,或设置为 "*" 以自动检测
  • opts.type:显式设置为 "pr" 表示私钥,"pu" 表示公钥;设置为 "*" 以自动检测

加载 PEM 编码的 RSA 密钥时,它可以是 PKCS#8 编码的 SubjectPublicKeyInfo/PrivateKeyInfo,也可以是 PKCS#1 编码的 RSAPublicKey/RSAPrivateKey

加载加密的 PEM 编码密钥时,用于解密的 passphrase 可以设置在 opts.passphraseopts.passphrase_cb 中:

pkey.new(pem_or_der_text, {
  format = "*", -- 选择 "PEM"、"DER"、"JWK" 或 "*" 以自动检测
  type = "*", -- 选择 "pr" 表示私钥,"pu" 表示公钥,"*" 表示自动检测
  passphrase = "secret password", -- PEM 加密口令
  passphrase_cb = function()
    return "secret password"
  end, -- PEM 加密口令回调函数
}

加载 JWK 时,有几点需要注意: - 确保传入的是编码后的 JSON 文本,它必须已经过 base64 解码。 - 约束 opts.type 用于 JWK 密钥需要 OpenSSL 3.0 或更高版本以及 lua-resty-openssl 1.6.0 或更高版本。对于 OpenSSL 1.1.1 或更旧的 lua-resty-openssl 版本,提供的 JSON 中的参数将决定加载的是私钥还是公钥,指定 type 将导致错误;此外,OKP 密钥的公钥部分(x 参数)不被识别,如果指定了私钥部分(d 参数),则会从中派生。 - 仅支持 RSAP-256P-384P-512 ECEd25519X25519Ed448X448 OKP 密钥类型。 - 对于 EC 密钥,签名和验证必须使用 ecdsa_use_raw 选项才能与 JWS 标准兼容。有关详细信息,请参阅 pkey:signpkey.verify。 - 在 OpenResty 之外运行时,需要安装 JSON 库(cjsondkjson)和 basexx

密钥生成

语法: pk, err = pkey.new(config?)

生成新的公钥或私钥。

要生成 RSA 密钥,config 表可以包含 bitsexp 字段来控制密钥生成。当省略 config 时,此函数生成一个 exponent 为 65537 的 2048 位 RSA 密钥,等效于:

local key, err = pkey.new({
  type = 'RSA',
  bits = 2048,
  exp = 65537
})

要生成 EC 或 DH 密钥,请参阅 pkey.paramgen 了解 config 表的可能值。例如:

local key, err = pkey.new({
  type = 'EC',
  curve = 'prime256v1',
})

在 OpenSSL 3.0 或更高版本上,可以通过名称请求由已加载 provider 实现的任何密钥类型。例如,OpenSSL 3.5 或更高版本提供了后量子密钥类型,包括:

local ml_dsa = assert(pkey.new({ type = "ML-DSA-44" }))
local ml_kem = assert(pkey.new({ type = "ML-KEM-768" }))
local slh_dsa = assert(pkey.new({ type = "SLH-DSA-SHA2-128s" }))

config.properties 可用于为这些 provider 原生密钥类型选择 provider 实现。

也可以将 PEM 编码的 EC 或 DH 参数传递给 config.param 以进行密钥生成:

local dhparam = pkey.paramgen({
  type = 'DH',
  group = 'dh_1024_160'
})
-- 或者
-- local dhparam = io.read("dhparams.pem"):read("*a")

local key, err = pkey.new({
  type = 'DH',
  param = dhparam,
}) 

也可以在 config 表中传递原始 pkeyopt 控制字符串,如 genpkey CLI 程序中所用。 有关选项列表,请参阅 openssl-genpkey(1)

例如:

pkey.new({
  type = 'RSA',
  bits = 2048,
  exp = 65537,
})
-- 等同于
pkey.new({
  type = 'RSA',
  exp = 65537,
  "rsa_keygen_bits:4096",
})

密钥组合

语法: pk, err = pkey.new(config?)

使用现有参数组合公钥或私钥。要查看每种密钥的参数列表,请参阅 pkey:set_parameters

config 表中应仅包含 typeparams,所有其他键将被忽略。

local private_bn = require "resty.openssl.bn".new("7F48282CCA4C1A65D589C06DBE9C42AE50FBFFDF3A18CBB48498E1DE47F11BE1A3486CD8FA950D68F111970F922279D8", 16)
local p_384, err = assert(require("resty.openssl.pkey").new({
    type = "EC",
    params = {
        private = private_bn,
        group = "secp384r1",
    }
}))

pkey.istype

语法: ok = pkey.istype(table)

如果 tablepkey 的实例,则返回 true。否则返回 false

pkey.paramgen

语法: pem_txt, err = pk.paramgen(config)

为 EC 或 DH 密钥生成参数,并输出为 PEM 编码文本。

对于 EC 密钥:

参数 描述
type "EC"
curve EC 曲线。如果省略,默认为 "prime192v1"。要查看支持的 EC 曲线列表,请使用 openssl ecparam -list_curves

对于 DH 密钥:

参数 描述
type "DH"
bits 生成一个具有 bits 长素数的新 DH 参数。如果省略,默认为 2048。从 OpenSSL 3.0 开始,仅允许 bits 等于 2048。
group 使用预定义组而不是生成新组。如果设置了 groupbit 将被忽略。

group 的可能值为: - RFC7919 "ffdhe2048""ffdhe3072""ffdhe4096""ffdhe6144""ffdhe8192" - RFC5114 "dh_1024_160""dh_2048_224""dh_2048_256" - RFC3526 "modp_1536""modp_2048""modp_3072""modp_4096""modp_6144""modp_8192"

local pem, err = pkey.paramgen({
  type = 'EC',
  curve = 'prime192v1',
})

local pem, err = pkey.paramgen({
  type = 'DH',
  group = 'ffdhe4096',
})

也可以在 config 表中传递原始 pkeyopt 控制字符串,如 genpkey CLI 程序中所用。 有关选项列表,请参阅 openssl-genpkey(1)

pkey:get_provider_name

语法: name = pkey:get_provider_name()

返回 pkey 的 provider 名称。

此函数适用于 OpenSSL 3.0 或更高版本。

pkey:gettable_params、pkey:settable_params、pkey:get_param、pkey:set_params

查询可设置或可获取的参数,并设置或获取参数。 请参阅 通用 EVP 参数获取器/设置器

pkey:get_parameters

语法: parameters, err = pk:get_parameters()

返回包含 pkey 实例 parameters 的表。

对于 ECX 密钥以及 OpenSSL 3 provider 原生密钥(如 ML-KEM、ML-DSA、SLH-DSA 和 ML-KEM TLS hybrid 密钥),当 provider 允许导出这些组件时,该表会暴露二进制的 publicprivate 字段。某些 provider 有意不导出私钥组件。

pkey:set_parameters

语法: ok, err = pk:set_parameters(params)

从表 params 设置 pkey 的参数。如果 params 表中未设置该参数,则 pkey 实例中的该参数保持不变。

对于 ECX 密钥以及 OpenSSL 3 provider 原生密钥,publicprivate 包含原始二进制密钥组件。设置任一组件都会替换底层不可变的 provider 密钥,同时保留 pkey 对象。

local pk, err = require("resty.openssl.pkey").new()
local parameters, err = pk:get_parameters()
local e = parameters.e
ngx.say(e:to_number())
-- 输出 65537

local ok, err = pk:set_parameters({
  e = require("resty.openssl.bn").from_hex("100001")
})

local ok, err = pk:set_parameters(parameters)

RSA 密钥的参数:

参数 描述 类型
n 公钥和私钥共有的模数 bn
e 公开指数 bn
d 私有指数 bn
p n 的第一个因子 bn
q n 的第二个因子 bn
dmp1 d mod (p - 1),指数1 bn
dmq1 d mod (q - 1),指数2 bn
iqmp (InverseQ)(q) = 1 mod p,系数 bn

EC 密钥的参数:

参数 描述 类型
private 私钥 bn
public 公钥 bn
x 公钥的 x 坐标 bn
y 公钥的 y 坐标 bn
group 命名曲线组 [NID] 作为数字,当作为 set_parameters() 传入时,也可以使用文本表示。这与 luaossl 不同,后者返回 EC_GROUP 实例。

不能同时设置 xypublic,因为 xy 基本上是 public 的另一种表示形式。此外,目前只能同时设置 xy

DH 密钥的参数:

参数 描述 类型
private 私钥 bn
public 公钥 bn
p 素数模数 bn
q 参考位置 bn
g 基础生成器 bn

Curve25519 和 Curve448 密钥的参数:

参数 描述 类型
private 以字节表示的原始私钥 string
public 以字节表示的原始公钥 string

pkey:is_private

语法: ok = pk:is_private()

检查 pk 是否为私钥。如果是私钥则返回 true,如果是公钥则返回 false。

pkey:get_key_type

语法: obj, err = pk:get_key_type(nid_only?)

以表的形式返回私钥密钥类型的 ASN1_OBJECT。

从 lua-resty-openssl 1.6.0 开始,可以设置可选参数 nid_onlytrue,仅返回密钥的数字 NID。

在 OpenSSL 3.0 或更高版本上,此方法为现有密钥类型保留历史 NID 和 ASN.1 表。具有指定 OID 的标准化后量子密钥类型(如 ML-KEM、ML-DSA 和 SLH-DSA)使用其 OID NID 返回相同的表结构。没有指定 OID 的仅 provider 密钥类型返回 nil 和错误,而不是合成 NID。

local pkey, err = require("resty.openssl.pkey").new({type="X448"})

ngx.say(require("cjson").encode(pkey:get_key_type()))
-- 输出 '{"ln":"X448","nid":1035,"sn":"X448","id":"1.3.101.111"}'
ngx.say(pkey:get_key_type(true))
-- 输出 1035

pkey:get_size

语法: size, err = pk:get_size()

返回几乎所有可以使用 pkey 完成的操作的输出缓冲区的最大合适大小。

对于 RSA 密钥,这是模数的大小。 对于 EC、Ed25519 和 Ed448 密钥,这是私钥的大小。 对于 DH 密钥,这是素数模数的大小。

pkey:get_default_digest_type

语法: obj, err = pk:get_default_digest_type()

以表的形式返回私钥密钥类型的 ASN1_OBJECT。表中还会返回一个额外的字段 mandatory,如果 mandatory 为 true,则不能使用其他摘要。

local pkey, err = require("resty.openssl.pkey").new()

ngx.say(require("cjson").encode(pkey:get_default_digest_type()))
-- 输出 '{"ln":"sha256","nid":672,"id":"2.16.840.1.101.3.4.2.1","mandatory":false,"sn":"SHA256"}'

pkey:sign

语法: signature, err = pk:sign(digest)

语法: signature, err = pk:sign(message, md_alg?, padding?, opts?)

使用 pkey 实例中定义的私钥执行摘要签名。第一个参数必须是 resty.openssl.digest 实例或字符串。返回签名文本和错误(如果有)。

当第一个参数传递 digest 实例时,不应已调用 final();用户应仅使用 update()。此模式仅支持 RSA 和 EC 密钥。

当第一个参数传递字符串时,md_alg 参数将指定签名时要使用的名称。当 md_alg 未定义时,对于 RSA 和 EC 密钥,此函数默认执行 SHA256。对于 Ed25519 或 Ed448 密钥,此函数执行 PureEdDSA 签名,不应指定消息摘要,也不会使用。

对于 RSA 密钥,还可以使用以下选项指定 padding 方案:

  pkey.PADDINGS = {
    RSA_PKCS1_PADDING       = 1,
    RSA_SSLV23_PADDING      = 2,
    RSA_NO_PADDING          = 3,
    RSA_PKCS1_OAEP_PADDING  = 4,
    RSA_X931_PADDING        = 5, -- 仅签名
    RSA_PKCS1_PSS_PADDING   = 6, -- 仅签名和验证
  }

paddingRSA_PKCS1_PSS_PADDING 时,可以通过设置 opts.pss_saltlen 来指定 PSS 盐长度。

对于 EC 密钥,此函数执行 ECDSA 签名。 请注意,OpenSSL 不支持使用