Spec-Zone.ru › Ruby 4.0
  1. OpenSSL::
  2. Digest

class OpenSSL::Digest

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 25
def self.digest(name, data)
  super(data, name)
end

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

Пример

OpenSSL::Digest.digest("SHA256", "abc")
Вызывает метод суперкласса
OpenSSL::Digest.digests → array[string...] Показать исходный код
static VALUE
ossl_s_digests(VALUE self)
{
    VALUE ary;

    ary = rb_ary_new();
    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
                           add_digest_name_to_ary,
                           (void*)ary);

    return ary;
}

Возвращает массив с именами всех доступных алгоритмов дайджеста.

new(string [, data]) → Digest Показать исходный код
static VALUE
ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
{
    EVP_MD_CTX *ctx;
    const EVP_MD *md;
    VALUE type, data, md_holder;

    rb_scan_args(argc, argv, "11", &type, &data);
    md = ossl_evp_md_fetch(type, &md_holder);
    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");
    rb_ivar_set(self, id_md_holder, md_holder);

    if (!NIL_P(data)) return ossl_digest_update(self, data);
    return self;
}

Создаёт экземпляр Digest на основе string, которое является полным именем (ln) или сокращённым именем (sn) поддерживаемого алгоритма дайджеста. Список поддерживаемых алгоритмов можно получить вызовом OpenSSL::Digest.digests.

Если задано data (объект String), оно используется как начные входные данные для экземпляра Digest, то есть:

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

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

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

Общедоступные методы экземпляра

<<
Псевдоним для: update
block_length → integer Показать исходный код
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 → integer Показать исходный код
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
name → string Показать исходный код
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)));
}

Возвращает сокращённое имя этого алгоритма 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(string) → aString Показать исходный код
static 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 → aString Показать исходный код
static VALUE
ossl_digest_finish(VALUE self)
{
    EVP_MD_CTX *ctx;
    VALUE str;

    GetDigest(self, ctx);
    str = rb_str_new(NULL, EVP_MD_CTX_size(ctx));
    if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL))
        ossl_raise(eDigestError, "EVP_DigestFinal_ex");

    return str;
}

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

Spec-Zone.ru

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