Feature #10098 » hmac-timing.patch
| ext/openssl/ossl_hmac.c | ||
|---|---|---|
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* hmac.verify(bytes) -> aBoolean
|
||
|
*
|
||
|
* Compares the receiver's digest to another digest in a timing-safe way.
|
||
|
* +bytes+ must be a binary string containing a digest, for example by calling +#digest+ on another
|
||
|
* instance of +OpenSSL::Digest+.
|
||
|
*/
|
||
|
VALUE
|
||
|
ossl_hmac_verify(VALUE self, VALUE other)
|
||
|
{
|
||
|
HMAC_CTX *ctx;
|
||
|
unsigned char *buf;
|
||
|
unsigned int buf_len;
|
||
|
unsigned char result;
|
||
|
unsigned int cur_idx;
|
||
|
unsigned char *other_buf;
|
||
|
if (!RB_TYPE_P(other, T_STRING))
|
||
|
rb_raise(rb_eArgError, "Must supply binary string or instance of OpenSSL::HMAC");
|
||
|
GetHMAC(self, ctx);
|
||
|
hmac_final(ctx, &buf, &buf_len);
|
||
|
if (!buf_len || buf_len != RSTRING_LEN(other))
|
||
|
return Qfalse;
|
||
|
other_buf = (unsigned char *)RSTRING_PTR(other);
|
||
|
result = 0;
|
||
|
for (cur_idx = 0; cur_idx < buf_len; cur_idx++) {
|
||
|
result |= buf[cur_idx] ^ other_buf[cur_idx];
|
||
|
}
|
||
|
if (result == 0)
|
||
|
return Qtrue;
|
||
|
return Qfalse;
|
||
|
}
|
||
|
/*
|
||
|
* INIT
|
||
|
*/
|
||
|
void
|
||
| ... | ... | |
|
rb_define_method(cHMAC, "hexdigest", ossl_hmac_hexdigest, 0);
|
||
|
rb_define_alias(cHMAC, "inspect", "hexdigest");
|
||
|
rb_define_alias(cHMAC, "to_s", "hexdigest");
|
||
|
rb_define_method(cHMAC, "verify", ossl_hmac_verify, 1);
|
||
|
}
|
||
|
#else /* NO_HMAC */
|
||
| test/openssl/test_hmac.rb | ||
|---|---|---|
|
assert_equal(OpenSSL::HMAC.digest("MD5", @key, @data), @h2.digest, "digest")
|
||
|
assert_equal(OpenSSL::HMAC.hexdigest("MD5", @key, @data), @h2.hexdigest, "hexdigest")
|
||
|
assert_same(false, @h1.verify("\x9EPYl\x0F\xA1\x19\x7F\x85\x87D:\x94-\x8A\xFD"))
|
||
|
assert_same(true, @h1.verify("\x9EPYl\x0F\xA1\x19\x7F\x85\x87D:\x94-\x8A\xFC"))
|
||
|
end
|
||
|
def test_hmac_verify
|
||
|
end
|
||
|
def test_dup
|
||