Home  >  Article  >  Backend Development  >  How to implement SM3 algorithm in PHP

How to implement SM3 algorithm in PHP

PHPz
PHPzOriginal
2023-04-26 10:30:43882browse

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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn