mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[ruby/openssl] pkey: port PKey::PKey#sign and #verify to the EVP_Digest* interface
Use EVP_DigestSign*() and EVP_DigestVerify*() interface instead of the
old EVP_Sign*() and EVP_Verify*() functions. They were added in OpenSSL
1.0.0.
Also, allow the digest to be specified as nil, as certain EVP_PKEY types
don't expect a digest algorithm.
9ff6e5143b
This commit is contained in:
parent
1e3590fe22
commit
5cae289682
Notes:
git
2021-03-16 20:38:52 +09:00
2 changed files with 63 additions and 39 deletions
|
@ -753,35 +753,47 @@ static VALUE
|
||||||
ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
|
ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
|
||||||
{
|
{
|
||||||
EVP_PKEY *pkey;
|
EVP_PKEY *pkey;
|
||||||
const EVP_MD *md;
|
const EVP_MD *md = NULL;
|
||||||
EVP_MD_CTX *ctx;
|
EVP_MD_CTX *ctx;
|
||||||
unsigned int buf_len;
|
size_t siglen;
|
||||||
VALUE str;
|
int state;
|
||||||
int result;
|
VALUE sig;
|
||||||
|
|
||||||
pkey = GetPrivPKeyPtr(self);
|
pkey = GetPrivPKeyPtr(self);
|
||||||
|
if (!NIL_P(digest))
|
||||||
md = ossl_evp_get_digestbyname(digest);
|
md = ossl_evp_get_digestbyname(digest);
|
||||||
StringValue(data);
|
StringValue(data);
|
||||||
str = rb_str_new(0, EVP_PKEY_size(pkey));
|
|
||||||
|
|
||||||
ctx = EVP_MD_CTX_new();
|
ctx = EVP_MD_CTX_new();
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
|
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
|
||||||
if (!EVP_SignInit_ex(ctx, md, NULL)) {
|
if (EVP_DigestSignInit(ctx, NULL, md, /* engine */NULL, pkey) < 1) {
|
||||||
EVP_MD_CTX_free(ctx);
|
EVP_MD_CTX_free(ctx);
|
||||||
ossl_raise(ePKeyError, "EVP_SignInit_ex");
|
ossl_raise(ePKeyError, "EVP_DigestSignInit");
|
||||||
}
|
}
|
||||||
if (!EVP_SignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
|
if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) {
|
||||||
EVP_MD_CTX_free(ctx);
|
EVP_MD_CTX_free(ctx);
|
||||||
ossl_raise(ePKeyError, "EVP_SignUpdate");
|
ossl_raise(ePKeyError, "EVP_DigestSignUpdate");
|
||||||
}
|
}
|
||||||
result = EVP_SignFinal(ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey);
|
if (EVP_DigestSignFinal(ctx, NULL, &siglen) < 1) {
|
||||||
EVP_MD_CTX_free(ctx);
|
EVP_MD_CTX_free(ctx);
|
||||||
if (!result)
|
ossl_raise(ePKeyError, "EVP_DigestSignFinal");
|
||||||
ossl_raise(ePKeyError, "EVP_SignFinal");
|
}
|
||||||
rb_str_set_len(str, buf_len);
|
if (siglen > LONG_MAX)
|
||||||
|
rb_raise(ePKeyError, "signature would be too large");
|
||||||
return str;
|
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");
|
||||||
|
}
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
rb_str_set_len(sig, siglen);
|
||||||
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -809,38 +821,38 @@ static VALUE
|
||||||
ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
|
ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
|
||||||
{
|
{
|
||||||
EVP_PKEY *pkey;
|
EVP_PKEY *pkey;
|
||||||
const EVP_MD *md;
|
const EVP_MD *md = NULL;
|
||||||
EVP_MD_CTX *ctx;
|
EVP_MD_CTX *ctx;
|
||||||
int siglen, result;
|
int ret;
|
||||||
|
|
||||||
GetPKey(self, pkey);
|
GetPKey(self, pkey);
|
||||||
ossl_pkey_check_public_key(pkey);
|
ossl_pkey_check_public_key(pkey);
|
||||||
|
if (!NIL_P(digest))
|
||||||
md = ossl_evp_get_digestbyname(digest);
|
md = ossl_evp_get_digestbyname(digest);
|
||||||
StringValue(sig);
|
StringValue(sig);
|
||||||
siglen = RSTRING_LENINT(sig);
|
|
||||||
StringValue(data);
|
StringValue(data);
|
||||||
|
|
||||||
ctx = EVP_MD_CTX_new();
|
ctx = EVP_MD_CTX_new();
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
|
ossl_raise(ePKeyError, "EVP_MD_CTX_new");
|
||||||
if (!EVP_VerifyInit_ex(ctx, md, NULL)) {
|
if (EVP_DigestVerifyInit(ctx, NULL, md, /* engine */NULL, pkey) < 1) {
|
||||||
EVP_MD_CTX_free(ctx);
|
EVP_MD_CTX_free(ctx);
|
||||||
ossl_raise(ePKeyError, "EVP_VerifyInit_ex");
|
ossl_raise(ePKeyError, "EVP_DigestVerifyInit");
|
||||||
}
|
}
|
||||||
if (!EVP_VerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
|
if (EVP_DigestVerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) {
|
||||||
EVP_MD_CTX_free(ctx);
|
EVP_MD_CTX_free(ctx);
|
||||||
ossl_raise(ePKeyError, "EVP_VerifyUpdate");
|
ossl_raise(ePKeyError, "EVP_DigestVerifyUpdate");
|
||||||
}
|
}
|
||||||
result = EVP_VerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), siglen, pkey);
|
ret = EVP_DigestVerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig),
|
||||||
|
RSTRING_LEN(sig));
|
||||||
EVP_MD_CTX_free(ctx);
|
EVP_MD_CTX_free(ctx);
|
||||||
switch (result) {
|
if (ret < 0)
|
||||||
case 0:
|
ossl_raise(ePKeyError, "EVP_DigestVerifyFinal");
|
||||||
|
if (ret)
|
||||||
|
return Qtrue;
|
||||||
|
else {
|
||||||
ossl_clear_error();
|
ossl_clear_error();
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
case 1:
|
|
||||||
return Qtrue;
|
|
||||||
default:
|
|
||||||
ossl_raise(ePKeyError, "EVP_VerifyFinal");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,4 +68,16 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
|
||||||
assert_equal 512, pkey.p.num_bits
|
assert_equal 512, pkey.p.num_bits
|
||||||
assert_not_equal nil, pkey.priv_key
|
assert_not_equal nil, pkey.priv_key
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_hmac_sign_verify
|
||||||
|
pkey = OpenSSL::PKey.generate_key("HMAC", { "key" => "abcd" })
|
||||||
|
|
||||||
|
hmac = OpenSSL::HMAC.new("abcd", "SHA256").update("data").digest
|
||||||
|
assert_equal hmac, pkey.sign("SHA256", "data")
|
||||||
|
|
||||||
|
# EVP_PKEY_HMAC does not support verify
|
||||||
|
assert_raise(OpenSSL::PKey::PKeyError) {
|
||||||
|
pkey.verify("SHA256", "data", hmac)
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue