| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 | using Org.BouncyCastle.Crypto;using Org.BouncyCastle.Crypto.Digests;using Org.BouncyCastle.Crypto.Generators;using Org.BouncyCastle.Crypto.Parameters;using Org.BouncyCastle.Math;using Org.BouncyCastle.Math.EC;using Org.BouncyCastle.Security;using Org.BouncyCastle.Utilities.Encoders;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace PTMedicalInsurance.Common{    /// <summary>    /// 密码计算    /// </summary>    public class Cipher    {        private int ct = 1;        /// <summary>        /// 椭圆曲线E上点P2        /// </summary>        private ECPoint p2;        private SM3Digest sm3keybase;        private SM3Digest sm3c3;        private readonly byte[] key = new byte[32];        private byte keyOff = 0;        public Cipher()        {        }        private void Reset()        {            sm3keybase = new SM3Digest();            sm3c3 = new SM3Digest();            byte[] p;            p = p2.Normalize().XCoord.ToBigInteger().ToByteArray();            sm3keybase.BlockUpdate(p, 0, p.Length);            sm3c3.BlockUpdate(p, 0, p.Length);            p = p2.Normalize().YCoord.ToBigInteger().ToByteArray();            sm3keybase.BlockUpdate(p, 0, p.Length);            ct = 1;            NextKey();        }        private void NextKey()        {            SM3Digest sm3keycur = new SM3Digest(sm3keybase);            sm3keycur.Update((byte)(ct >> 24 & 0x00ff));            sm3keycur.Update((byte)(ct >> 16 & 0x00ff));            sm3keycur.Update((byte)(ct >> 8 & 0x00ff));            sm3keycur.Update((byte)(ct & 0x00ff));            sm3keycur.DoFinal(key, 0);            keyOff = 0;            ct++;        }        public virtual ECPoint InitEnc(SM2 sm2, ECPoint userKey)        {            AsymmetricCipherKeyPair key = sm2.EccKeyPairGenerator.GenerateKeyPair();            ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;            ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;            BigInteger k = ecpriv.D;            ECPoint c1 = ecpub.Q;            p2 = userKey.Multiply(k);            Reset();            return c1;        }        public virtual void Encrypt(byte[] data)        {            //p2.Normalize();            sm3c3.BlockUpdate(data, 0, data.Length);            for (int i = 0; i < data.Length; i++)            {                if (keyOff == key.Length)                    NextKey();                data[i] ^= key[keyOff++];            }        }        public virtual void InitDec(BigInteger userD, ECPoint c1)        {            p2 = c1.Multiply(userD);            Reset();        }        public virtual void Decrypt(byte[] data)        {            for (int i = 0; i < data.Length; i++)            {                if (keyOff == key.Length)                    NextKey();                data[i] ^= key[keyOff++];            }            sm3c3.BlockUpdate(data, 0, data.Length);        }        public virtual void Dofinal(byte[] c3)        {            byte[] p = p2.Normalize().YCoord.ToBigInteger().ToByteArray();            sm3c3.BlockUpdate(p, 0, p.Length);            sm3c3.DoFinal(c3, 0);            Reset();        }    }    /// <summary>    /// 加密处理中心    /// </summary>    public class SM2    {        public static SM2 Instance        {            get            {                return new SM2();            }        }        public static SM2 InstanceTest        {            get            {                return new SM2();            }        }        #region 曲线参数        /// <summary>        /// 曲线参数        /// </summary>        public static readonly string[] CurveParameter = {            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",// p,0            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",// a,1            "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",// b,2            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",// n,3            "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",// gx,4            "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" // gy,5        };        /// <summary>        /// 椭圆曲线参数        /// </summary>        public string[] EccParam = CurveParameter;        /// <summary>        /// 椭圆曲线参数P        /// </summary>        public readonly BigInteger EccP;        /// <summary>        /// 椭圆曲线参数A        /// </summary>        public readonly BigInteger EccA;        /// <summary>        /// 椭圆曲线参数B        /// </summary>        public readonly BigInteger EccB;        /// <summary>        /// 椭圆曲线参数N        /// </summary>        public readonly BigInteger EccN;        /// <summary>        /// 椭圆曲线参数Gx        /// </summary>        public readonly BigInteger EccGx;        /// <summary>        /// 椭圆曲线参数Gy        /// </summary>        public readonly BigInteger EccGy;        #endregion        /// <summary>        /// 椭圆曲线        /// </summary>        public readonly ECCurve EccCurve;        /// <summary>        /// 椭圆曲线的点G        /// </summary>        public readonly ECPoint EccPointG;        /// <summary>        /// 椭圆曲线 bc规范        /// </summary>        public readonly ECDomainParameters EccBcSpec;        /// <summary>        /// 椭圆曲线密钥对生成器        /// </summary>        public readonly ECKeyPairGenerator EccKeyPairGenerator;        private SM2()        {            EccParam = CurveParameter;            EccP = new BigInteger(EccParam[0], 16);            EccA = new BigInteger(EccParam[1], 16);            EccB = new BigInteger(EccParam[2], 16);            EccN = new BigInteger(EccParam[3], 16);            EccGx = new BigInteger(EccParam[4], 16);            EccGy = new BigInteger(EccParam[5], 16);            ECFieldElement ecc_gx_fieldelement = new FpFieldElement(EccP, EccGx);            ECFieldElement ecc_gy_fieldelement = new FpFieldElement(EccP, EccGy);            EccCurve = new FpCurve(EccP, EccA, EccB);            EccPointG = new FpPoint(EccCurve, ecc_gx_fieldelement, ecc_gy_fieldelement);            EccBcSpec = new ECDomainParameters(EccCurve, EccPointG, EccN);            ECKeyGenerationParameters ecc_ecgenparam;            ecc_ecgenparam = new ECKeyGenerationParameters(EccBcSpec, new SecureRandom());            EccKeyPairGenerator = new ECKeyPairGenerator();            EccKeyPairGenerator.Init(ecc_ecgenparam);        }        /// <summary>        /// 获取杂凑值H        /// </summary>        /// <param name="z">Z值</param>        /// <param name="data">待签名消息</param>        /// <returns></returns>        public virtual byte[] Sm2GetH(byte[] z, byte[] data)        {            SM3Digest sm3 = new SM3Digest();            //Z            sm3.BlockUpdate(z, 0, z.Length);            //待签名消息            sm3.BlockUpdate(data, 0, data.Length);            // H            byte[] md = new byte[sm3.GetDigestSize()];            sm3.DoFinal(md, 0);            return md;        }        /// <summary>        /// 获取Z值        /// Z=SM3(ENTL∣∣userId∣∣a∣∣b∣∣gx∣∣gy ∣∣x∣∣y)         /// </summary>        /// <param name="userId">签名方的用户身份标识</param>        /// <param name="userKey">签名方公钥</param>        /// <returns></returns>        public virtual byte[] Sm2GetZ(byte[] userId, ECPoint userKey)        {            SM3Digest sm3 = new SM3Digest();            byte[] p;            // ENTL由2个字节标识的ID的比特长度             int len = userId.Length * 8;            sm3.Update((byte)(len >> 8 & 0x00ff));            sm3.Update((byte)(len & 0x00ff));            // userId用户身份标识ID            sm3.BlockUpdate(userId, 0, userId.Length);            // a,b为系统曲线参数;            p = EccA.ToByteArray();            sm3.BlockUpdate(p, 0, p.Length);            p = EccB.ToByteArray();            sm3.BlockUpdate(p, 0, p.Length);            //  gx、gy为基点            p = EccGx.ToByteArray();            sm3.BlockUpdate(p, 0, p.Length);            p = EccGy.ToByteArray();            sm3.BlockUpdate(p, 0, p.Length);            // x,y用户的公钥的X和Y            p = userKey.Normalize().XCoord.ToBigInteger().ToByteArray();            sm3.BlockUpdate(p, 0, p.Length);            p = userKey.Normalize().YCoord.ToBigInteger().ToByteArray();            sm3.BlockUpdate(p, 0, p.Length);            // Z            byte[] md = new byte[sm3.GetDigestSize()];            sm3.DoFinal(md, 0);            return md;        }    }    /// <summary>    /// Sm2算法       /// 对标国际RSA算法    /// </summary>    public class Sm2Crypto    {        /// <summary>        /// 数据        /// </summary>        public string Str { get; set; }        /// <summary>        /// 数据        /// </summary>        public byte[] Data { get; set; }        /// <summary>        /// 公钥        /// </summary>        public string PublicKey { get; set; }        /// <summary>        /// 私钥        /// </summary>        public string PrivateKey { get; set; }        /// <summary>        /// 获取密钥        /// </summary>        /// <param name="privateKey">私钥</param>        /// <param name="publicKey">公钥</param>        public static void GetKey(out string privateKey, out string publicKey)        {            SM2 sm2 = SM2.Instance;            AsymmetricCipherKeyPair key = sm2.EccKeyPairGenerator.GenerateKeyPair();            ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;            ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;            publicKey = Encoding.Default.GetString(Hex.Encode(ecpub.Q.GetEncoded())).ToUpper();            privateKey = Encoding.Default.GetString(Hex.Encode(ecpriv.D.ToByteArray())).ToUpper();        }        #region 解密        public object Decrypt(Sm2Crypto entity)        {            var data = !string.IsNullOrEmpty(entity.Str) ?                Hex.Decode(entity.Str) :                entity.Data;            return Encoding.Default.GetString(Decrypt(Hex.Decode(entity.PrivateKey), data));        }        /// <summary>        /// 解密        /// </summary>        /// <param name="privateKey"></param>        /// <param name="encryptedData"></param>        /// <returns></returns>        private static byte[] Decrypt(byte[] privateKey, byte[] encryptedData)        {            if (null == privateKey || privateKey.Length == 0)            {                return null;            }            if (encryptedData == null || encryptedData.Length == 0)            {                return null;            }            String data = Encoding.Default.GetString(Hex.Encode(encryptedData));            byte[] c1Bytes = Hex.Decode(Encoding.Default.GetBytes(data.Substring(0, 130)));            int c2Len = encryptedData.Length - 97;            byte[] c2 = Hex.Decode(Encoding.Default.GetBytes(data.Substring(130, 2 * c2Len)));            byte[] c3 = Hex.Decode(Encoding.Default.GetBytes(data.Substring(130 + 2 * c2Len, 64)));            SM2 sm2 = SM2.Instance;            BigInteger userD = new BigInteger(1, privateKey);            ECPoint c1 = sm2.EccCurve.DecodePoint(c1Bytes);            //c1.Normalize();            Cipher cipher = new Cipher();            cipher.InitDec(userD, c1);            cipher.Decrypt(c2);            cipher.Dofinal(c3);            return c2;        }        #endregion        #region 加密        public string Encrypt(Sm2Crypto entity)        {            var data = !string.IsNullOrEmpty(entity.Str) ?                Encoding.Default.GetBytes(entity.Str) :                entity.Data;            return Encrypt(Hex.Decode(entity.PublicKey), data);        }        /// <summary>        /// 默认加密        /// </summary>        /// <returns></returns>        public string Encrypt()        {            var data = !string.IsNullOrEmpty(this.Str) ?                Encoding.Default.GetBytes(this.Str) :                this.Data;            return Encrypt(Hex.Decode(this.PublicKey), data);        }        /// <summary>        /// 加密        /// </summary>        /// <param name="publicKey"></param>        /// <param name="data"></param>        /// <returns></returns>        private static string Encrypt(byte[] publicKey, byte[] data)        {            if (null == publicKey || publicKey.Length == 0)            {                return null;            }            if (data == null || data.Length == 0)            {                return null;            }            byte[] source = new byte[data.Length];            Array.Copy(data, 0, source, 0, data.Length);            Cipher cipher = new Cipher();            SM2 sm2 = SM2.Instance;            ECPoint userKey = sm2.EccCurve.DecodePoint(publicKey);            //userKey.Normalize();            ECPoint c1 = cipher.InitEnc(sm2, userKey);            cipher.Encrypt(source);            byte[] c3 = new byte[32];            cipher.Dofinal(c3);            String sc1 = Encoding.Default.GetString(Hex.Encode(c1.GetEncoded()));            String sc2 = Encoding.Default.GetString(Hex.Encode(source));            String sc3 = Encoding.Default.GetString(Hex.Encode(c3));            return (sc1 + sc2 + sc3).ToUpper();        }        #endregion    }}
 |