前々回はSHA-1、前回はSHA-256の仕様と実装について比較したので、今回はSHA-512について比較してみようと思います。
今回の比較に使用するソースコードは、前回同様、GitHubにあるopensslのソースコードを使用しました。その中の、crypto/sha/sha512.cです。
念のため、FIPS 180-4のリンクも置いておきます。
SHAの共通点やWordの操作については、SHA-1編を参照してください。
SHA-512の仕様と実装の比較
1.ブロックサイズやWordサイズ
SHA-512のブロックサイズは1024bits、Wordサイズは64bitsです。
各ブロックは16個の64bitに分けられて処理されます。
2.ハッシュの初期値
FIPS 180-4で記述されているSHA-512の初期値は以下です。
crypto/sha/sha512.cに設定されている値と一致します。
81 int SHA512_Init(SHA512_CTX *c) 82 { 83 c->h[0] = U64(0x6a09e667f3bcc908); 84 c->h[1] = U64(0xbb67ae8584caa73b); 85 c->h[2] = U64(0x3c6ef372fe94f82b); 86 c->h[3] = U64(0xa54ff53a5f1d36f1); 87 c->h[4] = U64(0x510e527fade682d1); 88 c->h[5] = U64(0x9b05688c2b3e6c1f); 89 c->h[6] = U64(0x1f83d9abfb41bd6b); 90 c->h[7] = U64(0x5be0cd19137e2179); 91 92 c->Nl = 0; 93 c->Nh = 0; 94 c->num = 0; 95 c->md_len = SHA512_DIGEST_LENGTH; 96 return 1; 97 }
3.定数
FIPS 180-4で記述されているSHA-512の定数は以下です。
80個の64bitの定数を使用します。これらはSHA-384、SHA-512/224、SHA-512/256でも同じ値を使用するようです。
crypto/sha/sha512.cでも同じ値が設定されています。
279 static const SHA_LONG64 K512[80] = { 280 U64(0x428a2f98d728ae22), U64(0x7137449123ef65cd), 281 U64(0xb5c0fbcfec4d3b2f), U64(0xe9b5dba58189dbbc), 282 U64(0x3956c25bf348b538), U64(0x59f111f1b605d019), 283 U64(0x923f82a4af194f9b), U64(0xab1c5ed5da6d8118), 284 U64(0xd807aa98a3030242), U64(0x12835b0145706fbe), 285 U64(0x243185be4ee4b28c), U64(0x550c7dc3d5ffb4e2), 286 U64(0x72be5d74f27b896f), U64(0x80deb1fe3b1696b1), 287 U64(0x9bdc06a725c71235), U64(0xc19bf174cf692694), 288 U64(0xe49b69c19ef14ad2), U64(0xefbe4786384f25e3), 289 U64(0x0fc19dc68b8cd5b5), U64(0x240ca1cc77ac9c65), 290 U64(0x2de92c6f592b0275), U64(0x4a7484aa6ea6e483), 291 U64(0x5cb0a9dcbd41fbd4), U64(0x76f988da831153b5), 292 U64(0x983e5152ee66dfab), U64(0xa831c66d2db43210), 293 U64(0xb00327c898fb213f), U64(0xbf597fc7beef0ee4), 294 U64(0xc6e00bf33da88fc2), U64(0xd5a79147930aa725), 295 U64(0x06ca6351e003826f), U64(0x142929670a0e6e70), 296 U64(0x27b70a8546d22ffc), U64(0x2e1b21385c26c926), 297 U64(0x4d2c6dfc5ac42aed), U64(0x53380d139d95b3df), 298 U64(0x650a73548baf63de), U64(0x766a0abb3c77b2a8), 299 U64(0x81c2c92e47edaee6), U64(0x92722c851482353b), 300 U64(0xa2bfe8a14cf10364), U64(0xa81a664bbc423001), 301 U64(0xc24b8b70d0f89791), U64(0xc76c51a30654be30), 302 U64(0xd192e819d6ef5218), U64(0xd69906245565a910), 303 U64(0xf40e35855771202a), U64(0x106aa07032bbd1b8), 304 U64(0x19a4c116b8d2d0c8), U64(0x1e376c085141ab53), 305 U64(0x2748774cdf8eeb99), U64(0x34b0bcb5e19b48a8), 306 U64(0x391c0cb3c5c95a63), U64(0x4ed8aa4ae3418acb), 307 U64(0x5b9cca4f7763e373), U64(0x682e6ff3d6b2b8a3), 308 U64(0x748f82ee5defb2fc), U64(0x78a5636f43172f60), 309 U64(0x84c87814a1f0ab72), U64(0x8cc702081a6439ec), 310 U64(0x90befffa23631e28), U64(0xa4506cebde82bde9), 311 U64(0xbef9a3f7b2c67915), U64(0xc67178f2e372532b), 312 U64(0xca273eceea26619c), U64(0xd186b8c721c0c207), 313 U64(0xeada7dd6cde0eb1e), U64(0xf57d4f7fee6ed178), 314 U64(0x06f067aa72176fba), U64(0x0a637dc5a2c898a6), 315 U64(0x113f9804bef90dae), U64(0x1b710b35131c471b), 316 U64(0x28db77f523047d84), U64(0x32caab7b40c72493), 317 U64(0x3c9ebe0a15c9bebc), U64(0x431d67c49c100d4c), 318 U64(0x4cc5d4becb3e42b6), U64(0x597f299cfc657e2a), 319 U64(0x5fcb6fab3ad6faec), U64(0x6c44198c4a475817) 320 };
4.関数
FIPS 180-4で記述されているSHA-512の関数は以下です。
SHA-256と非常によく似ていますが、SHA-512のWordサイズが64bitだという点には注意が必要です。
crypto/sha/sha512.cでは以下のように定義されています。
404 # ifndef ROTR 405 # define ROTR(x,s) (((x)>>s) | (x)<<(64-s)) 406 # endif 407 # define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) 408 # define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) 409 # define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) 410 # define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) 411 # define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) 412 # define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
SHA-512の場合は、ROTRに渡す値がFIPS 180-4に記述されている通りに実装されていることが分かります。
5.メッセージスケジュールの生成
FIPS 180-4で記述されているSHA-512のメッセージスケジュールの生成方法は以下です。
σ関数の中身やラウンド数が違いますが、形自体はSHA-256の時とよく似ています。
crypto/sha/sha512.cでは以下のように定義されています。
497 for (i = 0; i < 16; i++) { 498 # ifdef B_ENDIAN 499 T1 = X[i] = W[i]; 500 # else 501 T1 = X[i] = PULL64(W[i]); 502 # endif ...(中略)... 515 for (; i < 80; i++) { 516 s0 = X[(i + 1) & 0x0f]; 517 s0 = sigma0(s0); 518 s1 = X[(i + 14) & 0x0f]; 519 s1 = sigma1(s1); 520 521 T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf];
SHA-256の時の同じように、iが16まではそのままの値を使用し、16から80までは0xfとマスクを取った位置にある要素からWtを算出しています。その際に使用する要素は、0xfを法として合同な位置にある要素である点には注意が必要です。
6.ハッシュ値の計算
crypto/sha/sha512.cの該当部分は以下です。
497 for (i = 0; i < 16; i++) { 498 # ifdef B_ENDIAN 499 T1 = X[i] = W[i]; 500 # else 501 T1 = X[i] = PULL64(W[i]); 502 # endif 503 T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; 504 T2 = Sigma0(a) + Maj(a, b, c); 505 h = g; 506 g = f; 507 f = e; 508 e = d + T1; 509 d = c; 510 c = b; 511 b = a; 512 a = T1 + T2; 513 } 514 515 for (; i < 80; i++) { 516 s0 = X[(i + 1) & 0x0f]; 517 s0 = sigma0(s0); 518 s1 = X[(i + 14) & 0x0f]; 519 s1 = sigma1(s1); 520 521 T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf]; 522 T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; 523 T2 = Sigma0(a) + Maj(a, b, c); 524 h = g; 525 g = f; 526 f = e; 527 e = d + T1; 528 d = c; 529 c = b; 530 b = a; 531 a = T1 + T2; 532 }
こちらもSHA-256の時と同じように、iが16まで処理と16から80までの処理では、メッセージスケジュールを生成している部分だけが異なりますが、その他は全て同じです。
SHA-512も、FIPS 180-4のアルゴリズムがそのままの形で実装されています。
SHA-256同様、変数のdからe、hからaに移る時に値が変っていくイメージです。
最後に64bitの8つの変数の値を並べることで、512bitのメッセージダイジェストが得られます。
以上がSHA-512の仕様とその実装の比較でした。
これまでSHA-1、SHA-256、SHA-512の仕様と実装を比較してきて、今まではブラックボックスでしかなかったSHAを詳しく把握することができました。
これらの一連の記事がどなたかの理解の役に立てば幸いです。