class OpenSSL::HMAC
OpenSSL::HMAC 允许计算基于哈希的消息认证码 (HMAC)。它是一种消息认证码 (MAC),结合了哈希函数和密钥。HMAC 可用于验证消息的完整性和真实性。
OpenSSL::HMAC 的接口类似于 OpenSSL::Digest。
使用一次性接口的 HMAC-SHA256¶ ↑
key = "key" data = "message-to-be-authenticated" mac = OpenSSL::HMAC.hexdigest("SHA256", key, data) #=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e"
使用增量接口的 HMAC-SHA256¶ ↑
data1 = File.binread("file1") data2 = File.binread("file2") key = "key" hmac = OpenSSL::HMAC.new(key, 'SHA256') hmac << data1 hmac << data2 mac = hmac.digest
公共类方法
源代码
# File ext/openssl/lib/openssl/hmac.rb, line 73 def base64digest(digest, key, data) [digest(digest, key, data)].pack("m0") end
返回 Base64 编码的字符串形式的认证码。digest 参数指定要使用的摘要算法。它可以是表示算法名称的 String,也可以是 OpenSSL::Digest 的实例。
示例¶ ↑
key = 'key' data = 'The quick brown fox jumps over the lazy dog' hmac = OpenSSL::HMAC.base64digest('SHA1', key, data) #=> "3nybhbi3iqa8ino29wqQcBydtNk="
源代码
# File ext/openssl/lib/openssl/hmac.rb, line 35 def digest(digest, key, data) hmac = new(key, digest) hmac << data hmac.digest end
返回二进制字符串形式的认证码。digest 参数指定要使用的摘要算法。它可以是表示算法名称的 String,也可以是 OpenSSL::Digest 的实例。
示例¶ ↑
key = 'key' data = 'The quick brown fox jumps over the lazy dog' hmac = OpenSSL::HMAC.digest('SHA1', key, data) #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
源代码
# File ext/openssl/lib/openssl/hmac.rb, line 54 def hexdigest(digest, key, data) hmac = new(key, digest) hmac << data hmac.hexdigest end
返回十六进制编码的字符串形式的认证码。digest 参数指定要使用的摘要算法。它可以是表示算法名称的 String,也可以是 OpenSSL::Digest 的实例。
示例¶ ↑
key = 'key' data = 'The quick brown fox jumps over the lazy dog' hmac = OpenSSL::HMAC.hexdigest('SHA1', key, data) #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
源代码
static VALUE
ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
{
EVP_MD_CTX *ctx;
EVP_PKEY *pkey;
GetHMAC(self, ctx);
StringValue(key);
#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
(unsigned char *)RSTRING_PTR(key),
RSTRING_LENINT(key));
if (!pkey)
ossl_raise(eHMACError, "EVP_PKEY_new_raw_private_key");
#else
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
(unsigned char *)RSTRING_PTR(key),
RSTRING_LENINT(key));
if (!pkey)
ossl_raise(eHMACError, "EVP_PKEY_new_mac_key");
#endif
if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest),
NULL, pkey) != 1) {
EVP_PKEY_free(pkey);
ossl_raise(eHMACError, "EVP_DigestSignInit");
}
/* Decrement reference counter; EVP_MD_CTX still keeps it */
EVP_PKEY_free(pkey);
return self;
}
返回一个 OpenSSL::HMAC 的实例,并设置要使用的密钥和摘要算法。该实例表示在处理任何数据之前消息认证码的初始状态。要用它处理数据,请使用实例方法 update,并将您的数据作为参数。
示例¶ ↑
key = 'key' instance = OpenSSL::HMAC.new(key, 'SHA1') #=> f42bb0eeb018ebbd4597ae7213711ec60760843f instance.class #=> OpenSSL::HMAC
关于比较的说明¶ ↑
两个实例可以使用 == 在恒定时间内安全地进行比较
other_instance = OpenSSL::HMAC.new('key', 'SHA1') #=> f42bb0eeb018ebbd4597ae7213711ec60760843f instance == other_instance #=> true
公共实例方法
源代码
# File ext/openssl/lib/openssl/hmac.rb, line 6 def ==(other) return false unless HMAC === other return false unless self.digest.bytesize == other.digest.bytesize OpenSSL.fixed_length_secure_compare(self.digest, other.digest) end
在恒定时间内与另一个 HMAC 实例安全地进行比较。
源代码
# File ext/openssl/lib/openssl/hmac.rb, line 17 def base64digest [digest].pack("m0") end
返回 Base64 编码的字符串形式的认证码。
源代码
static VALUE
ossl_hmac_digest(VALUE self)
{
EVP_MD_CTX *ctx;
size_t buf_len = EVP_MAX_MD_SIZE;
VALUE ret;
GetHMAC(self, ctx);
ret = rb_str_new(NULL, EVP_MAX_MD_SIZE);
if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(ret),
&buf_len) != 1)
ossl_raise(eHMACError, "EVP_DigestSignFinal");
rb_str_set_len(ret, (long)buf_len);
return ret;
}
返回实例表示的二进制字符串形式的认证码。
示例¶ ↑
instance = OpenSSL::HMAC.new('key', 'SHA1') #=> f42bb0eeb018ebbd4597ae7213711ec60760843f instance.digest #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?"
源代码
static VALUE
ossl_hmac_hexdigest(VALUE self)
{
EVP_MD_CTX *ctx;
unsigned char buf[EVP_MAX_MD_SIZE];
size_t buf_len = EVP_MAX_MD_SIZE;
VALUE ret;
GetHMAC(self, ctx);
if (EVP_DigestSignFinal(ctx, buf, &buf_len) != 1)
ossl_raise(eHMACError, "EVP_DigestSignFinal");
ret = rb_str_new(NULL, buf_len * 2);
ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
return ret;
}
返回实例表示的十六进制编码的字符串形式的认证码。
源代码
static VALUE
ossl_hmac_copy(VALUE self, VALUE other)
{
EVP_MD_CTX *ctx1, *ctx2;
rb_check_frozen(self);
if (self == other) return self;
GetHMAC(self, ctx1);
GetHMAC(other, ctx2);
if (EVP_MD_CTX_copy(ctx1, ctx2) != 1)
ossl_raise(eHMACError, "EVP_MD_CTX_copy");
return self;
}
源代码
static VALUE
ossl_hmac_reset(VALUE self)
{
EVP_MD_CTX *ctx;
EVP_PKEY *pkey;
GetHMAC(self, ctx);
pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1)
ossl_raise(eHMACError, "EVP_DigestSignInit");
return self;
}
返回hmac,它与首次初始化时的状态相同,所有已处理的数据都已从中清除。
示例¶ ↑
data = "The quick brown fox jumps over the lazy dog" instance = OpenSSL::HMAC.new('key', 'SHA1') #=> f42bb0eeb018ebbd4597ae7213711ec60760843f instance.update(data) #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 instance.reset #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
源代码
static VALUE
ossl_hmac_update(VALUE self, VALUE data)
{
EVP_MD_CTX *ctx;
StringValue(data);
GetHMAC(self, ctx);
if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
ossl_raise(eHMACError, "EVP_DigestSignUpdate");
return self;
}
返回已使用要认证的消息更新的 hmac。可以重复调用,每次调用使用消息的各个部分。
示例¶ ↑
first_chunk = 'The quick brown fox jumps ' second_chunk = 'over the lazy dog' instance.update(first_chunk) #=> 5b9a8038a65d571076d97fe783989e52278a492a instance.update(second_chunk) #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
也别名为:<<