模块 OpenSSL::PKey
非对称公钥算法¶ ↑
非对称公钥算法解决了建立和共享用于加密/解密消息的密钥的问题。这种算法中的密钥由两部分组成:可以分发给其他人的公钥和需要保密的私钥。
用公钥加密的消息只能由持有相关私钥的接收者解密。由于公钥算法比对称密钥算法(参见 OpenSSL::Cipher
)慢得多,因此它们通常用于在持有彼此公钥的两方之间建立共享的对称密钥。
非对称算法提供了许多很好的特性,这些特性被用于许多不同的领域。一个非常常见的应用是创建和验证数字签名。为了签署文档,签署人通常使用消息摘要算法(参见 OpenSSL::Digest
)来计算文档的摘要,然后使用私钥加密(即签名)该摘要。任何持有公钥的人都可以通过自行计算原始文档的消息摘要,使用签署人的公钥解密签名,并将结果与他们之前计算的消息摘要进行比较来验证签名。当且仅当解密的签名等于此消息摘要时,签名才有效。
PKey
模块为三种流行的公钥/私钥算法提供支持
-
椭圆曲线密码学 (
OpenSSL::PKey::EC
)
这些实现的每一个实际上都是抽象 PKey
类的子类,它提供了以 PKey#sign
和 PKey#verify
的形式支持数字签名的接口。
迪菲-赫尔曼密钥交换¶ ↑
最后,PKey
还提供了 OpenSSL::PKey::DH
,它是基于有限域中离散对数的迪菲-赫尔曼密钥交换协议的实现,这也是 DSA
的基础。DH
可以用来在不安全的通道上交换(对称)密钥,而不需要参与方之间有任何事先的共同知识。由于 DH
的安全性需要相对较长的“公钥”(即在参与者之间公开传输的部分),因此 DH
往往很慢。如果安全或速度是您的主要考虑因素,OpenSSL::PKey::EC
提供了迪菲-赫尔曼协议的另一种实现。
公共类方法
源码
static VALUE ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self) { return pkey_generate(argc, argv, self, 0); }
生成一个新的密钥(对)。
如果将 String
作为第一个参数给出,它将为名称指定的算法生成一个新的随机密钥,就像 ::generate_parameters
所做的那样。如果改为给出 OpenSSL::PKey::PKey
,它将使用密钥包含的参数为与密钥相同的算法生成一个新的随机密钥。
有关options和给定块的详细信息,请参见 ::generate_parameters
。
示例¶ ↑
pkey_params = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048) pkey_params.priv_key #=> nil pkey = OpenSSL::PKey.generate_key(pkey_params) pkey.priv_key #=> #<OpenSSL::BN 6277...
源码
static VALUE ossl_pkey_s_generate_parameters(int argc, VALUE *argv, VALUE self) { return pkey_generate(argc, argv, self, 1); }
为算法生成新的参数。algo_name 是一个表示算法的 String
。可选参数 options 是一个 Hash
,用于指定特定于该算法的选项。选项的顺序可能很重要。
可以可选地传递一个块。传递给块的参数的含义因算法的实现而异。该块可能会被调用一次或多次,甚至可能不会被调用。
有关支持的选项,请参阅“openssl genpkey”实用程序命令的文档。
示例¶ ↑
pkey = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048) p pkey.p.num_bits #=> 2048
源码
static VALUE ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key) { EVP_PKEY *pkey; const EVP_PKEY_ASN1_METHOD *ameth; int pkey_id; size_t keylen; StringValue(type); StringValue(key); ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type)); if (!ameth) ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type); EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); keylen = RSTRING_LEN(key); pkey = EVP_PKEY_new_raw_private_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen); if (!pkey) ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key"); return ossl_pkey_new(pkey); }
请参阅 OpenSSL
文档中的 EVP_PKEY_new_raw_private_key()
源码
static VALUE ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key) { EVP_PKEY *pkey; const EVP_PKEY_ASN1_METHOD *ameth; int pkey_id; size_t keylen; StringValue(type); StringValue(key); ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type)); if (!ameth) ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type); EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); keylen = RSTRING_LEN(key); pkey = EVP_PKEY_new_raw_public_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen); if (!pkey) ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key"); return ossl_pkey_new(pkey); }
请参阅 OpenSSL
文档中的 EVP_PKEY_new_raw_public_key()
源码
static VALUE ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; BIO *bio; VALUE data, pass; rb_scan_args(argc, argv, "11", &data, &pass); bio = ossl_obj2bio(&data); pkey = ossl_pkey_read_generic(bio, ossl_pem_passwd_value(pass)); BIO_free(bio); if (!pkey) ossl_raise(ePKeyError, "Could not parse PKey"); return ossl_pkey_new(pkey); }
从 string 或 io 中读取 DER 或 PEM 编码的字符串,并返回适当的 PKey
类的实例。
参数¶ ↑
-
string 是一个包含任意私钥或公钥的 DER 或 PEM 编码的字符串。
-
io 是一个
IO
的实例,其中包含 DER 或 PEM 编码的任意私钥或公钥。 -
pwd 是一个可选密码,以防 string 或 io 是一个加密的 PEM 资源。