public class SM2CryptoUtil
{
public SM2CryptoUtil(byte[] pubkey, byte[] privkey, Mode mode)
{
this.pubkey = pubkey;
this.privkey = privkey;
this.mode = mode;
}
public SM2CryptoUtil(string pubkey, string privkey, Mode mode = Mode.C1C2C3, bool isPkcs8 = false)
{
if (!isPkcs8)
{
if (pubkey != null) this.pubkey = Decode(pubkey);
if (privkey != null) this.privkey = Decode(privkey);
}
else
{
if (pubkey != null) this.pubkey = ((ECPublicKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(pubkey))).Q.GetEncoded();
if (privkey != null) this.privkey = ((ECPrivateKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privkey))).D.ToByteArray();
}
this.mode = mode;
}
byte[] pubkey;
byte[] privkey;
Mode mode;
ICipherParameters _privateKeyParameters;
ICipherParameters PrivateKeyParameters
{
get
{
var r = _privateKeyParameters;
if (r == null) r = _privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, privkey), new ECDomainParameters(GMNamedCurves.GetByName("SM2P256V1")));
return r;
}
}
ICipherParameters _publicKeyParameters;
ICipherParameters PublicKeyParameters
{
get
{
var r = _publicKeyParameters;
if (r == null)
{
var x9ec = GMNamedCurves.GetByName("SM2P256V1");
r = _publicKeyParameters = new ECPublicKeyParameters(x9ec.Curve.DecodePoint(pubkey), new ECDomainParameters(x9ec));
}
return r;
}
}
public static void GenerateKeyHex(out string pubkey, out string privkey)
{
GenerateKey(out var a, out var b);
pubkey = Hex.ToHexString(a);
privkey = Hex.ToHexString(b);
}
public static void GenerateKey(out byte[] pubkey, out byte[] privkey)
{
var g = new ECKeyPairGenerator();
g.Init(new ECKeyGenerationParameters(new ECDomainParameters(GMNamedCurves.GetByName("SM2P256V1")), new SecureRandom()));
var k = g.GenerateKeyPair();
pubkey = ((ECPublicKeyParameters)k.Public).Q.GetEncoded(false);
privkey = ((ECPrivateKeyParameters)k.Private).D.ToByteArray();
}
public byte[] Decrypt(byte[] data)
{
if (mode == Mode.C1C3C2) data = C132ToC123(data);
var sm2 = new SM2Engine(new SM3Digest());
sm2.Init(false, this.PrivateKeyParameters);
return sm2.ProcessBlock(data, 0, data.Length);
}
public byte[] Encrypt(byte[] data)
{
var sm2 = new SM2Engine(new SM3Digest());
sm2.Init(true, new ParametersWithRandom(PublicKeyParameters));
data = sm2.ProcessBlock(data, 0, data.Length);
if (mode == Mode.C1C3C2) data = C123ToC132(data);
return data;
}
public byte[] Encrypt(string msg, byte[] data)
{
var sm2 = new SM2Engine(new SM3Digest());
var mw = Hex.DecodeStrict(msg);
var newPubkey = pubkey;
// if (pubkey.Length>128)
// {
// newPubkey = pubkey.Skip(0).Take(128).ToArray();
// var xHex = newPubkey.Skip(0).Take(64).ToArray();
// var yHex = newPubkey.Skip(0).Take(64).ToArray();
// publicKey = cipher.createPoint(xHex, yHex);
// let c1 = cipher.initEncipher(publicKey);
// cipher.encryptBlock(msg);
// let c2 = _.arrayToHex(msg);
// let c3 = new Array(32);
// cipher.doFinal(c3)
//c3 = _.arrayToHex(c3);
// return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2;
// }
sm2.Init(true, new ParametersWithRandom(PublicKeyParameters));
data = sm2.ProcessBlock(data, 0, data.Length);
if (mode == Mode.C1C3C2) data = C123ToC132(data);
return data;
}
public byte[] Sign(byte[] msg, byte[] id = null)
{
var sm2 = new SM2Signer(new SM3Digest());
ICipherParameters cp;
if (id != null) cp = new ParametersWithID(new ParametersWithRandom(PrivateKeyParameters), id);
else cp = new ParametersWithRandom(PrivateKeyParameters);
sm2.Init(true, cp);
sm2.BlockUpdate(msg, 0, msg.Length);
return sm2.GenerateSignature();
}
public bool VerifySign(byte[] msg, byte[] signature, byte[] id = null)
{
var sm2 = new SM2Signer(new SM3Digest());
ICipherParameters cp;
if (id != null) cp = new ParametersWithID(PublicKeyParameters, id);
else cp = PublicKeyParameters;
sm2.Init(false, cp);
sm2.BlockUpdate(msg, 0, msg.Length);
return sm2.VerifySignature(signature);
}
static byte[] C123ToC132(byte[] c1c2c3)
{
var gn = GMNamedCurves.GetByName("SM2P256V1");
int c1Len = (gn.Curve.FieldSize + 7) / 8 * 2 + 1;
int c3Len = 32;
byte[] result = new byte[c1c2c3.Length];
Array.Copy(c1c2c3, 0, result, 0, c1Len); //c1
Array.Copy(c1c2c3, c1c2c3.Length - c3Len, result, c1Len, c3Len); //c3
Array.Copy(c1c2c3, c1Len, result, c1Len + c3Len, c1c2c3.Length - c1Len - c3Len); //c2
return result;
}
static byte[] C132ToC123(byte[] c1c3c2)
{
var gn = GMNamedCurves.GetByName("SM2P256V1");
int c1Len = (gn.Curve.FieldSize + 7) / 8 * 2 + 1;
int c3Len = 32;
byte[] result = new byte[c1c3c2.Length];
Array.Copy(c1c3c2, 0, result, 0, c1Len); //c1: 0->65
Array.Copy(c1c3c2, c1Len + c3Len, result, c1Len, c1c3c2.Length - c1Len - c3Len); //c2
Array.Copy(c1c3c2, c1Len, result, c1c3c2.Length - c3Len, c3Len); //c3
return result;
}
static byte[] Decode(string key)
{
return Regex.IsMatch(key, "^[0-9a-f]+$", RegexOptions.IgnoreCase) ? Hex.Decode(key) : Convert.FromBase64String(key);
}
public enum Mode
{
C1C2C3, C1C3C2
}
}
public void test()
{
//这种方式可以适配 在线 加密内容 https://the-x.cn/cryptography/Sm2.aspx
//加密
var prikey = Hex.DecodeStrict(PRIVATE_KEY);
var pubkey = Hex.DecodeStrict(PUBLIC_KEY);
SM2CryptoUtil sM2CryptoUtil = new SM2CryptoUtil(pubkey, prikey, SM2CryptoUtil.Mode.C1C3C2);
var dt = sM2CryptoUtil.Encrypt(Encoding.UTF8.GetBytes("admin123"));
var hex = Hex.ToHexString(dt);
var ce = Encoding.UTF8.GetString(dt);
String image = Base64.ToBase64String(dt);
//解密
var jm = sM2CryptoUtil.Decrypt(Hex.DecodeStrict(hex));
var jg = Encoding.UTF8.GetString(jm);
var pp = "BN3Cwq9XYduzYmBVBPk222pGMHoX/5iSKB/i6XmgO0xk6/pNvf+Kpz1g3AERzAY+R1NumSLieNYLXgqb+nJF55TCbX0Na96csH4m9Z+CReSe/3ZAjv6Sz/0neiGIlR0Uy5sb1TTnynBQ";
var nr = Convert.FromBase64String(pp);
var jm1 = sM2CryptoUtil.Decrypt(nr);
var jg1 = Encoding.UTF8.GetString(jm1);
// 这种方式 适配 前端 和java 调用的 sm-crypto 插件 解决方法 补充04 或者 减少04
var pp2 = "048d842a5a958a5397b6c2a85509f1fae6b28f39489d29aba5d080b8460a5018d546017690cc938c5266dbe1ecc5ca0f630d36552960d9ca4361a3d83d1813ded86f7abbcc7a08d491e9b61ab7d586a50c60d39b24ae928cb55f5868d4af9d9bf3a9002c7474d5e0b2";
var jm2 = sM2CryptoUtil.Decrypt(Hex.DecodeStrict(pp2));
var jg2 = Encoding.UTF8.GetString(jm2);
}
![]()
public void test()
{
//这种方式可以适配 在线 加密内容 https://the-x.cn/cryptography/Sm2.aspx
//加密
var prikey = Hex.DecodeStrict(PRIVATE_KEY);
var pubkey = Hex.DecodeStrict(PUBLIC_KEY);
SM2CryptoUtil sM2CryptoUtil = new SM2CryptoUtil(pubkey, prikey, SM2CryptoUtil.Mode.C1C3C2);
var dt = sM2CryptoUtil.Encrypt(Encoding.UTF8.GetBytes("admin123"));
var hex = Hex.ToHexString(dt);
var ce = Encoding.UTF8.GetString(dt);
String image = Base64.ToBase64String(dt);
//解密
var jm = sM2CryptoUtil.Decrypt(Hex.DecodeStrict(hex));
var jg = Encoding.UTF8.GetString(jm);
var pp = "BN3Cwq9XYduzYmBVBPk222pGMHoX/5iSKB/i6XmgO0xk6/pNvf+Kpz1g3AERzAY+R1NumSLieNYLXgqb+nJF55TCbX0Na96csH4m9Z+CReSe/3ZAjv6Sz/0neiGIlR0Uy5sb1TTnynBQ";
var nr = Convert.FromBase64String(pp);
var jm1 = sM2CryptoUtil.Decrypt(nr);
var jg1 = Encoding.UTF8.GetString(jm1);
// 这种方式 适配 前端 和java 调用的 sm-crypto 插件 解决方法 补充04 或者 减少04
var pp2 = "048d842a5a958a5397b6c2a85509f1fae6b28f39489d29aba5d080b8460a5018d546017690cc938c5266dbe1ecc5ca0f630d36552960d9ca4361a3d83d1813ded86f7abbcc7a08d491e9b61ab7d586a50c60d39b24ae928cb55f5868d4af9d9bf3a9002c7474d5e0b2";
var jm2 = sM2CryptoUtil.Decrypt(Hex.DecodeStrict(pp2));
var jg2 = Encoding.UTF8.GetString(jm2);
}
View Code