Spec-Zone.ru › Ruby 2.6

класс 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. Каждый поддерживаемый алгоритм хэширования связан с идентификатором объекта, которые, в свою очередь, имеют короткие и полные имена. Например, идентификатор объекта SHA-1 — 1.3.14.3.2.26, его короткое имя — «SHA1», а полное — «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)

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

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

Возвращает значение хэша, вычисленное с использованием name Digest. 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')

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

<<(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 таким образом, что любая выполненная операция Digest#update отбрасывается, и Digest возвращается в исходное состояние.

update(string) → строка Показать исходный код
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
Также алиасируется как: <<

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

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