Giter VIP home page Giter VIP logo

Comments (9)

KingAckerman avatar KingAckerman commented on August 14, 2024

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));
}

}

from phpsm2sm3sm4.

lpilp avatar lpilp commented on August 14, 2024

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

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

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

from phpsm2sm3sm4.

KingAckerman avatar KingAckerman commented on August 14, 2024

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

from phpsm2sm3sm4.

lpilp avatar lpilp commented on August 14, 2024

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

from phpsm2sm3sm4.

KingAckerman avatar KingAckerman commented on August 14, 2024

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

from phpsm2sm3sm4.

lpilp avatar lpilp commented on August 14, 2024
<?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的参数是否使用正确

from phpsm2sm3sm4.

KingAckerman avatar KingAckerman commented on August 14, 2024

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

from phpsm2sm3sm4.

lpilp avatar lpilp commented on August 14, 2024
$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 就可以了

from phpsm2sm3sm4.

KingAckerman avatar KingAckerman commented on August 14, 2024

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

from phpsm2sm3sm4.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.