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