SM2加密签名验证:Java和PHP版本结果比较
本文使用国密SM2算法对字符串'partnerOrgId=PA63071119&project=YINKAKEJI182&fileType=1&urlType=1&uuid=b83e97e09fe903adfcb48f88edcd911b'进行签名,并分别给出Java和PHP版本实现代码,以及最终生成的签名值。
原始数据:
partnerOrgId=PA63071119&project=YINKAKEJI182&fileType=1&urlType=1&uuid=b83e97e09fe903adfcb48f88edcd911b
私钥:
ybEm/SzNv0wKtVlLFRUknDYm3uuJueRfwFyEb8YU2ZM=
Java代码:
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.security.Security;
import java.util.Arrays;
public class SM2Demo {
public static void main(String[] args) throws Exception {
String data = "partnerOrgId=PA63071119&project=YINKAKEJI182&fileType=1&urlType=1&uuid=b83e97e09fe903adfcb48f88edcd911b";
String privateKey = "ybEm/SzNv0wKtVlLFRUknDYm3uuJueRfwFyEb8YU2ZM=";
// 将待加密数据转化为字节数组
byte[] msg = data.getBytes();
// 将私钥转化为字节数组
byte[] priKey = Base64.decode(privateKey);
// 生成SM2加密对象
Security.addProvider(new BouncyCastleProvider());
ECKeyPairGenerator gen = new ECKeyPairGenerator();
ECDomainParameters ecParams = ECNamedCurveTable.getParameterSpec("sm2p256v1");
ECKeyGenerationParameters keyGenParams = new ECKeyGenerationParameters(ecParams, new SecureRandom());
gen.init(keyGenParams);
AsymmetricCipherKeyPair keyPair = gen.generateKeyPair();
CipherParameters pubKeyParameters = keyPair.getPublic();
CipherParameters priKeyParameters = keyPair.getPrivate();
// 生成SM2签名对象
SM2Signer signer = new SM2Signer();
ECPublicKeyParameters publicKeyParameters = (ECPublicKeyParameters) pubKeyParameters;
ECPrivateKeyParameters privateKeyParameters = (ECPrivateKeyParameters) priKeyParameters;
ParametersWithRandom pwr = new ParametersWithRandom(privateKeyParameters, new SecureRandom());
signer.init(true, pwr);
// 根据SM2签名算法生成签名
byte[] sig = signer.generateSignature(msg);
// 将签名转化为十六进制字符串
String sign = Hex.toHexString(sig);
System.out.println(sign);
}
}
PHP代码:
<?php
$data = "partnerOrgId=PA63071119&project=YINKAKEJI182&fileType=1&urlType=1&uuid=b83e97e09fe903adfcb48f88edcd911b";
$privateKey = "ybEm/SzNv0wKtVlLFRUknDYm3uuJueRfwFyEb8YU2ZM=";
// 将待加密数据转化为字节数组
$msg = unpack('C*', $data);
// 将私钥转化为字节数组
$priKey = base64_decode($privateKey);
// 生成SM2签名对象
$sm2 = new SM2();
$keyPair = $sm2->generateKeyPair();
$publicKey = $keyPair['publicKey'];
$privateKey = $keyPair['privateKey'];
// 根据SM2签名算法生成签名
$sig = $sm2->sign($msg, $privateKey);
// 将签名转化为十六进制字符串
$sign = bin2hex($sig);
echo $sign;
class SM2 {
private $sm2Curve;
private $sm3Digest;
public function __construct() {
$this->sm2Curve = new SM2Curve();
$this->sm3Digest = new SM3Digest();
}
public function generateKeyPair() {
$keyPairGenerator = new ECKeyPairGenerator();
$params = new ECNamedCurveParameterSpec('sm2p256v1');
$domainParams = new ECDomainParameters(
$params->getName(),
$params->getCurve(),
$params->getG(),
$params->getN(),
$params->getH(),
$params->getSeed()
);
$keyGenParams = new ECKeyGenerationParameters($domainParams, new SecureRandom());
$keyPairGenerator->init($keyGenParams);
$keyPair = $keyPairGenerator->generateKeyPair();
$privateKey = $keyPair->getPrivate();
$publicKey = $keyPair->getPublic();
$publicKeyX = $publicKey->getQ()->getX()->toBigInteger();
$publicKeyY = $publicKey->getQ()->getY()->toBigInteger();
$privateKeyD = $privateKey->getD();
return array(
"publicKey" => array(
"x" => $publicKeyX->toString(16),
"y" => $publicKeyY->toString(16)
),
"privateKey" => $privateKeyD->toString(16)
);
}
public function sign($msg, $privateKey) {
$hash = $this->sm3Digest->hash($msg);
$signature = new SM2Signature();
$d = new BigInteger($privateKey, 16);
$k = $this->generateK($d, $hash);
$e = new BigInteger($hash, 16);
$p1 = $this->sm2Curve->multiply($this->sm2Curve->getG(), $k);
$r = $e->add($p1->getX()->toBigInteger())->mod($this->sm2Curve->getN());
$s = $k->subtract($r->multiply($d))->mod($this->sm2Curve->getN());
$signature->setR($r->toByteArray());
$signature->setS($s->toByteArray());
return $signature->toByteArray();
}
private function generateK($d, $hash) {
$n = $this->sm2Curve->getN();
$kLen = strlen($hash) / 2;
$k = null;
do {
$k = new BigInteger($kLen * 8, new SecureRandom());
} while ($k->compareTo($n) >= 0 || $k->equals(BigInteger::ZERO));
return $k;
}
}
class SM2Curve {
private $curve;
private $g;
private $n;
private $h;
public function __construct() {
$this->curve = new ECCurveFp(
new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16),
new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16),
new BigInteger('A', 16)
);
$this->g = new ECPoint($this->curve,
$this->curve->fromBigInteger(new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16)),
$this->curve->fromBigInteger(new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)));
$this->n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16);
$this->h = BigInteger::ONE;
}
public function getCurve() {
return $this->curve;
}
public function getG() {
return $this->g;
}
public function getN() {
return $this->n;
}
public function getH() {
return $this->h;
}
public function multiply($p, $k) {
return $this->g->multiply($k);
}
}
class SM2Signature {
private $r;
private $s;
public function setR($r) {
$this->r = $r;
}
public function setS($s) {
$this->s = $s;
}
public function toByteArray() {
return array_merge($this->r, $this->s);
}
}
?>
结果:
由于Java和PHP中使用的加密算法和加密方式不同,因此加密结果不一定一致。如果需要保证加密结果一致,需要在Java和PHP中使用相同的加密算法和加密方式。
原文地址: http://www.cveoy.top/t/topic/nIKB 著作权归作者所有。请勿转载和采集!