lpilp / phpsm2sm3sm4

php版本,支持国密SM2的签名算法,非对称加解密,SM3的hash, SM4的对称加解密
329 stars 76 forks source link

Java 加密使用的是SM3withSm2,php生成签名验签不通过 #76

Closed KingAckerman closed 6 months ago

KingAckerman commented 6 months ago

$private_key='MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg37rIi67OU7RSz7gA4JkN3bV6TlnYAcbUfN58CsLhBwSgCgYIKoEcz1UBgi2hRANxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; $public_key='MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAENSXl+ohNQcCJ2H1tp7KKJjBnUM+f0sNQA4HaSMxRt/x7G1j5r0M58zON9GT74CjLWws4+xBxcPq8F7mBl0meCQ==';

$data = [ 'data' => 'eyJtZXJjaGFudF9ubyI6IjE1MDAwMDIwMjIwNTEzMDEiLCJ3aWRnZXRfY29udGVudCI6IntcIm1lcmNoYW50X25vXCI6XCIxNTAwMDAyMDIyMDUxMzAxXCIsXCJtZXJjaGFudF9vcmRlcl9ub1wiOlwiMjAyNDA2MDVfMDg1NTI3XCIsXCJhbW91bnRcIjoxLFwid2lkZ2V0X3BhcmFtXCI6e1wiYnVzaW5lc3NOb1wiOlwiMjAyNDA2MDVfMDg1NTI3XCIsXCJyZWdDb2RlXCI6XCIxNTAyOTVcIixcImJ1c2luZXNzVHlwZVwiOlwiMDAxXCIsXCJhZ2VuY3lDb2RlXCI6XCIyMTQwMDFcIixcImRhdGVcIjpcIjIwMjQtMDYtMDUgMDg6NTU6MjhcIixcInBheWVyTmFtZVwiOlwibGljXCIsXCJwYXllZUFjY0Fzc2lnblR5cGVcIjpcIjFcIixcInRvdGFsQW10XCI6MSxcImF1dGhvclwiOlwiQUJDXCIsXCJwbGFjZUNvZGVcIjpcIjAwMVwiLFwiYmlsbENvZGVcIjpcIjAwMDRcIixcIml0ZW1EZXRhaWxzXCI6W3tcIml0ZW1Db2RlXCI6XCIxMDMwNDI3ODlcIixcIml0ZW1OYW1lXCI6XCLmiJDkurrmlZnogrLlrabotLlcIixcInVuaXRcIjpcIuS6ui/mrKFcIixcIm51bWJlclwiOjEsXCJzdGRcIjoxLFwiYW10XCI6MX1dfSxcInN1YmplY3RcIjpcIua1i+ivleWVhuWTgVwiLFwiYm9keVwiOlwi5LiL5Y2V5rWL6K+VXCIsXCJkZXZpY2VfdHlwZVwiOlwicGNcIixcImVmZmVjdGl2ZV90aW1lXCI6XCIxZFwiLFwidmVyc2lvbl9ub1wiOlwiMS4xXCJ9IiwiZnJvbnRfdXJsIjoiaHR0cDovL3d3dy5iYWlkdS5jb20vIiwiYmFja191cmwiOiJodHRwOi8vd3d3LmJhaWR1LmNvbS8iLCJlYmlsbF9pbmZvIjp7ImJhY2tfdXJsIjoiaHR0cDovL3d3dy5iYWlkdS5jb20vIiwiYnVzTm8iOiIxNTAyOTUwMDAwMSIsInBheWVyIjoibGljIiwicGF5ZXJUeXBlIjoiMSIsImJ1c0RhdGVUaW1lIjoiMjAyNDA2MDMxNzM5MDAxIiwicGF5ZWUiOiJBQkMiLCJhdXRob3IiOiJBQkMiLCJ0b3RhbEFtdCI6IjAuMDEiLCJjaGFyZ2VEZXRhaWwiOlt7ImNoYXJnZUNvZGUiOiIxMDMwNDI3ODkiLCJjaGFyZ2VOYW1lIjoi5oiQ5Lq65pWZ6IKy5a2m6LS5Iiwic3RkIjowLjAxLCJudW1iZXIiOjEsImFtdCI6MC4wMX1dfX0=', 'method' => 'CreateOrder', 'appid' => 'BTDDXWXT', 'noise' => 'd9667f81-8068-4bee-9def-dc8f7cc00202', 'version' => 'V1.0', ]; //java生成的sign $sign = 'MEUCIFTiSS5ySk7RBPspGkSfHFh+5lP+4Gj9t6hhZPWHz9L5AiEA8a3+BNPgQ0RHMLxrXL3bqvhDX6HEwrEehcnXzdQImuk=';

//php生成的签名一直验签不通过。签名规则是将data中数组正序排序,然后然后用&拼接 //签名示例 $stringA="appid=app1&data=ewogI&method=query&noise=ibuaiVcKd pRxkhJA&version=V1.0"; $sign = createSign($stringA);

KingAckerman commented 6 months ago

java签名类 // // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) //

package com.nmgjc.dwzj.sdk.util.sign;

import com.alipay.api.internal.util.codec.Base64; import com.nmgjc.dwzj.sdk.exception.BusinessException; import com.nmgjc.dwzj.sdk.model.CheckSignParam; import com.nmgjc.dwzj.sdk.model.CommReq; import com.nmgjc.dwzj.sdk.model.CommRsp; import com.nmgjc.dwzj.sdk.model.SignParam; import com.nmgjc.dwzj.sdk.util.sign.inter.ISign; import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.spec.ECGenParameterSpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

public class GM2Util implements ISign { private static final Logger LOGGER = LoggerFactory.getLogger(GM2Util.class); private static final BouncyCastleProvider bc = new BouncyCastleProvider(); private static final String KEY_ALGORITHM = "EC"; private static final String SIGNATURE_ALGORITHM = "SM3withSm2";

public GM2Util() {
}

public String sign(CommReq reqData) {
    String srcData = reqData.getSrcSignData();
    LOGGER.info("srcData:" + srcData);
    return sign(srcData.getBytes(StandardCharsets.UTF_8), reqData.getKey());
}

public String getSign(SignParam signParam) {
    String srcData = signParam.getSrcSignData();
    LOGGER.info("srcData:" + srcData);
    return sign(srcData.getBytes(StandardCharsets.UTF_8), signParam.getKey());
}

public boolean checkSign(CheckSignParam checkSignParam) {
    String srcData = checkSignParam.getSrcSignData();
    LOGGER.info("srcData:" + srcData);
    return verify(srcData.getBytes(StandardCharsets.UTF_8), checkSignParam.getPubKey(), checkSignParam.getSign());
}

public boolean check(CommReq reqData, CommRsp rspData) {
    String srcData = rspData.getSrcSignData(reqData.getVersion());
    LOGGER.info("srcData:" + srcData);
    return verify(srcData.getBytes(StandardCharsets.UTF_8), reqData.getPubKey(), rspData.getSign());
}

private static String sign(byte[] data, String privateKeyStr) {
    try {
        byte[] keyBytes = Base64.decodeBase64(privateKeyStr.getBytes(StandardCharsets.UTF_8));
        KeyFactory keyFactory = KeyFactory.getInstance("EC", bc);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance("SM3withSm2", bc);
        signature.initSign(priKey);
        signature.update(data);
        return Base64.encodeBase64String(signature.sign());
    } catch (Exception var7) {
        LOGGER.error("sign异常", var7);
        return null;
    }
}

private static boolean verify(byte[] data, String publicKeyStr, String sign) {
    try {
        byte[] keyBytes = Base64.decodeBase64(publicKeyStr.getBytes(StandardCharsets.UTF_8));
        KeyFactory keyFactory = KeyFactory.getInstance("EC", bc);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance("SM3withSm2", bc);
        signature.initVerify(pubKey);
        signature.update(data);
        return signature.verify(Base64.decodeBase64(sign.getBytes(StandardCharsets.UTF_8)));
    } catch (Exception var8) {
        LOGGER.error("verify异常", var8);
        return false;
    }
}

public static KeyPair generateSm2KeyPair() {
    try {
        ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
        SecureRandom random = new SecureRandom();
        kpg.initialize(sm2Spec, random);
        KeyPair keyPair = kpg.generateKeyPair();
        return keyPair;
    } catch (Exception var4) {
        var4.printStackTrace();
        throw new BusinessException("生成密钥对失败");
    }
}

public static void main(String[] args) throws Exception {
    KeyPair keyPair = generateSm2KeyPair();
    String priPath = Base64.encodeBase64String(keyPair.getPrivate().getEncoded());
    String pubPath = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
    String data = "123213";
    String sign = sign(data.getBytes(), priPath);
    LOGGER.info(sign);
    boolean verify = verify(data.getBytes(), pubPath, sign);
    LOGGER.info(String.valueOf(verify));
}

}

lpilp commented 6 months ago

你这签名的公钥是是pkcs封装过的,需要解开为明文,解开后为: 043525E5FA884D41C089D87D6DA7B28A26306750CF9FD2C3500381DA48CC51B7FC7B1B58F9AF4339F3338DF464FBE028CB5B0B38FB107170FABC17B98197499E09
或者 把它存成 .pem文件格式的文件,有一个函数是去读密码文件的

你用这个去明文签名试试对方认不认

PS: 我把你的私钥隐去一部分了,如果是正式的放网上就不好了,能更新的话就换一个新的,如果只是测试用的,请忽略

KingAckerman commented 6 months ago

用这个明文签名去试了,验签失败

lpilp commented 6 months ago

哦,那你用 字符串为你例子中: ”appid=app1&data=ewogI&method=query&noise=ibuaiVcKdpRxkhJA&version=V1.0“ 分别用PHp与JAVA 签名一次,我看一下签名完的结果

KingAckerman commented 6 months ago

java: {"data":"eyJtZXJjaGFudF9ubyI6IjE1MDAwMDIwMjQwNTMwMDEiLCJ3aWRnZXRfY29udGVudCI6IntcIm1lcmNoYW50X25vXCI6XCIxNTAwMDAyMDI0MDUzMDAxXCIsXCJtZXJjaGFudF9vcmRlcl9ub1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJhbW91bnRcIjoxLFwid2lkZ2V0X3BhcmFtXCI6e1wiYnVzaW5lc3NOb1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJyZWdDb2RlXCI6XCIxNTAyOTVcIixcImJ1c2luZXNzVHlwZVwiOlwiMDAxXCIsXCJhZ2VuY3lDb2RlXCI6XCIyMTQwMDFcIixcImRhdGVcIjpcIjIwMjQtMDYtMDVcIixcInBheWVyTmFtZVwiOlwibGljXCIsXCJwYXllclRlbFwiOlwiMTMzODQ4ODIwNTJcIixcInBheWVlQWNjQXNzaWduVHlwZVwiOlwiMVwiLFwidG90YWxBbXRcIjoxLFwiYXV0aG9yXCI6XCJBQkNcIixcInBsYWNlQ29kZVwiOlwiMDAxXCIsXCJiaWxsQ29kZVwiOlwiMDAwNFwiLFwiaXRlbURldGFpbHNcIjpbe1wiaXRlbUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiaXRlbU5hbWVcIjpcIuaIkOS6uuaVmeiCsuWtpui0uVwiLFwidW5pdFwiOlwi5Lq6L+asoVwiLFwibnVtYmVyXCI6MSxcInN0ZFwiOjEsXCJhbXRcIjoxfV19LFwic3ViamVjdFwiOlwi5rWL6K+V5ZWG5ZOBXCIsXCJib2R5XCI6XCLkuIvljZXmtYvor5VcIixcImRldmljZV90eXBlXCI6XCJwY1wiLFwiZWZmZWN0aXZlX3RpbWVcIjpcIjFkXCIsXCJ2ZXJzaW9uX25vXCI6XCIxLjFcIn0iLCJiYWNrX3VybCI6Imh0dHA6Ly96aHVvZmFuLnBpY3AuaW8vcGF5bWVudC92Mi93d3cvaW5kZXgucGhwL29yZGVyL29yZGVyTm90aWZ5IiwiZWJpbGxfaW5mbyI6IntcImJhY2tfdXJsXCI6XCJodHRwOi8vd3d3LmJhaWR1LmNvbS9cIixcImJ1c05vXCI6XCIxNTAyOTUwMDAwMlwiLFwicGF5ZXJcIjpcImxpY1wiLFwicGF5ZXJUeXBlXCI6XCIxXCIsXCJjYXJkVHlwZVwiOlwiXCIsXCJjcmVkaXRDb2RlXCI6XCJcIixcImJ1c0RhdGVUaW1lXCI6XCIyMDI0MDYwMzE3MzkwMTAwMVwiLFwicmV2aWV3ZXJcIjpcIlwiLFwicGF5ZWVcIjpcIkFCQ1wiLFwiYXV0aG9yXCI6XCJBQkNcIixcInRvdGFsQW10XCI6MC4wMSxcInJlbWFya1wiOlwiXCIsXCJ0ZWxcIjpcIlwiLFwiZW1haWxcIjpcIlwiLFwiaWRDYXJkTm9cIjpcIlwiLFwiY2hhcmdlRGV0YWlsXCI6W3tcImNoYXJnZUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiY2hhcmdlTmFtZVwiOlwi5oiQ5Lq65pWZ6IKy5a2m6LS5XCIsXCJpdGVtU3RkQ29kZVwiOlwiXCIsXCJ1bml0XCI6XCLkurov5qyhXCIsXCJzdGRcIjowLjAxLFwibnVtYmVyXCI6MSxcImFtdFwiOjAuMDEsXCJyZW1hcmtcIjpcIua1i+ivlVwifV19In0=","method":"query","appid":"app1","noise":"ibuaiVcKdpRxkhJA","sign":"MEUCIQDJLdeHuN8Ef/0Q7xLPpDr1W/WJwkoG9c9WQ9N9OLuF3wIgE98oDSq96auYbwTPi0X51vGXFLiTPOxfs9GPI1SnqFg=","version":"V1.0"}

php: {"data":"eyJtZXJjaGFudF9ubyI6IjE1MDAwMDIwMjQwNTMwMDEiLCJ3aWRnZXRfY29udGVudCI6IntcIm1lcmNoYW50X25vXCI6XCIxNTAwMDAyMDI0MDUzMDAxXCIsXCJtZXJjaGFudF9vcmRlcl9ub1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJhbW91bnRcIjoxLFwid2lkZ2V0X3BhcmFtXCI6e1wiYnVzaW5lc3NOb1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJyZWdDb2RlXCI6XCIxNTAyOTVcIixcImJ1c2luZXNzVHlwZVwiOlwiMDAxXCIsXCJhZ2VuY3lDb2RlXCI6XCIyMTQwMDFcIixcImRhdGVcIjpcIjIwMjQtMDYtMDVcIixcInBheWVyTmFtZVwiOlwibGljXCIsXCJwYXllclRlbFwiOlwiMTMzODQ4ODIwNTJcIixcInBheWVlQWNjQXNzaWduVHlwZVwiOlwiMVwiLFwidG90YWxBbXRcIjoxLFwiYXV0aG9yXCI6XCJBQkNcIixcInBsYWNlQ29kZVwiOlwiMDAxXCIsXCJiaWxsQ29kZVwiOlwiMDAwNFwiLFwiaXRlbURldGFpbHNcIjpbe1wiaXRlbUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiaXRlbU5hbWVcIjpcIuaIkOS6uuaVmeiCsuWtpui0uVwiLFwidW5pdFwiOlwi5Lq6L+asoVwiLFwibnVtYmVyXCI6MSxcInN0ZFwiOjEsXCJhbXRcIjoxfV19LFwic3ViamVjdFwiOlwi5rWL6K+V5ZWG5ZOBXCIsXCJib2R5XCI6XCLkuIvljZXmtYvor5VcIixcImRldmljZV90eXBlXCI6XCJwY1wiLFwiZWZmZWN0aXZlX3RpbWVcIjpcIjFkXCIsXCJ2ZXJzaW9uX25vXCI6XCIxLjFcIn0iLCJiYWNrX3VybCI6Imh0dHA6Ly96aHVvZmFuLnBpY3AuaW8vcGF5bWVudC92Mi93d3cvaW5kZXgucGhwL29yZGVyL29yZGVyTm90aWZ5IiwiZWJpbGxfaW5mbyI6IntcImJhY2tfdXJsXCI6XCJodHRwOi8vd3d3LmJhaWR1LmNvbS9cIixcImJ1c05vXCI6XCIxNTAyOTUwMDAwMlwiLFwicGF5ZXJcIjpcImxpY1wiLFwicGF5ZXJUeXBlXCI6XCIxXCIsXCJjYXJkVHlwZVwiOlwiXCIsXCJjcmVkaXRDb2RlXCI6XCJcIixcImJ1c0RhdGVUaW1lXCI6XCIyMDI0MDYwMzE3MzkwMTAwMVwiLFwicmV2aWV3ZXJcIjpcIlwiLFwicGF5ZWVcIjpcIkFCQ1wiLFwiYXV0aG9yXCI6XCJBQkNcIixcInRvdGFsQW10XCI6MC4wMSxcInJlbWFya1wiOlwiXCIsXCJ0ZWxcIjpcIlwiLFwiZW1haWxcIjpcIlwiLFwiaWRDYXJkTm9cIjpcIlwiLFwiY2hhcmdlRGV0YWlsXCI6W3tcImNoYXJnZUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiY2hhcmdlTmFtZVwiOlwi5oiQ5Lq65pWZ6IKy5a2m6LS5XCIsXCJpdGVtU3RkQ29kZVwiOlwiXCIsXCJ1bml0XCI6XCLkurov5qyhXCIsXCJzdGRcIjowLjAxLFwibnVtYmVyXCI6MSxcImFtdFwiOjAuMDEsXCJyZW1hcmtcIjpcIua1i+ivlVwifV19In0=","method":"query","appid":"app1","noise":"ibuaiVcKdpRxkhJA","version":"V1.0","sign":"MEYCIQDxoQeo778i8fg7ZJHVC5TwrsC\/onyodbeIgl2DvfzGhQIhAJBYJ9l18KaBnmQBGHo4sc6yuegJGLNmF5Xwk5sTyve8"}

php签名用的公钥是:043525E5FA884D41C089D87D6DA7B28A26306750CF9FD2C3500381DA48CC51B7FC7B1B58F9AF4339F3338DF464FBE028CB5B0B38FB107170FABC17B98197499E09

lpilp commented 6 months ago
<?php
require_once '../vendor/autoload.php';
use Rtgm\sm\RtSm2;
$publicKey = '043525E5FA884D41C089D87D6DA7B28A26306750CF9FD2C3500381DA48CC51B7FC7B1B58F9AF4339F3338DF464FBE028CB5B0B38FB107170FABC17B98197499E09'; // 公钥
$privateKey = 'DFBAC8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxE7C0AC2E10704'; // 私钥
$userId = '1234567812345678';
$str = '{"data":"eyJtZXJjaGFudF9ubyI6IjE1MDAwMDIwMjQwNTMwMDEiLCJ3aWRnZXRfY29udGVudCI6IntcIm1lcmNoYW50X25vXCI6XCIxNTAwMDAyMDI0MDUzMDAxXCIsXCJtZXJjaGFudF9vcmRlcl9ub1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJhbW91bnRcIjoxLFwid2lkZ2V0X3BhcmFtXCI6e1wiYnVzaW5lc3NOb1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJyZWdDb2RlXCI6XCIxNTAyOTVcIixcImJ1c2luZXNzVHlwZVwiOlwiMDAxXCIsXCJhZ2VuY3lDb2RlXCI6XCIyMTQwMDFcIixcImRhdGVcIjpcIjIwMjQtMDYtMDVcIixcInBheWVyTmFtZVwiOlwibGljXCIsXCJwYXllclRlbFwiOlwiMTMzODQ4ODIwNTJcIixcInBheWVlQWNjQXNzaWduVHlwZVwiOlwiMVwiLFwidG90YWxBbXRcIjoxLFwiYXV0aG9yXCI6XCJBQkNcIixcInBsYWNlQ29kZVwiOlwiMDAxXCIsXCJiaWxsQ29kZVwiOlwiMDAwNFwiLFwiaXRlbURldGFpbHNcIjpbe1wiaXRlbUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiaXRlbU5hbWVcIjpcIuaIkOS6uuaVmeiCsuWtpui0uVwiLFwidW5pdFwiOlwi5Lq6L+asoVwiLFwibnVtYmVyXCI6MSxcInN0ZFwiOjEsXCJhbXRcIjoxfV19LFwic3ViamVjdFwiOlwi5rWL6K+V5ZWG5ZOBXCIsXCJib2R5XCI6XCLkuIvljZXmtYvor5VcIixcImRldmljZV90eXBlXCI6XCJwY1wiLFwiZWZmZWN0aXZlX3RpbWVcIjpcIjFkXCIsXCJ2ZXJzaW9uX25vXCI6XCIxLjFcIn0iLCJiYWNrX3VybCI6Imh0dHA6Ly96aHVvZmFuLnBpY3AuaW8vcGF5bWVudC92Mi93d3cvaW5kZXgucGhwL29yZGVyL29yZGVyTm90aWZ5IiwiZWJpbGxfaW5mbyI6IntcImJhY2tfdXJsXCI6XCJodHRwOi8vd3d3LmJhaWR1LmNvbS9cIixcImJ1c05vXCI6XCIxNTAyOTUwMDAwMlwiLFwicGF5ZXJcIjpcImxpY1wiLFwicGF5ZXJUeXBlXCI6XCIxXCIsXCJjYXJkVHlwZVwiOlwiXCIsXCJjcmVkaXRDb2RlXCI6XCJcIixcImJ1c0RhdGVUaW1lXCI6XCIyMDI0MDYwMzE3MzkwMTAwMVwiLFwicmV2aWV3ZXJcIjpcIlwiLFwicGF5ZWVcIjpcIkFCQ1wiLFwiYXV0aG9yXCI6XCJBQkNcIixcInRvdGFsQW10XCI6MC4wMSxcInJlbWFya1wiOlwiXCIsXCJ0ZWxcIjpcIlwiLFwiZW1haWxcIjpcIlwiLFwiaWRDYXJkTm9cIjpcIlwiLFwiY2hhcmdlRGV0YWlsXCI6W3tcImNoYXJnZUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiY2hhcmdlTmFtZVwiOlwi5oiQ5Lq65pWZ6IKy5a2m6LS5XCIsXCJpdGVtU3RkQ29kZVwiOlwiXCIsXCJ1bml0XCI6XCLkurov5qyhXCIsXCJzdGRcIjowLjAxLFwibnVtYmVyXCI6MSxcImFtdFwiOjAuMDEsXCJyZW1hcmtcIjpcIua1i+ivlVwifV19In0=","method":"query","appid":"app1","noise":"ibuaiVcKdpRxkhJA","version":"V1.0","sign":"MEYCIQDxoQeo778i8fg7ZJHVC5TwrsC/onyodbeIgl2DvfzGhQIhAJBYJ9l18KaBnmQBGHo4sc6yuegJGLNmF5Xwk5sTyve8"}';

$json = json_decode($str,1);
$document="appid=$json[appid]&data=$json[data]&method=$json[method]&noise=$json[noise]&version=$json[version]";

//返回的签名16进制还是base64, 目前可选hex,与base64两种
// __construct($formatSign='hex', $randFixed = true) 
$sm2 = new RtSm2('base64',false);

echo "\n---------明文密钥签名---------------------------\n";
$sign = $sm2->doSign( $document, $privateKey, $userId);
print_r($sign);
var_dump($sm2->verifySign( $document, $sign, $publicKey, $userId ));
$sign = 'MEUCIQDJLdeHuN8Ef/0Q7xLPpDr1W/WJwkoG9c9WQ9N9OLuF3wIgE98oDSq96auYbwTPi0X51vGXFLiTPOxfs9GPI1SnqFg=';
echo "\n---------验证java---------------------------\n";
var_dump($sm2->verifySign( $document, $sign, $publicKey, $userId )); // true
$sign = 'MEYCIQDxoQeo778i8fg7ZJHVC5TwrsC/onyodbeIgl2DvfzGhQIhAJBYJ9l18KaBnmQBGHo4sc6yuegJGLNmF5Xwk5sTyve8';
echo "\n---------验证 PHP---------------------------\n";
var_dump($sm2->verifySign( $document, $sign, $publicKey, $userId )); // false

用你的数据测试了下,验证了三次,1 次是程序生成,验证 true, 2是用给的java签名验证也通过,3 用给的PHP生成的验证 不通过, 说明你使用PHP代码时出错了, 可能性有二, 1 使用的私钥不正确,代码显示了你那个公钥对应的私钥的一部分,请确认你用的私钥(该私钥从最开始的给的base64的私钥里解出来的明文) 2 中间有一个userId的参数是否使用正确

KingAckerman commented 6 months ago

大佬,能不能把如何获得公私玥明文的方式给一下?

lpilp commented 6 months ago
$private = '私钥的base64的值xxxxxxxxxxxxxxxxxxxx';
$private = "-----BEGIN EC PRIVATE KEY-----\n".chunk_split($private,64,"\n")."-----END EC PRIVATE KEY-----";
file_put_contents('private.pem',$private);
openssl ec -in private.pem -noout -text

如果你有私钥文件的话,直接 openssl ec -in private.pem -noout -text 就可以了

KingAckerman commented 6 months ago

解出私钥的明文后验签就可以了,感谢大佬