Spec-Zone.ru › Ruby 3.1

класс OpenSSL::Digest

Родитель:
OpenSSL::Digest::Class

OpenSSL::Digest позволяет вычислять хеши произвольных данных, которые являются криптографически безопасными, т.е. Digest реализует безопасную одностороннюю функцию.

Односторонние функции обладают некоторыми полезными свойствами. Например, при двух различных входных данных вероятность того, что оба дадут одинаковый результат, крайне мала. В сочетании с тем, что каждый алгоритм хеширования имеет выходные данные фиксированной длины всего в несколько байт, хеши часто используются для создания уникальных идентификаторов произвольных данных. Примером является создание уникального идентификатора для двоичных документов, хранящихся в базе данных.

Еще одной полезной характеристикой односторонних функций (и, следовательно, названием) является то, что, зная хеш, нет никакой информации о исходных данных, которые его породили, т.е. единственный способ идентифицировать исходный ввод — это «перебор» всех возможных комбинаций ввода.

Эти характеристики делают односторонние функции также идеальными компаньонами для алгоритмов подписи с открытым ключом: вместо подписи всего документа сначала вычисляется хеш документа с помощью значительно более быстрого алгоритма хеширования, и только несколько байт его результата нужно подписать с помощью более медленного алгоритма с открытым ключом. Для проверки целостности подписанного документа достаточно повторно вычислить хеш и проверить, что он равен хешу в подписи.

Вы можете получить список всех поддерживаемых на вашей системе алгоритмов хеширования, выполнив эту команду в терминале:

openssl list -digest-algorithms

Среди поддерживаемых алгоритмов хеширования OpenSSL 1.1.1:

  • SHA224, SHA256, SHA384, SHA512, SHA512-224 и SHA512-256

  • SHA3-224, SHA3-256, SHA3-384 и SHA3-512

  • BLAKE2s256 и BLAKE2b512

Каждый из этих алгоритмов может быть инициализирован с использованием названия:

digest = OpenSSL::Digest.new('SHA256')

«Взлом» алгоритма хеширования означает нарушение его свойств односторонней функции, т.е. получение коллизии или поиск способа получить исходные данные более эффективным способом, чем перебор и т.д. Большинство поддерживаемых алгоритмов хеширования могут считаться в этом смысле взломанными, даже очень популярные алгоритмы MD5 и SHA1. Если безопасность для вас важнее всего, то вы, вероятно, должны полагаться на SHA224, SHA256, SHA384 или SHA512.

Хеширование файла

data = File.binread('document')
sha256 = OpenSSL::Digest.new('SHA256')
digest = sha256.digest(data)

Хеширование нескольких кусков данных одновременно

data1 = File.binread('file1')
data2 = File.binread('file2')
data3 = File.binread('file3')
sha256 = OpenSSL::Digest.new('SHA256')
sha256 << data1
sha256 << data2
sha256 << data3
digest = sha256.digest

Использование экземпляра Digest

data1 = File.binread('file1')
sha256 = OpenSSL::Digest.new('SHA256')
digest1 = sha256.digest(data1)

data2 = File.binread('file2')
sha256.reset
digest2 = sha256.digest(data2)

Публичные методы класса

digest(name, data) Показать исходный код
# File ext/openssl/lib/openssl/digest.rb, line 29
def self.digest(name, data)
  super(data, name)
end

Возвращает значение хеша, вычисленное с помощью name Digest. name — это либо полное, либо короткое имя поддерживаемого алгоритма хеширования.

Примеры

OpenSSL::Digest.digest("SHA256", "abc")

что эквивалентно:

OpenSSL::Digest.digest('SHA256', "abc")
Вызов метода суперкласса
new(строка [, данные]) → Digest Показать исходный код
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 = ossl_evp_get_digestbyname(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;
}

Создает экземпляр Digest на основе строки, которая представляет собой либо полное, либо короткое имя поддерживаемого алгоритма хеширования.

Если данные (строка) указаны, они используются в качестве начального ввода для экземпляра Digest, т.е.

digest = OpenSSL::Digest.new('sha256', 'digestdata')

эквивалентно

digest = OpenSSL::Digest.new('sha256')
digest.update('digestdata')

Публичные методы экземпляра

<<(p1)

Не каждый хеш можно вычислить за один проход. Если хеш нужно вычислить из нескольких последовательных источников, каждый из них может быть передан в экземпляр Digest по отдельности.

Пример

digest = OpenSSL::Digest.new('SHA256')
digest.update('First input')
digest << 'Second input' # equivalent to digest.update('Second input')
result = digest.digest
Псевдоним для: update
block_length → целое число Показать исходный код
static VALUE
ossl_digest_block_length(VALUE self)
{
    EVP_MD_CTX *ctx;

    GetDigest(self, ctx);

    return INT2NUM(EVP_MD_CTX_block_size(ctx));
}

Возвращает длину блока алгоритма хеширования, т.е. длину отдельного блока в байтах. Большинство современных алгоритмов разделяют сообщение, которое нужно хешировать, на последовательность блоков фиксированного размера, которые обрабатываются последовательно.

Пример

digest = OpenSSL::Digest.new('SHA1')
puts digest.block_length # => 64
digest_length → целое число Показать исходный код
static VALUE
ossl_digest_size(VALUE self)
{
    EVP_MD_CTX *ctx;

    GetDigest(self, ctx);

    return INT2NUM(EVP_MD_CTX_size(ctx));
}

Возвращает размер результата хеширования, т.е. длину конечного результата хеширования в байтах.

Пример

digest = OpenSSL::Digest.new('SHA1')
puts digest.digest_length # => 20
initialize_copy(p1) Показать исходный код
static VALUE
ossl_digest_copy(VALUE self, VALUE other)
{
    EVP_MD_CTX *ctx1, *ctx2;

    rb_check_frozen(self);
    if (self == other) return self;

    TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx1);
    if (!ctx1) {
        RTYPEDDATA_DATA(self) = ctx1 = EVP_MD_CTX_new();
        if (!ctx1)
            ossl_raise(eDigestError, "EVP_MD_CTX_new");
    }
    GetDigest(other, ctx2);

    if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
        ossl_raise(eDigestError, NULL);
    }
    return self;
}
name → строка Показать исходный код
static VALUE
ossl_digest_name(VALUE self)
{
    EVP_MD_CTX *ctx;

    GetDigest(self, ctx);

    return rb_str_new_cstr(EVP_MD_name(EVP_MD_CTX_get0_md(ctx)));
}

Возвращает короткое имя (sn) этого алгоритма Digest.

Пример

digest = OpenSSL::Digest.new('SHA512')
puts digest.name # => SHA512
reset → self Показать исходный код
static VALUE
ossl_digest_reset(VALUE self)
{
    EVP_MD_CTX *ctx;

    GetDigest(self, ctx);
    if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL) != 1) {
        ossl_raise(eDigestError, "Digest initialization failed.");
    }

    return self;
}

Сбрасывает Digest так, что любая операция Digest#update отбрасывается, и Digest возвращается в начальное состояние.

update(строка) → строка Показать исходный код
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;
}

Не каждый хеш можно вычислить за один проход. Если хеш нужно вычислить из нескольких последовательных источников, каждый из них может быть передан в экземпляр Digest по отдельности.

Пример

digest = OpenSSL::Digest.new('SHA256')
digest.update('First input')
digest << 'Second input' # equivalent to digest.update('Second input')
result = digest.digest
Также псевдоним для: <<

Приватные методы экземпляра

finish → строка Показать исходный код
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;
}

Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API