首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

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 的子类,可以像例如那样简单地实例化

代码语言:javascript
复制
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。

散列文件

代码语言:javascript
复制
data = File.read('document')
sha256 = OpenSSL::Digest::SHA256.new
digest = sha256.digest(data)

一次散列几条数据

代码语言:javascript
复制
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

重用摘要实例

代码语言:javascript
复制
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是受支持的摘要算法的长名称或短名称。

示例

代码语言:javascript
复制
OpenSSL::Digest.digest("SHA256", "abc")

相当于:

代码语言:javascript
复制
OpenSSL::Digest::SHA256.digest("abc")

调用超类方法

代码语言:javascript
复制
# 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)被给出,则它被用作摘要实例的初始输入,即,

代码语言:javascript
复制
digest = OpenSSL::Digest.new('sha256', 'digestdata')

等于

代码语言:javascript
复制
digest = OpenSSL::Digest.new('sha256')
digest.update('digestdata')
代码语言:javascript
复制
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→整数显示源

返回摘要算法的块长度,即单个块的字节长度。大多数现代算法将消息分割成一系列连续处理的固定大小的块。

示例

代码语言:javascript
复制
digest = OpenSSL::Digest::SHA1.new
puts digest.block_length # => 64
代码语言:javascript
复制
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

代码语言:javascript
复制
digest = OpenSSL::Digest::SHA1.new
puts digest.digest_length # => 20
代码语言:javascript
复制
static VALUE
ossl_digest_size(VALUE self)
{
    EVP_MD_CTX *ctx;

    GetDigest(self, ctx);

    return INT2NUM(EVP_MD_CTX_size(ctx));
}

名称 name →字符串显示源

返回此摘要算法的 sn。

示例

代码语言:javascript
复制
digest = OpenSSL::Digest::SHA512.new
puts digest.name # => SHA512
代码语言:javascript
复制
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 被放弃,并且摘要被重新设置为其初始状态。

代码语言:javascript
复制
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 显示源

并非每个消息摘要都可以在一次传递中计算。如果要从多个后续源计算消息摘要,则每个消息摘要可以单独传递到摘要实例。

示例

代码语言:javascript
复制
digest = OpenSSL::Digest::SHA256.new
digest.update('First input')
digest << 'Second input' # equivalent to digest.update('Second input')
result = digest.digest
代码语言:javascript
复制
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 显示源

代码语言:javascript
复制
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;
}

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com