rain
2024-08-12 4edec5b8b749a22040c24e0cb8709c91d6f215f6
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
package com.dji.sample.territory.utils.jym;
 
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECFieldElement.Fp;
import org.bouncycastle.math.ec.ECPoint;
 
import java.math.BigInteger;
import java.security.SecureRandom;
 
public class SM2Factory {
    private static final BigInteger a = new BigInteger("fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc", 16);
    private static final BigInteger b = new BigInteger("28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93", 16);
    private static final BigInteger gx = new BigInteger("32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7", 16);
    private static final BigInteger gy = new BigInteger("bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0", 16);
    private static final BigInteger n = new BigInteger("fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123", 16);
    private static final BigInteger p = new BigInteger("fffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff", 16);
    private static final int h = 1;
    public final ECFieldElement ecc_gx_fieldelement;
    public final ECFieldElement ecc_gy_fieldelement;
    public final ECCurve ecc_curve;
    public final ECPoint ecc_point_g;
    public final ECDomainParameters ecc_bc_spec;
    public final ECKeyPairGenerator ecc_key_pair_generator;
 
    public static SM2Factory getInstance() {
        return new SM2Factory();
    }
 
    public SM2Factory() {
        this.ecc_gx_fieldelement = new Fp(p, gx);
        this.ecc_gy_fieldelement = new Fp(p, gy);
        this.ecc_curve = new ECCurve.Fp(p, a, b);
        this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement, false);
        this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, n);
        ECKeyGenerationParameters ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());
        this.ecc_key_pair_generator = new ECKeyPairGenerator();
        this.ecc_key_pair_generator.init(ecc_ecgenparam);
    }
 
    public byte[] sm2GetZ(byte[] userId, ECPoint userKey) {
        SM3Digest sm3 = new SM3Digest();
        int len = userId.length * 8;
        sm3.update((byte)(len >> 8 & 255));
        sm3.update((byte)(len & 255));
        sm3.update(userId, 0, userId.length);
        byte[] p = Util.byteConvert32Bytes(a);
        sm3.update(p, 0, p.length);
        p = Util.byteConvert32Bytes(b);
        sm3.update(p, 0, p.length);
        p = Util.byteConvert32Bytes(gx);
        sm3.update(p, 0, p.length);
        p = Util.byteConvert32Bytes(gy);
        sm3.update(p, 0, p.length);
        p = Util.byteConvert32Bytes(userKey.normalize().getXCoord().toBigInteger());
        sm3.update(p, 0, p.length);
        p = Util.byteConvert32Bytes(userKey.normalize().getYCoord().toBigInteger());
        sm3.update(p, 0, p.length);
        byte[] md = new byte[sm3.getDigestSize()];
        sm3.doFinal(md, 0);
        return md;
    }
 
    public void sm2Sign(byte[] md, BigInteger userD, ECPoint userKey,SM2Result sm2Result) {
        BigInteger e = new BigInteger(1, md);
        BigInteger k = null;
        ECPoint kp = null;
        BigInteger r = null;
        BigInteger s = null;
 
        while(true) {
            do {
                AsymmetricCipherKeyPair keypair = this.ecc_key_pair_generator.generateKeyPair();
                ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)keypair.getPrivate();
                ECPublicKeyParameters ecpub = (ECPublicKeyParameters)keypair.getPublic();
                k = ecpriv.getD();
                kp = ecpub.getQ();
                r = e.add(kp.getXCoord().toBigInteger());
                r = r.mod(n);
            } while(r.equals(BigInteger.ZERO));
 
            if (!r.add(k).equals(n) && r.toString(16).length() == 64) {
                BigInteger da_1 = userD.add(BigInteger.ONE);
                da_1 = da_1.modInverse(n);
                s = r.multiply(userD);
                s = k.subtract(s).mod(n);
                s = da_1.multiply(s).mod(n);
                if (!s.equals(BigInteger.ZERO) && s.toString(16).length() == 64) {
                    sm2Result.r = r;
                    sm2Result.s = s;
                    return;
                }
            }
        }
    }
 
    public void sm2Verify(byte[] md, ECPoint userKey, BigInteger r, BigInteger s, SM2Result sm2Result) {
        sm2Result.R = null;
        BigInteger e = new BigInteger(1, md);
        BigInteger t = r.add(s).mod(n);
        if (!t.equals(BigInteger.ZERO)) {
            ECPoint x1y1 = this.ecc_point_g.multiply(sm2Result.s);
            x1y1 = x1y1.add(userKey.multiply(t));
            sm2Result.R = e.add(x1y1.normalize().getXCoord().toBigInteger()).mod(n);
        }
    }
}