class OpenSSL::Digest
OpenSSL::Digest ermöglicht es Ihnen, kryptografisch sichere Nachrichten-Digests (manchmal auch als "Hashes" bezeichnet) beliebiger Daten zu berechnen, d.h. ein Digest implementiert eine sichere Einwegfunktion.
Einwegfunktionen bieten einige nützliche Eigenschaften. Zum Beispiel ist die Wahrscheinlichkeit, dass zwei unterschiedliche Eingaben denselben Ausgabewert ergeben, äußerst gering. In Kombination mit der Tatsache, dass jeder Nachrichten-Digest-Algorithmus eine feste Ausgabelänge von nur wenigen Bytes hat, werden Digests häufig verwendet, um eindeutige Identifikatoren für beliebige Daten zu erstellen. Ein gängiges Beispiel ist die Erstellung einer eindeutigen ID für binäre Dokumente, die in einer Datenbank gespeichert werden.
Ein weiteres nützliches Merkmal von Einwegfunktionen (und damit der Name) ist, dass es bei einem gegebenen Digest keinen Hinweis auf die ursprünglichen Daten gibt, die ihn erzeugt haben, d.h. der einzige Weg, die ursprüngliche Eingabe zu identifizieren, ist das "Brute-Force"-Durchprobieren aller möglichen Eingabekombinationen.
Diese Eigenschaften machen Einwegfunktionen auch zu idealen Begleitern für Public-Key-Signaturalgorithmen: Anstatt ein gesamtes Dokument zu signieren, wird zuerst ein Hash des Dokuments mit einem erheblich schnelleren Nachrichten-Digest-Algorithmus erstellt und nur die wenigen Bytes seiner Ausgabe müssen mit dem langsameren Public-Key-Algorithmus signiert werden. Um die Integrität eines signierten Dokuments zu validieren, genügt es, den Hash neu zu berechnen und zu überprüfen, ob er mit dem in der Signatur übereinstimmt.
Sie können eine Liste aller auf Ihrem System unterstützten Digest-Algorithmen erhalten, indem Sie diesen Befehl in Ihrem Terminal ausführen
openssl list -digest-algorithms
Zu den von OpenSSL 1.1.1 unterstützten Nachrichten-Digest-Algorithmen gehören
-
SHA224, SHA256, SHA384, SHA512, SHA512-224 und SHA512-256
-
SHA3-224, SHA3-256, SHA3-384 und SHA3-512
-
BLAKE2s256 und BLAKE2b512
Jeder dieser Algorithmen kann anhand seines Namens instanziiert werden
digest = OpenSSL::Digest.new('SHA256')
Das "Brechen" eines Nachrichten-Digest-Algorithmus bedeutet, seine Einwegfunktionseigenschaften zu umgehen, d.h. eine Kollision zu erzeugen oder einen Weg zu finden, zu den ursprünglichen Daten zu gelangen, der effizienter ist als Brute-Force usw. Die meisten der unterstützten Digest-Algorithmen können in diesem Sinne als gebrochen betrachtet werden, selbst die sehr beliebten Algorithmen MD5 und SHA1. Wenn Sicherheit Ihre höchste Priorität hat, sollten Sie sich wahrscheinlich auf SHA224, SHA256, SHA384 oder SHA512 verlassen.
Hashing einer Datei
data = File.binread('document') sha256 = OpenSSL::Digest.new('SHA256') digest = sha256.digest(data)
Hashing mehrerer Datenstücke gleichzeitig
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
Wiederverwendung einer Digest-Instanz
data1 = File.binread('file1') sha256 = OpenSSL::Digest.new('SHA256') digest1 = sha256.digest(data1) data2 = File.binread('file2') sha256.reset digest2 = sha256.digest(data2)
Öffentliche Klassenmethoden
Source
# File ext/openssl/lib/openssl/digest.rb, line 25 def self.digest(name, data) super(data, name) end
Source
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;
}
Gibt die Namen aller verfügbaren Digests in einem Array zurück.
Source
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;
}
Erstellt eine Digest-Instanz basierend auf string, der entweder der lange Name (ln) oder der kurze Name (sn) eines unterstützten Digest-Algorithmus ist. Eine Liste der unterstützten Algorithmen kann durch Aufruf von OpenSSL::Digest.digests abgerufen werden.
Wenn data (ein String) angegeben wird, wird es als anfängliche Eingabe für die Digest-Instanz verwendet, d.h.
digest = OpenSSL::Digest.new('sha256', 'digestdata')
entspricht
digest = OpenSSL::Digest.new('sha256') digest.update('digestdata')
Öffentliche Instanzmethoden
Source
static VALUE
ossl_digest_block_length(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
return INT2NUM(EVP_MD_CTX_block_size(ctx));
}
Gibt die Blocklänge des Digest-Algorithmus zurück, d.h. die Länge in Bytes eines einzelnen Blocks. Die meisten modernen Algorithmen teilen eine zu digestierende Nachricht in eine Sequenz von Blöcken fester Größe auf, die nacheinander verarbeitet werden.
Beispiel
digest = OpenSSL::Digest.new('SHA1') puts digest.block_length # => 64
Source
static VALUE
ossl_digest_size(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
return INT2NUM(EVP_MD_CTX_size(ctx));
}
Gibt die Ausgabegröße des Digests zurück, d.h. die Länge in Bytes des endgültigen Nachrichten-Digest-Ergebnisses.
Beispiel
digest = OpenSSL::Digest.new('SHA1') puts digest.digest_length # => 20
Source
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)));
}
Source
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;
}
Setzt den Digest zurück, in dem Sinne, dass alle durchgeführten Digest#update-Aufrufe verworfen werden und der Digest wieder in seinen Anfangszustand versetzt wird.
Source
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;
}
Nicht jeder Nachrichten-Digest kann in einem einzigen Durchgang berechnet werden. Wenn ein Nachrichten-Digest aus mehreren aufeinanderfolgenden Quellen berechnet werden soll, kann jede Quelle einzeln an die Digest-Instanz übergeben werden.
Beispiel
digest = OpenSSL::Digest.new('SHA256') digest.update('First input') digest << 'Second input' # equivalent to digest.update('Second input') result = digest.digest
Private Instanzmethoden
Source
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;
}