.gitignore000064400000000062146412216570006542 0ustar00/vendor .idea .vscode .svn .DS_Store composer.lockREADME.md000064400000001637146412216570006042 0ustar00## php国密SM3签名算法 ### 安装 ```shell composer require lizhichao/one-sm ``` ### 使用 ```php sign('abc') . PHP_EOL; echo $sm3->sign(str_repeat("adfas哈哈哈", 100)) . PHP_EOL; // 文件签名 echo $sm3->signFile(__FILE__) . PHP_EOL; ``` ### 性能测试 和 [openssl](https://github.com/openssl/openssl) , [SM3-PHP](https://github.com/DongyunLee/SM3-PHP) 性能测试 ```shell php bench.php ``` 结果 ``` openssl:4901d7181a1024b8c0f59b8d3c5c6d96b4b707ad10e8ebc8ece5dc49364a3067 one-sm3:4901d7181a1024b8c0f59b8d3c5c6d96b4b707ad10e8ebc8ece5dc49364a3067 SM3-PHP:4901d7181a1024b8c0f59b8d3c5c6d96b4b707ad10e8ebc8ece5dc49364a3067 openssl time:6.3741207122803ms one-sm3 time:8.1770420074463ms SM3-PHP time:1738.5928630829ms ``` [测试代码bench.php](https://github.com/lizhichao/sm/blob/master/bench.php)bench.php000064400000017673146412216570006362 0ustar00sign($str) . PHP_EOL; $t2 = microtime(true); echo 'SM3-PHP:' . sm3($str) . PHP_EOL; $t3 = microtime(true); echo 'openssl time:'.($t1 - $t) * 1000 . 'ms' . PHP_EOL; echo 'one-sm3 time:'.($t2 - $t1) * 1000 . 'ms' . PHP_EOL; echo 'SM3-PHP time:'.($t3 - $t2) * 1000 . 'ms' . PHP_EOL; // 文件签名 //echo \OneSm\Sm3::signFile(__FILE__) . PHP_EOL;composer.json000064400000000644146412216570007302 0ustar00{ "name": "lizhichao/one-sm", "type": "library", "description": "国密sm3", "keywords": [ "php", "sm3" ], "license": "Apache-2.0", "authors": [ { "name": "tanszhe", "email": "1018595261@qq.com" } ], "require": { "php": ">=5.6" }, "autoload": { "psr-4": { "OneSm\\": "src/" } } } src/Sm3.php000064400000007236146412216570006526 0ustar00getK($l); $bt = $this->getB($k); $str = $str . $bt . pack('J', $l); $count = strlen($str); $l = $count / $this->STR_LEN; $vr = hex2bin($this->IV); for ($i = 0; $i < $l; $i++) { $vr = $this->cf($vr, substr($str, $i * $this->STR_LEN, $this->STR_LEN)); } return bin2hex($vr); } private function getK($l) { $v = $l % $this->LEN; return $v + $this->STR_LEN < $this->LEN ? $this->LEN - $this->STR_LEN - $v - 1 : ($this->LEN * 2) - $this->STR_LEN - $v - 1; } private function getB($k) { $arg = [128]; $arg = array_merge($arg, array_fill(0, intval($k / 8), 0)); return pack('C*', ...$arg); } public function signFile($file) { $l = filesize($file) * 8; $k = $this->getK($l); $bt = $this->getB($k) . pack('J', $l); $hd = fopen($file, 'r'); $vr = hex2bin($this->IV); $str = fread($hd, $this->STR_LEN); if ($l > $this->LEN - $this->STR_LEN - 1) { do { $vr = $this->cf($vr, $str); $str = fread($hd, $this->STR_LEN); } while (!feof($hd)); } $str = $str . $bt; $count = strlen($str) * 8; $l = $count / $this->LEN; for ($i = 0; $i < $l; $i++) { $vr = $this->cf($vr, substr($str, $i * $this->STR_LEN, $this->STR_LEN)); } return bin2hex($vr); } private function t($i) { return $i < 16 ? 0x79cc4519 : 0x7a879d8a; } private function cf($ai, $bi) { $wr = array_values(unpack('N*', $bi)); for ($i = 16; $i < 68; $i++) { $wr[$i] = $this->p1($wr[$i - 16] ^ $wr[$i - 9] ^ $this->lm($wr[$i - 3], 15)) ^ $this->lm($wr[$i - 13], 7) ^ $wr[$i - 6]; } $wr1 = []; for ($i = 0; $i < 64; $i++) { $wr1[] = $wr[$i] ^ $wr[$i + 4]; } list($a, $b, $c, $d, $e, $f, $g, $h) = array_values(unpack('N*', $ai)); for ($i = 0; $i < 64; $i++) { $ss1 = $this->lm( ($this->lm($a, 12) + $e + $this->lm($this->t($i), $i % 32) & 0xffffffff), 7); $ss2 = $ss1 ^ $this->lm($a, 12); $tt1 = ($this->ff($i, $a, $b, $c) + $d + $ss2 + $wr1[$i]) & 0xffffffff; $tt2 = ($this->gg($i, $e, $f, $g) + $h + $ss1 + $wr[$i]) & 0xffffffff; $d = $c; $c = $this->lm($b, 9); $b = $a; $a = $tt1; $h = $g; $g = $this->lm($f, 19); $f = $e; $e = $this->p0($tt2); } return pack('N*', $a, $b, $c, $d, $e, $f, $g, $h) ^ $ai; } private function ff($j, $x, $y, $z) { return $j < 16 ? $x ^ $y ^ $z : ($x & $y) | ($x & $z) | ($y & $z); } private function gg($j, $x, $y, $z) { return $j < 16 ? $x ^ $y ^ $z : ($x & $y) | (~$x & $z); } private function lm($a, $n) { return ($a >> (32 - $n) | (($a << $n) & 0xffffffff)); } private function p0($x) { return $x ^ $this->lm($x, 9) ^ $this->lm($x, 17); } private function p1($x) { return $x ^ $this->lm($x, 15) ^ $this->lm($x, 23); } }test.php000064400000000371146412216570006245 0ustar00sign('abc') . PHP_EOL; echo $sm3->sign(str_repeat("adfas哈哈哈", 100)) . PHP_EOL; // 文件签名 echo $sm3->signFile(__FILE__) . PHP_EOL;