记录一下 php解密java的问题
使用大佬的:https://github.com/lpilp/phpsm2sm3sm4
php版本国密
意见问题:在判断椭圆点的时候x,y报错。
发现java部分的问题在于
/***分解加密字串
* (C1 = C1标志位2位 + C1实体部分128位 = 130)
* (C3 = C3实体部分64位 = 64)
* (C2 = encryptedData.length * 2 - C1长度 - C2长度)
*/
if (data == null || data.length == 0)
{
return null;
}
byte[] source = new byte[data.length];
System.arraycopy(data, 0, source, 0, data.length);
Cipher cipher = new Cipher();
SM2 sm2 = SM2.Instance();
ECPoint userKey = sm2.ecc_curve.decodePoint(Util.hexToByte(pubk));
ECPoint c1 = cipher.Init_enc(sm2, userKey);
cipher.Encrypt(source);
byte[] c3 = new byte[32];
cipher.Dofinal(c3);
//C1 C2 C3拼装成加密字串
//使用BC库/也有可能是Hutool工具库进行sm2加密后的密文,前两位也是04标志位,而其进行解密的时候也必须有该标志位。
return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(source) + Util.byteToHex(c3);
java解密重要代码
byte[] c1Bytes = Util.hexToByte(data.substring(0,130));
int c2Len = encryptedData.length - 97;
byte[] c2 = Util.hexToByte(data.substring(130,130 + 2 * c2Len));
byte[] c3 = Util.hexToByte(data.substring(130 + 2 * c2Len,194 + 2 * c2Len));
SM2 sm2 = SM2.Instance();
BigInteger userD = new BigInteger(1, privateKey);
//通过C1实体字节来生成ECPoint
ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
Cipher cipher = new Cipher();
cipher.Init_dec(userD, c1);
cipher.Decrypt(c2);
cipher.Dofinal(c3);
因为bc库自带的标志位,经过发现咋计算检查椭圆点的时候,位数对不上了,找不到,就报错了,截取掉04(解密里面根据trim来控制,默认就好)
public function doDecrypt($encryptData, $privateKey, $trim = true, $model = C1C3C2)
{
// $encryptData = $c1.$c3.$c2
if (substr($encryptData, 0, 2) == '04' && $trim) {
$encryptData = substr($encryptData, 2);
}
if (strlen($privateKey) == 66 && substr($privateKey, 0, 2) == '00') {
$privateKey = substr($privateKey, 2); // 个别的key 前面带着00
}
$c1 = substr($encryptData, 0, 128);
$c3 = substr($encryptData, -64);
$c2 = substr($encryptData, 128, strlen($encryptData) - 128 - 64);
$encryptData = $c1 . $c3 . $c2;
$adapter = $this->adapter;
$generator = $this->generator;
$this->cipher = new \Rtgm\smecc\SM2\Cipher();
$c1X = substr($encryptData, 0, 64);
$c1Y = substr($encryptData, strlen($c1X), 64);
$c1Length = strlen($c1X) + strlen($c1Y);
if ($model == C1C3C2) {
$c3 = substr($encryptData, $c1Length, 64);
$c2 = substr($encryptData, $c1Length + strlen($c3));
} else {
$c3 = substr($encryptData, -64);
$c2 = substr($encryptData, $c1Length, strlen($encryptData) - $c1Length - 64);
}
$p1 = new Point($adapter, $generator->getCurve(), gmp_init($c1X, 16), gmp_init($c1Y, 16));
$this->cipher->initDecipher($p1, $privateKey);
$arrMsg = Hex2ByteBuf::HexStringToByteArray2($c2);
$arrMsg = $this->cipher->decryptBlock($arrMsg);
$document = hex2bin(Hex2ByteBuf::ByteArrayToHexString($arrMsg));
$c3_ = strtolower(Hex2ByteBuf::ByteArrayToHexString($this->cipher->Dofinal()));
$c3 = strtolower($c3);
if ($c3 == $c3_) { //hash签名相同,
return $document;
} else {
return '';
}
}