Home > Article > Backend Development > How to implement SM3 algorithm in PHP
The SM3 algorithm is a cryptographic hash function algorithm launched by the China Computer Cryptography Research Center in 2010. It is known as a very important algorithm in national secrets. In this article, we will introduce how to implement the SM3 algorithm in PHP.
1. Introduction to the algorithm
SM3 algorithm is a cryptographic hash function algorithm. A cryptographic hash function accepts data of any size as input and converts it into a fixed-length output, and the output value is different for different input values. The password hash function has the following characteristics:
1. Fixed length: The output length of the password hash function should be fixed, usually 128, 160, 192, 224 or 256 bits.
2. Irreversibility: Given a hash output, its input cannot be determined, which is called a one-way hash function.
3. Strong resistance: Given a hash value, it is impossible to find any input with the same hash value, while changing only a single or limited number of bits in the input means producing a different input than the original output.
The SM3 algorithm uses the Merkle-Damgard structure to split the message into blocks and perform iterative compression processing.
Algorithm processing is divided into 4 parts:
1. Padding: Pad the message to ensure that its length is a multiple of 512 bits.
2. Compression: Process blocks into 256-bit message digests.
3. Iteration: Process each message block iteratively until all blocks are compressed.
4. Output: Generate the final 256-bit digest.
2. PHP implementation
1. Padding
Implement the padding function in PHP to ensure that the message length is a multiple of 512 bits.
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. Compression
Implement the compression function in PHP to process 512-bit message blocks A 256-bit message digest.
function CF($X, $Y, $Z) {
return ($X & $Y) | (~$X & $Z);
}
function MG($X, $Y, $Z) {
return ($X & $Y) | ($X & $Z) | ($Y & $Z);
}
function P0($X) {
return $X ^ (($X << 9) | ($X >> 23)) ^ (($X << 17) | ($X >> 15));
}
function P1($X) {
return $X ^ (($X << 15) | ($X >> 17)) ^ (($X << 23) | ($X >> 9));
}
function 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. Iteration
Implement the iteration function in PHP and process each message block iteratively until all blocks are compressed.
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. Algorithm testing
In order to verify whether our implementation is correct, we can use GM/ T 0004-2012 Cryptographic Hash Algorithm Test.
require_once "sm3.php";
$input = "abc";
$expected_output = "66C7F0FAD8E2DDDB2D0A6EEA2E2ECEB4E83441BEC4C3056BFCDC6F7E9
D9E8B7F5D6A5B96D011A7B 19A1456";
$output = SM3($input);
var_dump($output === $expected_output); // true
?>
We can also use other messages to test and verify our Is the implementation correct?
The above is the detailed content of How to implement SM3 algorithm in PHP. For more information, please follow other related articles on the PHP Chinese website!