Spec-Zone.ru › Ruby 2.5

класс OpenSSL::Digest

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

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

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

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

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

К поддерживаемым алгоритмам хэширования относятся:

  • SHA, SHA1, SHA224, SHA256, SHA384 и SHA512

  • MD2, MD4, MDC2 и 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. Каждый поддерживаемый алгоритм хэширования имеет связанный с ним идентификатор OBJECT, а у них, в свою очередь, есть короткие/полные имена. Например, идентификатором OBJECT для SHA-1 является 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

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

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

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

Методы класса public

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

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

Примеры

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

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

OpenSSL::Digest::SHA256.digest("abc")
Вызывает метод суперкласса
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;

    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 на основе string, которое является либо полным (ln), либо коротким (sn) именем поддерживаемого алгоритма хэширования.

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

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

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

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

Методы экземпляра public

<<(p1)
Псевдоним для: 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::SHA1.new
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::SHA1.new
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_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
}

Возвращает sn этого алгоритма хэширования Digest.

Пример

digest = OpenSSL::Digest::SHA512.new
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_md(ctx), NULL) != 1) {
        ossl_raise(eDigestError, "Digest initialization failed.");
    }

    return self;
}

Сбрасывает 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::SHA256.new
digest.update('First input')
digest << 'Second input' # equivalent to digest.update('Second input')
result = digest.digest
Также алиас для: <<

Методы экземпляра private

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–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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