elkers
2025-04-07 bd9808a81b1eafdc75a42c1c9904408dc888061d
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
150
151
152
153
154
155
156
157
158
159
160
161
162
package com.nanjing.water.common.util;
 
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.util.Base64Utils;
 
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.*;
 
public class SM2Util {
    /**
     * 要生成的EC域参数的标准名称
     */
    private static final String STANDARD_NAME = "sm2p256v1";
    /**
     * 算法
     */
    private static final String ALGORITHM = "EC";
    /**
     * 字符编码
     */
    private static final Charset CHARSET = StandardCharsets.UTF_8;
 
    /**
     * 生成密钥对
     *
     * @return 密钥对
     */
    private static KeyPair generateSm2KeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        //使用标准名称创建EC参数生成的参数规范
        final ECGenParameterSpec sm2Spec = new ECGenParameterSpec(STANDARD_NAME);
 
        // 获取一个椭圆曲线类型的密钥对生成器
        final KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM, new BouncyCastleProvider());
 
        kpg.initialize(sm2Spec, new SecureRandom());
        // 通过密钥生成器生成密钥对
        return kpg.generateKeyPair();
    }
 
    /**
     * 生成密钥对
     *
     * @return 密钥对
     */
    public static String[] genKeyPair() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
        KeyPair keyPair = generateSm2KeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        return new String[]{
                Base64Utils.encodeToString(privateKey.getEncoded()),
                Base64Utils.encodeToString(publicKey.getEncoded())
        };
    }
 
    /**
     * 私钥转换为 {@link ECPrivateKeyParameters}
     *
     * @param key 私钥
     * @return 私钥{@link ECPrivateKeyParameters}
     */
    private static ECPrivateKeyParameters privateKeyToParams(byte[] key) throws InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException {
        KeySpec keySpec = new PKCS8EncodedKeySpec(key);
        PrivateKey privateKey = getKeyFactory().generatePrivate(keySpec);
        ;
        return (ECPrivateKeyParameters) ECUtil.generatePrivateKeyParameter(privateKey);
    }
 
    /**
     * 公钥转换为 {@link ECPublicKeyParameters}
     *
     * @param key 公钥
     * @return 公钥{@link ECPublicKeyParameters}
     */
    private static ECPublicKeyParameters publicKeyToParams(byte[] key) throws InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException {
        KeySpec keySpec = new X509EncodedKeySpec(key);
        PublicKey publicKey = getKeyFactory().generatePublic(keySpec);
        return (ECPublicKeyParameters) ECUtil.generatePublicKeyParameter(publicKey);
    }
 
    /**
     * 获取{@link KeyFactory}
     *
     * @return {@link KeyFactory}
     */
    private static KeyFactory getKeyFactory() throws NoSuchAlgorithmException {
        final Provider provider = new BouncyCastleProvider();
        return KeyFactory.getInstance(ALGORITHM, provider);
    }
 
    /**
     * 签名
     *
     * @param content 原始串
     * @param priKey  私钥
     * @return 签名
     */
    public static String sign(String content, String priKey) throws Exception {
        byte[] data = content.getBytes(CHARSET);
        byte[] privateKey = Base64Utils.decode(priKey.getBytes(CHARSET));
 
        SM2Signer signer = new SM2Signer();
        CipherParameters param = new ParametersWithRandom(privateKeyToParams(privateKey));
        signer.init(true, param);
        signer.update(data, 0, data.length);
 
        byte[] buffer = signer.generateSignature();
 
        return Base64Utils.encodeToString(buffer);
    }
 
    /**
     * 用公钥检验数字签名的合法性
     *
     * @param content   原始串
     * @param sign      待验证签名
     * @param publicKey 私钥
     * @return 是否验证通过
     */
    public static boolean verify(String content, String sign, String publicKey) throws Exception {
        byte[] data = content.getBytes(CHARSET);
        byte[] signBuffer = Base64Utils.decodeFromString(sign);
        byte[] keyBuffer = Base64Utils.decodeFromString(publicKey);
 
        SM2Signer signer = new SM2Signer();
        CipherParameters param = publicKeyToParams(keyBuffer);
        signer.init(false, param);
        signer.update(data, 0, data.length);
        return signer.verifySignature(signBuffer);
    }
 
 
 
//    public static void main(String[] args) {
//        Security.addProvider(new BouncyCastleProvider());
//
//        try {
//            // 生成密钥对
//            String[] keyPair = SM2Util.genKeyPair();
//            String privateKey = keyPair[0];
//            String publicKey = keyPair[1];
//
//            // 对消息进行签名
//            String message = "你好,世界!";
//            String signature = SM2Util.sign(message, privateKey);
//            System.out.println("生成的签名: " + signature);
//
//            // 验证签名
//            boolean isValid = SM2Util.verify(message, signature, publicKey);
//            System.out.println("签名验证结果: " + isValid);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
}