
読者の皆さん、こんにちは。
おそらくあなたの多くは、新しいSHA-3標準を採用するために、NISTがハッシュ関数間の競争を数年間行ってきたことをおそらく知っています。 そして今年、この賞はそのヒーローを見つけました。 新しい標準が安全に採用されました。
さて、この標準は既に採用されているので、それが何であるかを見る時です。
そして、静かな土曜日の夜、私はブラウザgoogle.comで開かれた
マニュアルで自分自身を
カバーしたので、私の小さな研究を始めました。
前戯
224,256,384および512ビットの可変出力長を持つKeccakハッシュ関数が新しい標準として選択されました。 ケッカックの中心にあるのは、スポンジ(スポンジ、上の画像と同じ)と呼ばれるデザインです。
この設計は次のように表すことができます。

図からわかるように、スキームは2つの段階で構成されています。
- 吸収する 元のメッセージMは、マルチラウンド順列fを経ます。
- スクイージング(リリース)。 順列の結果として生じるZ値の出力。
注意深い読者は、図の文字rとcに気付いたに違いありません。 前もって陰謀を明らかにすることはしません。これらの変数の値を変えることで、まったく異なるハッシュ関数が得られるとだけ言っておきましょう。 したがって、SHA-512では、r = 576、c = 1024をこれらの値として選択する必要があります。
さらに詳細に?
そのため、上で述べたように、KeccakアルゴリズムはSpongeコンストラクトに基づいています。 つまり、ハッシュを取得するには、次の簡単なアクションを実行する必要があります。
- 元のメッセージMを取得し、rの長さの倍数に追加します。 追加規則は、その単純さに魅了されます。 式の形式では、M = M || 0x01 || 0x00 || .. || 0x00 || 0x80のように表すことができます。 または、ロシア語では、1バイトがメッセージに追加され、必要な数のゼロが追加され、このアンサンブル全体が0x80の値でバイトを完成させます。
UPD:上記のすべては、複数のバイトが追加された場合にのみ適用されます。 ただし、1バイトのみを追加する必要がある場合は、0x81のみを追加すれば十分です。 尊敬されているOverQuantumの警戒のおかげで、間違いが明らかになりました。 そしてさらに以前、fdsc habrayuzerは同じことについて話しました。サンドボックスの投稿は気づかれていませんでしたが、今では正義が勝利しました。 したがって、これを念頭に置いてコードを書き換える必要があります! - 次に、長さrビットの各ブロックM iに対して 、次を実行します。
- 初期状態Sのセットの最初のrビットを使用したモジュロ2加算。関数が開始する前に、Sのすべての要素はゼロになります。
- 結果のデータに関数fをN回適用します。 ブロックM i + 1の初期状態のセットSは、ブロックM iの最後のラウンドの結果になります。
- すべてのブロックM iが終了したら、最終結果を取得してハッシュ値として返します。
とにかく、何も明確ではありません!
さて、今では、
ブラックジャックと売春婦のコードと説明を含むアルゴリズムの全体が
詳しく説明されています。
しかし、まず、秘密のベールをはがして、パラメーターrとcが必要な理由を教えてください。
このため、Keccakハッシュ関数は、ユーザーが事前定義関数b = {f-25、f-50、f-100、fのセットから各ブロックM
iに使用する置換関数fを選択できるように実装されていると言わなければなりません。 -200、f-400、f-800、f-1600}。
実装で、たとえばf-800関数を使用するには、等式r + c = 800が満たされるように、そのようなrとcを選択する必要があります。
さらに、rとcの値を変更することにより、ハッシュ関数のラウンド数を変更します。 なぜなら これらの数は、式n = 12 + 2lで計算されます。ここで、2
l =(b / 25)です。 したがって、b = 1600の場合、ラウンド数は24です。
ただし、ユーザーは作成者が実装に提案する機能を選択する権利を持っていますが、SHA-3標準として受け入れられるのはKeccak-1600機能のみであり、作成者はそれのみを使用することを強くお勧めします。 そのため、著者はさまざまな長さのハッシュの主な値として次のパラメーターを選択しました。
SHA-224:r = 1156、c = 448(結果の最初の28バイトを返す)
SHA-256:r = 1088、c = 512(結果の最初の32バイトを返す)
SHA-384:r = 832、c = 768(最初の48バイトの結果を返す)
SHA-512:r = 576、c = 1024(最初の64バイトの結果を返す)
コードはどこにありますか?
そして、これらすべての説明の後、すでにアルゴリズムの擬似コードに直接行くことができます。
吸収段階は、次の関数として表すことができます。
Keccak-f[b](A) { forall i in 0…nr-1 A = Round[b](A, RC[i]) return A }
ここで、bは選択された関数の値です(デフォルトは1600)。 また、Round()関数は、各ラウンドに適用される擬似ランダム順列です。 ラウンド数nrは、rとcの値から計算されます。
各ラウンドで実行される操作は次の機能です。
Round[b](A,RC) { θ step for(int x=0; x<5; x++) C[x] = A[x,0] xor A[x,1] xor A[x,2] xor A[x,3] xor A[x,4]; for(int x=0; x<5; x++) D[x] = C[x-1] xor rot(C[x+1],1); for(int x=0; x<5; x++) A[x,y] = A[x,y] xor D[x]; ρ and π steps for(int x=0; x<5; x++) for(int y=0; y<5; y++) B[y,2*x+3*y] = rot(A[x,y], r[x,y]); χ step for(int x=0; x<5; x++) for(int y=0; y<5; y++) A[x,y] = B[x,y] xor ((not B[x+1,y]) and B[x+2,y]); ι step A[0,0] = A[0,0] xor RC return A }
これは4つのステップで構成され、各ステップで受信データに対して一連の論理演算が実行されます。
ここで、関数rot(X、n)は、要素Xのn位置による巡回シフトを示します。
配列r []は、各ラウンドでシフトするバイト数を示す事前定義された値のセットです。 この配列のすべての要素の値は、次の表に示されています。

RC配列は、事前定義された定数のセットです。

Keccak関数自体は次のとおりです。
Keccak[r,c](M) { Initialization and padding for(int x=0; x<5; x++) for(int y=0; y<5; y++) S[x,y] = 0; P = M || 0x01 || 0x00 || … || 0x00; P = P xor (0x00 || … || 0x00 || 0x80);
Absorbigステップでは、値のハッシュが計算されます。
そして、スクイージング段階で、必要なハッシュ長に達するまで結果を出力します。
ネタバレの下で、これらすべてのアクションを実装するC#で書かれた小さなクラス ここからソースをダウンロードできます。PSこの記事のすべての資料とイラストは、
公式のKeccakハッシュ関数のWebサイトで見つかりました
。UPD:
fshpは、新しい標準の主な機能
に関するロシア語の説明へのリンクを親切に共有しました。
UPD2:記事を公開した後、Admiralというニックネームを持つ読者からメールで連絡がありました。 彼は、文字列操作を使用しない、より最適化されたコードを提案しました。
提督リーダーの実装 using System; using System.Linq; using System.Collections.Generic; class Program { static private Byte InstanceNumber = 6; static private UInt16[] b_array = { 25, 50, 100, 200, 400, 800, 1600 };