SM3 アルゴリズムは、2010 年に中国コンピュータ暗号研究センターによって開始された暗号ハッシュ関数アルゴリズムです。国家機密において非常に重要なアルゴリズムとして知られています。この記事では、PHP で SM3 アルゴリズムを実装する方法を紹介します。
1. アルゴリズムの概要
SM3 アルゴリズムは、暗号化ハッシュ関数アルゴリズムです。暗号化ハッシュ関数は、任意のサイズのデータを入力として受け入れ、それを固定長の出力に変換します。出力値は入力値ごとに異なります。パスワード ハッシュ関数には次の特性があります:
1. 固定長: パスワード ハッシュ関数の出力長は固定である必要があり、通常は 128、160、192、224、または 256 ビットです。
2. 不可逆性: ハッシュ出力が与えられた場合、その入力を決定することはできません。これは、一方向ハッシュ関数と呼ばれます。
3. 強い抵抗: ハッシュ値が与えられた場合、同じハッシュ値を持つ入力を見つけることは不可能ですが、入力内の単一または限られた数のビットのみを変更すると、元の入力とは異なる入力が生成されることになります。出力。
SM3 アルゴリズムは、マークル-ダムガード構造を使用してメッセージをブロックに分割し、反復圧縮処理を実行します。
アルゴリズム処理は 4 つの部分に分かれています:
1. パディング: メッセージの長さが 512 ビットの倍数になるようにメッセージをパディングします。
2. 圧縮: ブロックを 256 ビットのメッセージ ダイジェストに処理します。
3. 反復: すべてのブロックが圧縮されるまで、各メッセージ ブロックを反復的に処理します。
4. 出力: 最終的な 256 ビット ダイジェストを生成します。
2. PHP の実装
1. パディング
PHP にパディング関数を実装して、メッセージ長が 512 ビットの倍数になるようにします。
function padding($msg) {
$length = strlen($msg) * 8; // 消息长度,单位是比特 $k = 448 - (($length + 64) % 512); // 填充长度 if ($k < 0) { $k += 512; } $msg .= hex2bin("80"); // 消息后面添加1 for ($i = 0; $i < $k / 8 - 1; $i++) { $msg .= hex2bin("00"); // 用0填充 } $msg .= pack("N", $length); // 添加消息长度 return $msg;
}
2. 圧縮
PHP で圧縮関数を実装して、512 ビットのメッセージ ブロック A を処理します。 256 ビットのメッセージ ダイジェスト。
関数 CF($X, $Y, $Z) {
return ($X & $Y) | (~$X & $Z);
}
関数 MG($X, $Y, $Z) {
return ($X & $Y) | ($X & $Z) | ($Y & $Z);
}
関数 P0($X) {
return $X ^ (($X << 9) | ($X >> 23)) ^ (($X << 17) | ($X >> 15));
}
関数 P1($X) {
return $X ^ (($X << 15) | ($X >> 17)) ^ (($X << 23) | ($X >> 9));
}
関数 FF($X, $Y, $ Z, $j) {
if ($j >= 0 && $j <= 15) { return P0($X ^ $Y ^ $Z); } else { return P1($X ^ $Y ^ $Z); }
}
function GG($X, $Y, $Z, $j) {
if ($j >= 0 && $j <= 15) { return P0($X ^ $Y ^ $Z); } else { return P1($X ^ $Y ^ $Z); }
}
function SM3_compress($msg, $IV) {
$W = array(); $V = $IV; $A = $IV[0]; $B = $IV[1]; $C = $IV[2]; $D = $IV[3]; $E = $IV[4]; $F = $IV[5]; $G = $IV[6]; $H = $IV[7]; for ($i = 0; $i < 16; $i++) { $W[$i] = unpack("N", substr($msg, $i * 4, 4))[1]; } for ($j = 16; $j < 68; $j++) { $W[$j] = GG($W[$j - 16] ^ $W[$j - 9] ^ ($W[$j - 3] << 15) ^ ($W[$j - 13] >> 17), 15) ^ ($W[$j - 6] << 7) ^ $W[$j - 16]; } for ($j = 0; $j < 64; $j++) { $SS1 = ($A << 12) | ($A >> 20); $SS2 = ($SS1 << 7) | ($SS1 >> 25); $TT1 = FF($A, $B, $C, $j) + $D + $SS2 + $W[$j] + (0x79cc4519 >> $j); $SS1 = ($E << 12) | ($E >> 20); $SS2 = ($SS1 << 7) | ($SS1 >> 25); $TT2 = GG($E, $F, $G, $j) + $H + $SS2 + $W[$j] + (0x7a879d8a >> $j); $D = $C; $C = ($B << 9) | ($B >> 23); $B = $A; $A = $TT1; $H = $G; $G = ($F << 19) | ($F >> 13); $F = $E; $E = P0($TT2); } $V[0] = $V[0] ^ $A; $V[1] = $V[1] ^ $B; $V[2] = $V[2] ^ $C; $V[3] = $V[3] ^ $D; $V[4] = $V[4] ^ $E; $V[5] = $V[5] ^ $F; $V[6] = $V[6] ^ $G; $V[7] = $V[7] ^ $H; return $V;
}
3. 反復
PHP で反復関数を実装し、すべてのブロックが圧縮されるまで各メッセージ ブロックを反復的に処理します。
function SM3($msg) {
$IV = array( 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e ); $msg = padding($msg); $n = strlen($msg) / 64; for ($i = 0; $i < $n; $i++) { $block = substr($msg, $i * 64, 64); $IV = SM3_compress($block, $IV); } $digest = ""; foreach ($IV as $v) { $digest .= str_pad(dechex($v), 8, "0", STR_PAD_LEFT); } return $digest;
}
4. アルゴリズムのテスト
実装が正しいかどうかを検証するには、次のようにします。 GM/T 0004-2012 暗号化ハッシュ アルゴリズム テスト。
require_once "sm3.php";
$input = "abc";
$expected_output = "66C7F0FAD8E2DDDB2D0A6EEA2E2ECEB4E83441BEC4C3056BFCDC6F7E9
D9E8B7F5D6A5B96D011A7B 19A1456";
$output = SM3($input);
var_dump($output === $expected_output); // true
?>
他のメッセージを使用してテストおよび検証することもできます。実装は正しいですか?
以上がPHP で SM3 アルゴリズムを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。