rain
2024-08-05 b912913c1a96c76cc2b43dd22e662c7d02b59c8e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package com.dji.sample.territory.utils;
 
import lombok.SneakyThrows;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
 
import java.io.File;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.security.spec.ECGenParameterSpec;
import java.util.Arrays;
 
/**
 * @PROJECT_NAME: drone
 * @DESCRIPTION:
 * @USER: aix
 * @DATE: 2024/5/9 10:09
 */
public class SM2SignUtil {
 
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
 
    @SneakyThrows
    public static ECPrivateKeyParameters getSM2PrivateKey() {
 
        String privateKeyHex = "23E57DA1E4AB865CCBC325B668762207DEF74345B782237808AE0BABDF26734D";
 
        // 获取SM2曲线的参数
        ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("sm2p256v1");
        ECDomainParameters domainParams = new ECDomainParameters(
                ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN(), ecSpec.getH(), null);
 
        // 将十六进制字符串表示的私钥转换为BigInteger
        BigInteger privateKey = new BigInteger(privateKeyHex, 16);
 
        // 创建ECPrivateKeyParameters
        return new ECPrivateKeyParameters(privateKey, domainParams);
    }
 
    public static boolean verify(byte[] dataHash, byte[] signature) {
 
        String publicKeyHex = "044D6061FC08A19D3F32CEAA8CF6679B40500008FD741FC26DE7E50AEBF3A9115D47274437730EADEDAEF0CCC4853C5F0B35B30C6AEA83A5F6FBCA4ABEAC9E3B98";
 
        // 获取SM2曲线的参数
        ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("sm2p256v1");
        ECDomainParameters domainParams = new ECDomainParameters(
                ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN(), ecSpec.getH(), null);
        // 解析十六进制公钥
        // 公钥通常是压缩或未压缩的EC点坐标的十六进制表示
        // 这里我们假设公钥是未压缩的(65字节,以04开头)
        byte[] pubKeyBytes = hexStringToByteArray(publicKeyHex);
        if (pubKeyBytes[0] != 0x04) {
            throw new IllegalArgumentException("Unsupported public key format, expecting uncompressed point (04 prefix)");
        }
        ECPoint q = ecSpec.getCurve().decodePoint(Arrays.copyOfRange(pubKeyBytes, 1, pubKeyBytes.length));
        ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(q, domainParams);
 
        // 创建SM2签名验证器
        SM2Signer verifier = new SM2Signer();
        verifier.init(false, ecPublicKeyParameters);
 
        // 更新数据哈希值
        verifier.update(dataHash, 0, dataHash.length);
 
        // 验证签名
        return verifier.verifySignature(signature);
    }
 
    // 辅助方法:将十六进制字符串转换为字节数组
    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
 
    // 使用SM2私钥对哈希值进行签名
    public static String signWithSM2(byte[] hash, ECPrivateKeyParameters sm2PrivateKey) throws Exception {
        // 创建SM2签名器
        SM2Signer signer = new SM2Signer();
        signer.init(true, sm2PrivateKey);
        // 对哈希值进行签名
        signer.update(hash, 0, hash.length);
        byte[] signature = signer.generateSignature();
 
        // 将签名转换为十六进制大写字符串
        StringBuilder hexString = new StringBuilder();
        for (byte b : signature) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString().toUpperCase();
    }
 
//    public static void main(String[] args) throws Exception {
//        // 示例哈希值(这里只是一个占位符,你应该使用实际的哈希值)
//        String hxz = String.valueOf(SM3HashExample.str(("B69200D500E57054E987FFF855204B30CE6BD32FE54937C531D6F943633A97A6"
//                + "," + "2024-06-05 10:04:16" + "," + "115.8506321" + "," + "28.6193951" + "," + "-83" + "," + "135" +
//                "," + "0" + "," + "中图智绘无人机" + "," + "23C8CCC61E3042FBA6A658F319337B1A")));
////        System.out.println("sm3 in hash: " + sm3);
////        byte[] hash = sm3.getBytes(); // 注意:使用SM3或其他哈希算法来计算数据的哈希值
//        System.out.println(hxz);
//        byte[] hash = hxz.getBytes(); // 注意:使用SM3或其他哈希算法来计算数据的哈希值
//        // 加载私钥
//        ECPrivateKeyParameters sm2PrivateKey = getSM2PrivateKey();
//        // 使用SM2私钥对哈希值进行签名
//        String signatureHex = signWithSM2(hash, sm2PrivateKey);
//        System.out.println(signatureHex);
        // 加载私钥
//        ECPrivateKeyParameters sm2PrivateKey = getSM2PrivateKey();
//
//        // 使用SM2私钥对哈希值进行签名
//        String signatureHex = signWithSM2(hash, sm2PrivateKey);
//        System.out.println("Signature in hex (uppercase): " + signatureHex);
 
//        //验证
//        // 示例数据哈希(SM3哈希值)
//        byte[] dataHash = hash; // 注意:这里仅作为示例,你需要用实际的SM3哈希值
//
//        // 示例签名(字节数组)
//        byte[] signature = signatureHex.getBytes(); // 注意:这里仅作为示例,你需要用实际的签名值
//
//        // 验证签名
//        boolean isValid = verify(dataHash, signature);
//
//        // 输出验证结果
//        System.out.println("Signature is valid: " + isValid);
 
//    }
 
}