OpenSSL::Digest
类 OpenSSL :: Digest
家长:OpenSSL的::摘要::类 (Parent:OpenSSL::Digest::Class)
OpenSSL :: Digest 允许您计算加密安全的任意数据的消息摘要(有时可互换地称为“散列”),即 Digest 实现安全的单向函数。
单向函数提供了一些有用的属性。例如,给定两个不同的输入,产生相同输出的概率极不可能。结合每个消息摘要算法具有只有几个字节的固定长度输出这一事实,摘要通常用于为任意数据创建唯一标识符。一个常见的例子是为存储在数据库中的二进制文档创建唯一的 ID。
单向函数(以及名称)的另一个有用特征是给定摘要没有关于产生它的原始数据的指示,即识别原始输入的唯一方法是在每一个可能的情况下“蛮力”输入组合。
这些特征使得单向函数也是公钥签名算法的理想伴侣:不是签署整个文档,首先使用相当快的消息摘要算法生成文档的哈希,并且只需输出它的输出的几个字节使用较慢的公钥算法。要验证已签名文档的完整性,只需重新计算散列并验证其与签名中的散列值相等即可。
支持的消息摘要算法包括:
- SHA, SHA1, SHA224, SHA256, SHA384 and SHA512
- MD2, MD4, MDC2 and MD5
- RIPEMD160
- DSS,DSS1(用于 DSA 签名的伪算法,DSS 等于 SHA,DSS1 等于 SHA1)
对于这些算法中的每一个,都有一个 Digest 的子类,可以像例如那样简单地实例化
digest = OpenSSL::Digest::SHA1.new
Digest 类和 sn / ln 之间的映射
sn(短名称)和ln(长名称)在<openssl / object.h>和<openssl / obj_mac.h>中定义。它们是 ASN.1 OBJECT IDENTIFIER 的文本表示。每个受支持的摘要算法都有一个与之关联的 OBJECT IDENTIFIER,并且这些算法又分配了短/长名称。例如,SHA-1 的 OBJECT IDENTIFIER 是1.3.14.3.2.26,其 sn 是“SHA1”,其 ln 是“sha1”。
MD2
- sn: MD2
- ln: md2
MD4
- sn: MD4
- ln: md4
MD5
- sn: MD5
- ln: md5
SHA
- sn: SHA
- ln: SHA
SHA-1
- sn: SHA1
- ln: sha1
SHA-224
- sn: SHA224
- ln: sha224
SHA-256
- sn: SHA256
- ln: sha256
SHA-384
- sn: SHA384
- ln: sha384
SHA-512
- sn: SHA512
- ln: sha512
“打破”消息摘要算法意味着藐视其单向函数特性,即产生冲突或找到一种通过比强迫等效率更高的方式获得原始数据的方法等。大多数支持的摘要算法可以是在这个意义上被认为是破碎的,甚至是非常流行的 MD5 和 SHA1 算法。如果安全是您最关心的问题,那么您应该可以依靠 SHA224,SHA256,SHA384 或 SHA512。
散列文件
data = File.read('document')
sha256 = OpenSSL::Digest::SHA256.new
digest = sha256.digest(data)
一次散列几条数据
data1 = File.read('file1')
data2 = File.read('file2')
data3 = File.read('file3')
sha256 = OpenSSL::Digest::SHA256.new
sha256 << data1
sha256 << data2
sha256 << data3
digest = sha256.digest
重用摘要实例
data1 = File.read('file1')
sha256 = OpenSSL::Digest::SHA256.new
digest1 = sha256.digest(data1)
data2 = File.read('file2')
sha256.reset
digest2 = sha256.digest(data2)
公共类方法
摘要(名称,数据)显示源
返回data
使用name
摘要计算的散列值。name
是受支持的摘要算法的长名称或短名称。
示例
OpenSSL::Digest.digest("SHA256", "abc")
相当于:
OpenSSL::Digest::SHA256.digest("abc")
调用超类方法
# File ext/openssl/lib/openssl/digest.rb, line 36
def self.digest(name, data)
super(data, name)
end
新(字符串,数据) new(string , data)→摘要显示源
根据string
受支持的摘要算法的 ln(长名称)或 sn(短名称)创建摘要实例。
如果data
(一个 String
)被给出,则它被用作摘要实例的初始输入,即,
digest = OpenSSL::Digest.new('sha256', 'digestdata')
等于
digest = OpenSSL::Digest.new('sha256')
digest.update('digestdata')
static VALUE
ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_MD_CTX *ctx;
const EVP_MD *md;
VALUE type, data;
rb_scan_args(argc, argv, "11", &type, &data
md = GetDigestPtr(type
if (!NIL_P(data)) StringValue(data
TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx
if (!ctx) {
RTYPEDDATA_DATA(self) = ctx = EVP_MD_CTX_new(
if (!ctx)
ossl_raise(eDigestError, "EVP_MD_CTX_new"
}
if (!EVP_DigestInit_ex(ctx, md, NULL))
ossl_raise(eDigestError, "Digest initialization failed"
if (!NIL_P(data)) return ossl_digest_update(self, data
return self;
}
公共实例方法
<<(p1)
别名为:更新
block_length→整数显示源
返回摘要算法的块长度,即单个块的字节长度。大多数现代算法将消息分割成一系列连续处理的固定大小的块。
示例
digest = OpenSSL::Digest::SHA1.new
puts digest.block_length # => 64
static VALUE
ossl_digest_block_length(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx
return INT2NUM(EVP_MD_CTX_block_size(ctx)
}
digest_length→整数显示源文件
返回摘要的输出大小,即最终消息摘要结果的字节长度。
Example
digest = OpenSSL::Digest::SHA1.new
puts digest.digest_length # => 20
static VALUE
ossl_digest_size(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx
return INT2NUM(EVP_MD_CTX_size(ctx)
}
名称 name →字符串显示源
返回此摘要算法的 sn。
示例
digest = OpenSSL::Digest::SHA512.new
puts digest.name # => SHA512
static VALUE
ossl_digest_name(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx
return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx))
}
重置 reset → self显示来源
重置摘要的意思是任何已执行的 #update 被放弃,并且摘要被重新设置为其初始状态。
static VALUE
ossl_digest_reset(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx
if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL) != 1) {
ossl_raise(eDigestError, "Digest initialization failed."
}
return self;
}
更新(字符串)update(string) →aString 显示源
并非每个消息摘要都可以在一次传递中计算。如果要从多个后续源计算消息摘要,则每个消息摘要可以单独传递到摘要实例。
示例
digest = OpenSSL::Digest::SHA256.new
digest.update('First input')
digest << 'Second input' # equivalent to digest.update('Second input')
result = digest.digest
VALUE
ossl_digest_update(VALUE self, VALUE data)
{
EVP_MD_CTX *ctx;
StringValue(data
GetDigest(self, ctx
if (!EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)))
ossl_raise(eDigestError, "EVP_DigestUpdate"
return self;
}
另外别名为:<<
私有实例方法
完成→aString 显示源
static VALUE
ossl_digest_finish(int argc, VALUE *argv, VALUE self)
{
EVP_MD_CTX *ctx;
VALUE str;
int out_len;
GetDigest(self, ctx
rb_scan_args(argc, argv, "01", &str
out_len = EVP_MD_CTX_size(ctx
if (NIL_P(str)) {
str = rb_str_new(NULL, out_len
} else {
StringValue(str
rb_str_resize(str, out_len
}
if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL))
ossl_raise(eDigestError, "EVP_DigestFinal_ex"
return str;
}