7

sha-256 アルゴリズムの実装に懸命に取り組んでいます。メッセージのパディングに問題があります。sha-256 の場合、メッセージの末尾に 1 ビットを追加する必要があります。これまで$message .= (chr 0x80); のところ、次のステップは、空のスペース (512 ビット ブロック) を 0 で埋めることです。次の式で計算しました: l+1+k=448-l そしてそれをメッセージに追加します。私の問題は次のとおりです。最後の64ビットブロックにメッセージの長さのバイナリ表現を追加し、残りを再び0で埋めます。perl はそれらのデータ型を自分で処理するため、「バイト」データ型はありません。どの値を追加する必要があるかを知るにはどうすればよいですか?

公式仕様も参照してください: http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf

4

2 に答える 2

5

可能であれば、棚から何かを取り出してください。独自の SHA-256 実装を展開する必要はありません。公式の承認を得るには、認証を受ける必要があるからです。

とは言え、仕様は

5.1.1 SHA-1、SHA-224、SHA-256

メッセージの長さMlビットであるとします。1メッセージの末尾にビットを追加し、その後にkゼロ ビットを追加します。ここで、kは方程式の最小の非負の解です。

l + 1 + k ≡ 448 mod 512

次に、バイナリ表現を使用して表現された数lに等しい 64 ビット ブロックを追加します。たとえば、(8 ビット ASCII) メッセージ「<strong>abc」の長さは 8 × 3 = 24 であるため、メッセージは 1 ビットでパディングされ、次に 448 - (24 + 1) = 423 ゼロ ビットでパディングされ、次に512 ビットの埋め込みメッセージになるメッセージ長

                                  423       64
                                 .-^-.  .---^---.
01100001  01100010  01100011  1  00…00  00…011000
   “a”       “b”       “c”                  '-v-'
                                             l=24

次に、パディングされたメッセージの長さは 512 ビットの倍数になるはずです。

単一ビットをアドレス指定できるため、使用したくなるかもしれませんがvec、ファンキーなアドレス指定を回避する必要があります。

ビットが 4 以下の場合、文字列はバイトに分割され、各バイトのビットは 8/ BITSグループに分割されます。0x01バイトのビットは、0x020x040x08、 、 、0x100x200x40ように、リトル エンディアン風の方法で番号付けされ0x80ます。たとえば、1 つの入力バイトchr(0x36)を 2 つのグループに分割すると、リストが得られます(0x6, 0x3)。それを 4 つのグループに分けると、 が得られ(0x2, 0x1, 0x3, 0x0)ます。

代わりに、指定のpackテンプレートB*

ビット文字列 (各バイト内の降順のビット順)。

N

「ネットワーク」(ビッグエンディアン) 順の unsigned long (32 ビット)。

後者は、メッセージの長さを組み立てるのに役立ちます。quad のパラメーターがpackありQますが、結果はネイティブの順序になります。

少し準備作業から始めます

our($UPPER32BITS,$LOWER32BITS);
BEGIN {
  use Config;
  die "$0: $^X not configured for 64-bit ints"
    unless $Config{use64bitint};

  # create non-portable 64-bit masks as constants
  no warnings "portable";
  *UPPER32BITS = \0xffff_ffff_0000_0000;
  *LOWER32BITS = \0x0000_0000_ffff_ffff;
}

pad_message次に、次のように定義できます

sub pad_message {
  use bytes;

  my($msg) = @_;
  my $l = bytes::length($msg) * 8;
  my $extra = $l % 512;  # pad to 512-bit boundary
  my $k = 448 - ($extra + 1);

  # append 1 bit followed by $k zero bits
  $msg .= pack "B*", 1 . 0 x $k;

  # add big-endian length
  $msg .= pack "NN", (($l & $UPPER32BITS) >> 32), ($l & $LOWER32BITS);

  die "$0: bad length: ", bytes::length $msg
    if (bytes::length($msg) * 8) % 512;

  $msg;
}

コードがパディングされたメッセージを出力するとします

my $padded = pad_message "abc";

# break into multiple lines for readability
for (unpack("H*", $padded) =~ /(.{64})/g) {
  print $_, "\n";
}

次に、出力は

616263800000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000018

これは仕様に一致します。

于 2012-05-31T19:58:03.220 に答える
5

まず、演習としてこれを実行していただければ幸いです。Digestコアには、すでに SHA-256 を問題なく計算するモジュールがあります。

$message .= (chr 0x80);1 ビットではなく、1 バイトを追加することに注意してください。本当にビット単位の操作が必要な場合は、vec関数を見てください。

整数のバイナリ表現を取得するには、packを使用する必要があります。64ビットにするには、次のようにします

$message .= pack 'Q', length($message)

'Q' 形式は 64 ビット perl でのみ利用可能であることに注意してください。あなたのものでない場合は、4 つの 0 バイトを 32 ビット値 (パック形式L) で連結するだけです。

于 2012-05-31T10:02:53.697 に答える