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