暗号学的ハッシュは、任意の量のデータを短い固定サイズのダイジェストに変換します。同じ入力は常に同じダイジェストを生成し、異なる入力(たとえ1ビットの変更であっても)はまったく異なるダイジェストを生成し、選んだダイジェストを生成する入力を見つける実用的な方法は存在しません。メッセージ認証コード(MAC)は、この考え方に秘密鍵を追加するもので、鍵を持たない者がデータを改ざんしていないこともダイジェストによって証明できるようになります。
このページのすべての関数はTBytesを受け取りTBytesを返し、sgcCrypto_SHA2、sgcCrypto_Keccak、sgcCrypto_Blake2b、sgcCrypto_Blake2s、sgcCrypto_SipHash、sgcCrypto_HMAC、sgcCrypto_CMACおよびsgcCrypto_Poly1305に含まれています。
SHA-2
TLS 証明書、コード署名、そして今日運用されているほとんどのプロトコルを支えるハッシュファミリーです。特定の理由で別のサイズが必要とされない限り、SHA-256 を使用してください。
function sgcSHA1(const aData: TBytes): TBytes;
function sgcSHA224(const aData: TBytes): TBytes;
function sgcSHA256(const aData: TBytes): TBytes;
function sgcSHA384(const aData: TBytes): TBytes;
function sgcSHA512(const aData: TBytes): TBytes;
SHA-3、SHAKE、cSHAKE、KMAC
SHA-3 は SHA-2 とは異なる構造(Keccak)の上に構築されているため、一方のファミリーの弱点がもう一方に波及することはありません。これが、長期的な保証を必要とするプロトコルがしばしば両方を指定する理由です。SHAKE128 と SHAKE256 は拡張可能出力関数です。固定サイズのダイジェストの代わりに必要な数のバイトを要求でき、同じ入力から得られる短い出力は常に長い出力の先頭部分になります。ML-KEM、ML-DSA、SLH-DSA(ポスト量子暗号を参照)はいずれも内部で SHAKE を基盤としています。KMAC は cSHAKE を基盤とする SHA-3 ネイティブのメッセージ認証コードです。
function sgcSHA3_224(const aData: TBytes): TBytes;
function sgcSHA3_256(const aData: TBytes): TBytes;
function sgcSHA3_384(const aData: TBytes): TBytes;
function sgcSHA3_512(const aData: TBytes): TBytes;
function sgcSHAKE128(const aData: TBytes; aLen: Integer): TBytes;
function sgcSHAKE256(const aData: TBytes; aLen: Integer): TBytes;
function sgcKMAC128(const aKey, aData: TBytes; aLen: Integer; const aCustom: TBytes): TBytes;
function sgcKMAC256(const aKey, aData: TBytes; aLen: Integer; const aCustom: TBytes): TBytes;
BLAKE2b、BLAKE2s
BLAKE2 は、SHA-2 や SHA-3 と同等のセキュリティマージンを持ちながら、ソフトウェア上ではそれらより高速であり、HMAC 構成を使わずに直接オプションの鍵を受け取ることができます。BLAKE2b は 64 ビットプラットフォーム向けで最大 512 ビットのダイジェストに対応し、BLAKE2s は 32 ビットおよび組み込みプラットフォーム向けで最大 256 ビットのダイジェストに対応します。短いダイジェストは完全なダイジェストを切り詰めたものではありません。長さそのものがハッシュに混ぜ込まれているため、プログラムがサイズを切り替えても出力が一致することはありません。
function sgcBlake2b(const aData: TBytes; aDigestLen: Integer = 64): TBytes;
function sgcBlake2b_Keyed(const aKey, aData: TBytes; aDigestLen: Integer = 64): TBytes;
function sgcBlake2s(const aData: TBytes; aDigestLen: Integer = 32): TBytes;
function sgcBlake2s_Keyed(const aKey, aData: TBytes; aDigestLen: Integer = 32): TBytes;
SipHash
SipHash-2-4 は、ハッシュテーブルの検索のために設計された高速な鍵付きハッシュです。その役割は、攻撃者が選んだ入力をアプリケーションに与え、それらすべてを同じバケットに集中させて O(1) の検索を O(n) に変えてしまう、ハッシュフラッディングと呼ばれるサービス拒否攻撃を防ぐことです。ちょうど 16 バイトの鍵を受け取り、8 バイトのタグを生成します。汎用の MAC ではないため、メッセージの認証に使用すべきではありません。
function sgcSipHash24(const aKey, aData: TBytes): TBytes;
HMAC
HMAC は、上記のいずれのハッシュもメッセージ認証コードに変換します。基盤となるハッシュが直接鍵を受け取れない場合(SHA-1、SHA-2)の標準的な選択肢です。
function sgcHMAC_SHA1(const aKey, aData: TBytes): TBytes;
function sgcHMAC_SHA256(const aKey, aData: TBytes): TBytes;
function sgcHMAC_SHA384(const aKey, aData: TBytes): TBytes;
function sgcHMAC_SHA512(const aKey, aData: TBytes): TBytes;
var
oTag: TBytes;
begin
oTag := sgcHMAC_SHA256(TBytes(oKey), TBytes(oMessage));
end;
AES-CMAC
CMAC は、ハッシュではなくブロック暗号から MAC を構築します。プロトコルが名前で AES-CMAC を指定している場合(スマートカードや IoT の仕様でよく見られます)に使用してください。それ以外の場合は、HMAC-SHA256 の方がより一般的なデフォルトです。
function sgcAES_CMAC(const aKey, aData: TBytes): TBytes;
function sgcAES_CMAC_Verify(const aKey, aData, aTag: TBytes): Boolean;
Poly1305
Poly1305 はワンタイム認証子であり、同じ鍵を2回使用してはいけません。実際には直接呼び出されることはなく、対称暗号化ページで扱う ChaCha20-Poly1305 および XChaCha20-Poly1305 の AEAD 暗号における認証部分として使われ、これらはメッセージごとに新しいワンタイム鍵を導出します。
function sgcPoly1305(const aKey, aData: TBytes): TBytes;
function sgcPoly1305_Verify(const aKey, aData, aTag: TBytes): Boolean;
MAC またはパスワードハッシュの比較
2つのタグまたはダイジェストのいずれかが信頼できない情報源から得られたものである場合、単純な=で比較してはいけません。不一致を検出した時点で処理を終了するバイト単位の比較は、不一致が早い位置で発生するほど測定可能なレベルで処理時間が短くなり、これは攻撃者が多数回の試行を通じて1バイトずつ有効なタグを偽造するのに十分な手がかりとなります。代わりに、暗号技術の概要ページの「エンコーディング & ユーティリティ」に記載されているsgcCrypto_Encodingの定数時間比較を使用してください。
function sgcConstantTimeEquals(const aLeft, aRight: TBytes): Boolean;
RIPEMD-160
ヨーロッパの RIPE プロジェクトによる 160 ビットダイジェストで、sgcCrypto_Legacyに含まれていますが、以下のセクションが意味する意味でのレガシーではありません。MD5 や SHA-1 のように破られているわけではありませんが、SHA-256 より低速でセキュリティマージンも小さいため、デフォルトの選択としてではなく、ある形式が名指しで要求している場合に使うべきものです。Bitcoin およびそこから派生したすべてのチェーンは、アドレスに SHA-256 の上に重ねてこれを使用しています。HMAC-RIPEMD160 は RFC 2286 です。
function sgcRIPEMD160(const aData: TBytes): TBytes;
function sgcHMAC_RIPEMD160(const aKey, aData: TBytes): TBytes;
var
oHash160: TBytes;
begin
{ the Bitcoin address digest: RIPEMD-160 over SHA-256 }
oHash160 := sgcRIPEMD160(sgcSHA256(oPublicKey));
end;
レガシーハッシュ
sgcCrypto_Legacyは MD4、MD5、HMAC-MD5 を提供します。この3つはいずれもセキュリティ用のプリミティブとしては破綻しており、MD4 と MD5 の両方について実用的な衝突が公表されています。これらは、名前で指定する古いプロトコルやファイル形式(たとえば NTLM 認証)と相互運用するためだけに存在します。新規の用途では選択せず、代わりに SHA-256 または BLAKE2b を使用してください。
function sgcMD4(const aData: TBytes): TBytes;
function sgcMD5(const aData: TBytes): TBytes;
function sgcHMAC_MD5(const aKey, aData: TBytes): TBytes;