SM3 알고리즘은 중국 컴퓨터 암호 연구 센터에서 2010년에 출시한 암호 해시 함수 알고리즘입니다. 국가 기밀에 있어서 매우 중요한 알고리즘으로 알려져 있습니다. 이번 글에서는 SM3 알고리즘을 PHP로 구현하는 방법을 소개하겠습니다.
1. 알고리즘 소개
SM3 알고리즘은 암호화 해시 함수 알고리즘입니다. 암호화 해시 함수는 모든 크기의 데이터를 입력으로 받아들이고 이를 고정 길이 출력으로 변환하며 출력 값은 입력 값에 따라 다릅니다. 암호화 해시 함수에는 다음과 같은 특징이 있습니다.
1. 고정 길이: 암호화 해시 함수의 출력 길이는 일반적으로 128, 160, 192, 224 또는 256비트로 고정되어야 합니다.
2. 비가역성: 해시 출력이 주어지면 입력을 확인할 수 없으며 이를 단방향 해시 함수라고 합니다.
3. 강한 저항: 해시 값이 주어지면 동일한 해시 값을 가진 입력을 찾을 수 없으며 입력에서 단일 또는 제한된 수의 비트만 변경하면 원래 입력과 다른 출력이 생성됩니다.
SM3 알고리즘은 Merkle-Damgard 구조를 사용하여 메시지를 블록으로 분할하고 반복적인 압축 처리를 수행합니다.
알고리즘 처리는 4가지 부분으로 나뉩니다.
1. 패딩: 메시지 길이가 512비트의 배수가 되도록 메시지를 패딩합니다.
2. 압축: 블록을 256비트 메시지 요약으로 처리합니다.
3. 반복: 모든 블록이 압축될 때까지 각 메시지 블록을 반복적으로 처리합니다.
4. 출력: 최종 256비트 다이제스트를 생성합니다.
2. PHP 구현
1. 패딩
메시지 길이가 512비트의 배수가 되도록 PHP에서 패딩 기능을 구현합니다.
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비트 메시지 블록을 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); }
}
함수 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. Iteration
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
D9E8B7F5D6A5B9 6D011A7B19A1456";
$output = SM3($input);
var_dump($output = = = $expected_output); // true
?>
구현이 올바른지 확인하기 위해 다른 메시지를 테스트에 사용할 수도 있습니다.
위 내용은 PHP에서 SM3 알고리즘을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!