记录一下 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 '';
        }
    }
posted @ 2023-01-09 17:06  尘梦  阅读(322)  评论(0编辑  收藏  举报