class OpenSSL::PKey::PKey
一个抽象类,捆绑了签名创建(PKey#sign)和验证(PKey#verify),这些是除了 OpenSSL::PKey::DH 之外所有实现都通用的。
公共类方法
源代码
static VALUE
ossl_pkey_initialize(VALUE self)
{
if (rb_obj_is_instance_of(self, cPKey)) {
ossl_raise(rb_eTypeError, "OpenSSL::PKey::PKey can't be instantiated directly");
}
return self;
}
因为 PKey 是一个抽象类,实际显式调用此方法将引发 NotImplementedError。
公共实例方法
源代码
static VALUE
ossl_pkey_compare(VALUE self, VALUE other)
{
int ret;
EVP_PKEY *selfPKey;
EVP_PKEY *otherPKey;
GetPKey(self, selfPKey);
GetPKey(other, otherPKey);
/* Explicitly check the key type given EVP_PKEY_ASN1_METHOD(3)
* docs param_cmp could return any negative number.
*/
if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey))
ossl_raise(rb_eTypeError, "cannot match different PKey types");
ret = EVP_PKEY_eq(selfPKey, otherPKey);
if (ret == 0)
return Qfalse;
else if (ret == 1)
return Qtrue;
else
ossl_raise(ePKeyError, "EVP_PKEY_eq");
}
主要用于检查 OpenSSL::X509::Certificate#public_key 是否与其私钥匹配。
示例¶ ↑
x509 = OpenSSL::X509::Certificate.new(pem_encoded_certificate) rsa_key = OpenSSL::PKey::RSA.new(pem_encoded_private_key) rsa_key.compare?(x509.public_key) => true | false
源代码
static VALUE
ossl_pkey_decrypt(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
EVP_PKEY_CTX *ctx;
VALUE data, options, str;
size_t outlen;
int state;
GetPKey(self, pkey);
rb_scan_args(argc, argv, "11", &data, &options);
StringValue(data);
ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!ctx)
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
if (EVP_PKEY_decrypt_init(ctx) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_decrypt_init");
}
if (!NIL_P(options)) {
pkey_ctx_apply_options(ctx, options, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
}
if (EVP_PKEY_decrypt(ctx, NULL, &outlen,
(unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_decrypt");
}
if (outlen > LONG_MAX) {
EVP_PKEY_CTX_free(ctx);
rb_raise(ePKeyError, "decrypted data would be too large");
}
str = ossl_str_new(NULL, (long)outlen, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
if (EVP_PKEY_decrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen,
(unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_decrypt");
}
EVP_PKEY_CTX_free(ctx);
rb_str_set_len(str, outlen);
return str;
}
使用 pkey 执行公钥解密操作。
有关参数的描述和示例,请参见 encrypt。
在版本 3.0 中添加。另请参见手册页 EVP_PKEY_decrypt(3)。
源代码
static VALUE
ossl_pkey_derive(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey, *peer_pkey;
EVP_PKEY_CTX *ctx;
VALUE peer_pkey_obj, str;
size_t keylen;
int state;
GetPKey(self, pkey);
rb_scan_args(argc, argv, "1", &peer_pkey_obj);
GetPKey(peer_pkey_obj, peer_pkey);
ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!ctx)
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
if (EVP_PKEY_derive_init(ctx) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_derive_init");
}
if (EVP_PKEY_derive_set_peer(ctx, peer_pkey) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_derive_set_peer");
}
if (EVP_PKEY_derive(ctx, NULL, &keylen) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_derive");
}
if (keylen > LONG_MAX)
rb_raise(ePKeyError, "derived key would be too large");
str = ossl_str_new(NULL, (long)keylen, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
if (EVP_PKEY_derive(ctx, (unsigned char *)RSTRING_PTR(str), &keylen) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_derive");
}
EVP_PKEY_CTX_free(ctx);
rb_str_set_len(str, keylen);
return str;
}
从 pkey 和 peer_pkey 派生共享密钥。pkey 必须包含私有组件,peer_pkey 必须包含公共组件。
源代码
static VALUE
ossl_pkey_encrypt(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
EVP_PKEY_CTX *ctx;
VALUE data, options, str;
size_t outlen;
int state;
GetPKey(self, pkey);
rb_scan_args(argc, argv, "11", &data, &options);
StringValue(data);
ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!ctx)
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
if (EVP_PKEY_encrypt_init(ctx) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_encrypt_init");
}
if (!NIL_P(options)) {
pkey_ctx_apply_options(ctx, options, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
}
if (EVP_PKEY_encrypt(ctx, NULL, &outlen,
(unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_encrypt");
}
if (outlen > LONG_MAX) {
EVP_PKEY_CTX_free(ctx);
rb_raise(ePKeyError, "encrypted data would be too large");
}
str = ossl_str_new(NULL, (long)outlen, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
if (EVP_PKEY_encrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen,
(unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_encrypt");
}
EVP_PKEY_CTX_free(ctx);
rb_str_set_len(str, outlen);
return str;
}
使用 pkey 执行公钥加密操作。
有关反向操作,请参见 decrypt。
在版本 3.0 中添加。另请参见手册页 EVP_PKEY_encrypt(3)。
data-
要加密的
String。 options-
包含特定于算法的控制操作以传递给 OpenSSL 的
Hash。有关详细信息,请参见 OpenSSL 手册页 EVP_PKEY_CTX_ctrl_str(3)。
示例
pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) data = "secret data" encrypted = pkey.encrypt(data, rsa_padding_mode: "oaep") decrypted = pkey.decrypt(data, rsa_padding_mode: "oaep") p decrypted #=> "secret data"
源代码
HAVE_EVP_PKEY_DUP
static VALUE
ossl_pkey_initialize_copy(VALUE self, VALUE other)
{
EVP_PKEY *pkey, *pkey_other;
TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
TypedData_Get_Struct(other, EVP_PKEY, &ossl_evp_pkey_type, pkey_other);
if (pkey)
rb_raise(rb_eTypeError, "pkey already initialized");
if (pkey_other) {
pkey = EVP_PKEY_dup(pkey_other);
if (!pkey)
ossl_raise(ePKeyError, "EVP_PKEY_dup");
RTYPEDDATA_DATA(self) = pkey;
}
return self;
}
源代码
static VALUE
ossl_pkey_inspect(VALUE self)
{
EVP_PKEY *pkey;
int nid;
GetPKey(self, pkey);
nid = EVP_PKEY_id(pkey);
return rb_sprintf("#<%"PRIsVALUE":%p oid=%s>",
rb_class_name(CLASS_OF(self)), (void *)self,
OBJ_nid2sn(nid));
}
返回描述 PKey 对象的字符串。
源代码
static VALUE
ossl_pkey_oid(VALUE self)
{
EVP_PKEY *pkey;
int nid;
GetPKey(self, pkey);
nid = EVP_PKEY_id(pkey);
return rb_str_new_cstr(OBJ_nid2sn(nid));
}
返回与 pkey 关联的 OID 的短名称。
源代码
static VALUE
ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self)
{
return do_pkcs8_export(argc, argv, self, 1);
}
将私钥序列化为 DER 编码的 PKCS #8 格式。如果调用时不带参数,则使用未加密的 PKCS #8 PrivateKeyInfo 格式。如果使用密码名称和密码调用,则使用带有 PBES2 加密方案的 PKCS #8 EncryptedPrivateKeyInfo 格式。
源代码
static VALUE
ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
{
return do_pkcs8_export(argc, argv, self, 0);
}
将私钥序列化为 PEM 编码的 PKCS #8 格式。有关更多详细信息,请参见 private_to_der。
未加密的 PEM 编码密钥如下所示
-----BEGIN PRIVATE KEY----- [...] -----END PRIVATE KEY-----
加密的 PEM 编码密钥如下所示
-----BEGIN ENCRYPTED PRIVATE KEY----- [...] -----END ENCRYPTED PRIVATE KEY-----
源代码
static VALUE
ossl_pkey_public_to_der(VALUE self)
{
return ossl_pkey_export_spki(self, 1);
}
将公钥序列化为 DER 编码的 X.509 SubjectPublicKeyInfo 格式。
源代码
static VALUE
ossl_pkey_public_to_pem(VALUE self)
{
return ossl_pkey_export_spki(self, 0);
}
将公钥序列化为 PEM 编码的 X.509 SubjectPublicKeyInfo 格式。
PEM 编码的密钥如下所示
-----BEGIN PUBLIC KEY----- [...] -----END PUBLIC KEY-----
源代码
static VALUE
ossl_pkey_raw_private_key(VALUE self)
{
EVP_PKEY *pkey;
VALUE str;
size_t len;
GetPKey(self, pkey);
if (EVP_PKEY_get_raw_private_key(pkey, NULL, &len) != 1)
ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key");
str = rb_str_new(NULL, len);
if (EVP_PKEY_get_raw_private_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key");
rb_str_set_len(str, len);
return str;
}
有关 EVP_PKEY_get_raw_private_key() 的信息,请参见 OpenSSL 文档
源代码
static VALUE
ossl_pkey_raw_public_key(VALUE self)
{
EVP_PKEY *pkey;
VALUE str;
size_t len;
GetPKey(self, pkey);
if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1)
ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key");
str = rb_str_new(NULL, len);
if (EVP_PKEY_get_raw_public_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key");
rb_str_set_len(str, len);
return str;
}
有关 EVP_PKEY_get_raw_public_key() 的信息,请参见 OpenSSL 文档
源代码
static VALUE
ossl_pkey_sign(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
VALUE digest, data, options, sig;
const EVP_MD *md = NULL;
EVP_MD_CTX *ctx;
EVP_PKEY_CTX *pctx;
size_t siglen;
int state;
pkey = GetPrivPKeyPtr(self);
rb_scan_args(argc, argv, "21", &digest, &data, &options);
if (!NIL_P(digest))
md = ossl_evp_get_digestbyname(digest);
StringValue(data);
ctx = EVP_MD_CTX_new();
if (!ctx)
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
if (EVP_DigestSignInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_DigestSignInit");
}
if (!NIL_P(options)) {
pkey_ctx_apply_options(pctx, options, &state);
if (state) {
EVP_MD_CTX_free(ctx);
rb_jump_tag(state);
}
}
#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0)
if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) < 1) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_DigestSign");
}
if (siglen > LONG_MAX) {
EVP_MD_CTX_free(ctx);
rb_raise(ePKeyError, "signature would be too large");
}
sig = ossl_str_new(NULL, (long)siglen, &state);
if (state) {
EVP_MD_CTX_free(ctx);
rb_jump_tag(state);
}
if (EVP_DigestSign(ctx, (unsigned char *)RSTRING_PTR(sig), &siglen,
(unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) < 1) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_DigestSign");
}
#else
if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_DigestSignUpdate");
}
if (EVP_DigestSignFinal(ctx, NULL, &siglen) < 1) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_DigestSignFinal");
}
if (siglen > LONG_MAX) {
EVP_MD_CTX_free(ctx);
rb_raise(ePKeyError, "signature would be too large");
}
sig = ossl_str_new(NULL, (long)siglen, &state);
if (state) {
EVP_MD_CTX_free(ctx);
rb_jump_tag(state);
}
if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(sig),
&siglen) < 1) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_DigestSignFinal");
}
#endif
EVP_MD_CTX_free(ctx);
rb_str_set_len(sig, siglen);
return sig;
}
使用消息摘要算法 digest 和私钥 pkey 对 data 进行哈希和签名。
有关验证操作,请参见 verify。
另请参见手册页 EVP_DigestSign(3)。
digest-
表示消息摘要算法名称的
String,如果PKey类型不需要摘要算法,则为nil。为了向后兼容,它可以是OpenSSL::Digest的实例。其状态不会影响签名。 data-
一个
String。要进行哈希和签名的数据。 options-
包含特定于算法的控制操作以传递给 OpenSSL 的
Hash。有关详细信息,请参见 OpenSSL 手册页 EVP_PKEY_CTX_ctrl_str(3)。options参数在版本 3.0 中添加。
示例
data = "Sign me!" pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) signopts = { rsa_padding_mode: "pss" } signature = pkey.sign("SHA256", data, signopts) # Creates a copy of the RSA key pkey, but without the private components pub_key = pkey.public_key puts pub_key.verify("SHA256", signature, data, signopts) # => true
源代码
static VALUE
ossl_pkey_sign_raw(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
VALUE digest, data, options, sig;
const EVP_MD *md = NULL;
EVP_PKEY_CTX *ctx;
size_t outlen;
int state;
GetPKey(self, pkey);
rb_scan_args(argc, argv, "21", &digest, &data, &options);
if (!NIL_P(digest))
md = ossl_evp_get_digestbyname(digest);
StringValue(data);
ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!ctx)
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
if (EVP_PKEY_sign_init(ctx) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_sign_init");
}
if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
}
if (!NIL_P(options)) {
pkey_ctx_apply_options(ctx, options, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
}
if (EVP_PKEY_sign(ctx, NULL, &outlen, (unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_sign");
}
if (outlen > LONG_MAX) {
EVP_PKEY_CTX_free(ctx);
rb_raise(ePKeyError, "signature would be too large");
}
sig = ossl_str_new(NULL, (long)outlen, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
if (EVP_PKEY_sign(ctx, (unsigned char *)RSTRING_PTR(sig), &outlen,
(unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_sign");
}
EVP_PKEY_CTX_free(ctx);
rb_str_set_len(sig, outlen);
return sig;
}
使用私钥 pkey 对 data 进行签名。与 sign 不同,data 不会自动被 digest 哈希处理。
有关验证操作,请参见 verify_raw。
在版本 3.0 中添加。另请参见手册页 EVP_PKEY_sign(3)。
digest-
表示消息摘要算法名称的
String,如果PKey类型不需要摘要算法,则为nil。虽然此方法不会使用它对data进行哈希处理,但根据签名算法,可能仍然需要此参数。 data-
一个
String。要签名的数据。 options-
包含特定于算法的控制操作以传递给 OpenSSL 的
Hash。有关详细信息,请参见 OpenSSL 手册页 EVP_PKEY_CTX_ctrl_str(3)。
示例
data = "Sign me!" hash = OpenSSL::Digest.digest("SHA256", data) pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048) signopts = { rsa_padding_mode: "pss" } signature = pkey.sign_raw("SHA256", hash, signopts) # Creates a copy of the RSA key pkey, but without the private components pub_key = pkey.public_key puts pub_key.verify_raw("SHA256", signature, hash, signopts) # => true
源代码
static VALUE
ossl_pkey_to_text(VALUE self)
{
EVP_PKEY *pkey;
BIO *bio;
GetPKey(self, pkey);
if (!(bio = BIO_new(BIO_s_mem())))
ossl_raise(ePKeyError, "BIO_new");
if (EVP_PKEY_print_private(bio, pkey, 0, NULL) == 1)
goto out;
OSSL_BIO_reset(bio);
if (EVP_PKEY_print_public(bio, pkey, 0, NULL) == 1)
goto out;
OSSL_BIO_reset(bio);
if (EVP_PKEY_print_params(bio, pkey, 0, NULL) == 1)
goto out;
BIO_free(bio);
ossl_raise(ePKeyError, "EVP_PKEY_print_params");
out:
return ossl_membio2str(bio);
}
将密钥中包含的密钥参数、公钥和私钥组件转储为人类可读的文本。
这旨在用于调试目的。
另请参见手册页 EVP_PKEY_print_private(3)。
源代码
static VALUE
ossl_pkey_verify(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
VALUE digest, sig, data, options;
const EVP_MD *md = NULL;
EVP_MD_CTX *ctx;
EVP_PKEY_CTX *pctx;
int state, ret;
GetPKey(self, pkey);
rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options);
ossl_pkey_check_public_key(pkey);
if (!NIL_P(digest))
md = ossl_evp_get_digestbyname(digest);
StringValue(sig);
StringValue(data);
ctx = EVP_MD_CTX_new();
if (!ctx)
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
if (EVP_DigestVerifyInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_DigestVerifyInit");
}
if (!NIL_P(options)) {
pkey_ctx_apply_options(pctx, options, &state);
if (state) {
EVP_MD_CTX_free(ctx);
rb_jump_tag(state);
}
}
#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0)
ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig),
RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data));
EVP_MD_CTX_free(ctx);
if (ret < 0)
ossl_raise(ePKeyError, "EVP_DigestVerify");
#else
if (EVP_DigestVerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) {
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_DigestVerifyUpdate");
}
ret = EVP_DigestVerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig),
RSTRING_LEN(sig));
EVP_MD_CTX_free(ctx);
if (ret < 0)
ossl_raise(ePKeyError, "EVP_DigestVerifyFinal");
#endif
if (ret)
return Qtrue;
else {
ossl_clear_error();
return Qfalse;
}
}
使用消息摘要算法 digest 和公钥 pkey 验证 data 的 signature。
如果成功验证了签名,则返回 true,否则返回 false。调用者必须检查返回值。
有关签名操作和示例,请参见 sign。
另请参见手册页 EVP_DigestVerify(3)。
源代码
static VALUE
ossl_pkey_verify_raw(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
VALUE digest, sig, data, options;
const EVP_MD *md = NULL;
EVP_PKEY_CTX *ctx;
int state, ret;
GetPKey(self, pkey);
rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options);
ossl_pkey_check_public_key(pkey);
if (!NIL_P(digest))
md = ossl_evp_get_digestbyname(digest);
StringValue(sig);
StringValue(data);
ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!ctx)
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
if (EVP_PKEY_verify_init(ctx) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_verify_init");
}
if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
}
if (!NIL_P(options)) {
pkey_ctx_apply_options(ctx, options, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
}
ret = EVP_PKEY_verify(ctx, (unsigned char *)RSTRING_PTR(sig),
RSTRING_LEN(sig),
(unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data));
EVP_PKEY_CTX_free(ctx);
if (ret < 0)
ossl_raise(ePKeyError, "EVP_PKEY_verify");
if (ret)
return Qtrue;
else {
ossl_clear_error();
return Qfalse;
}
}
使用公钥 pkey 验证 data 的 signature。与 verify 不同,此方法不会自动使用 digest 对 data 进行哈希处理。
如果成功验证了签名,则返回 true,否则返回 false。调用者必须检查返回值。
有关签名操作和示例代码,请参见 sign_raw。
在版本 3.0 中添加。另请参见手册页 EVP_PKEY_verify(3)。
signature-
包含要验证的签名的
String。
源代码
static VALUE
ossl_pkey_verify_recover(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
VALUE digest, sig, options, out;
const EVP_MD *md = NULL;
EVP_PKEY_CTX *ctx;
int state;
size_t outlen;
GetPKey(self, pkey);
rb_scan_args(argc, argv, "21", &digest, &sig, &options);
ossl_pkey_check_public_key(pkey);
if (!NIL_P(digest))
md = ossl_evp_get_digestbyname(digest);
StringValue(sig);
ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!ctx)
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
if (EVP_PKEY_verify_recover_init(ctx) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_verify_recover_init");
}
if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
}
if (!NIL_P(options)) {
pkey_ctx_apply_options(ctx, options, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
}
if (EVP_PKEY_verify_recover(ctx, NULL, &outlen,
(unsigned char *)RSTRING_PTR(sig),
RSTRING_LEN(sig)) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_verify_recover");
}
out = ossl_str_new(NULL, (long)outlen, &state);
if (state) {
EVP_PKEY_CTX_free(ctx);
rb_jump_tag(state);
}
if (EVP_PKEY_verify_recover(ctx, (unsigned char *)RSTRING_PTR(out), &outlen,
(unsigned char *)RSTRING_PTR(sig),
RSTRING_LEN(sig)) <= 0) {
EVP_PKEY_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_PKEY_verify_recover");
}
EVP_PKEY_CTX_free(ctx);
rb_str_set_len(out, outlen);
return out;
}
使用公钥 pkey 从 signature 恢复已签名的数据。并非所有签名算法都支持此操作。
在版本 3.0 中添加。另请参见手册页 EVP_PKEY_verify_recover(3)。
signature-
包含要验证的签名的
String。