欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# SM加密

程序员文章站 2022-09-22 10:16:34
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC; usi ......
using system;
using system.collections.generic;
using system.linq;
using system.text;
using org.bouncycastle.math;
using org.bouncycastle.math.ec;
using org.bouncycastle.crypto.parameters;
using org.bouncycastle.crypto.generators;
using org.bouncycastle.crypto.digests;
using org.bouncycastle.security;
 
namespace consoleapplication1
{
    public class sm2
    {
        public static sm2 instance
        {
            get
            {
                return new sm2();
            }
 
        }
        public static sm2 instancetest
        {
            get
            {
                return new sm2();
            }
 
        }
 
        public static readonly string[] sm2_param = {
            "fffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff",// p,0
            "fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc",// a,1
            "28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93",// b,2
            "fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123",// n,3
            "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",// gx,4
            "bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0" // gy,5
        };
 
        public string[] ecc_param = sm2_param;
 
        public readonly biginteger ecc_p;
        public readonly biginteger ecc_a;
        public readonly biginteger ecc_b;
        public readonly biginteger ecc_n;
        public readonly biginteger ecc_gx;
        public readonly biginteger ecc_gy;
 
        public readonly eccurve ecc_curve;
        public readonly ecpoint ecc_point_g;
 
        public readonly ecdomainparameters ecc_bc_spec;
 
        public readonly eckeypairgenerator ecc_key_pair_generator;
 
        private sm2()
        {
            ecc_param = sm2_param;
 
            ecfieldelement ecc_gx_fieldelement;
            ecfieldelement ecc_gy_fieldelement;
 
            ecc_p = new biginteger(ecc_param[0], 16);
            ecc_a = new biginteger(ecc_param[1], 16);
            ecc_b = new biginteger(ecc_param[2], 16);
            ecc_n = new biginteger(ecc_param[3], 16);
            ecc_gx = new biginteger(ecc_param[4], 16);
            ecc_gy = new biginteger(ecc_param[5], 16);
 
 
            ecc_gx_fieldelement = new fpfieldelement(ecc_p, ecc_gx);
            ecc_gy_fieldelement = new fpfieldelement(ecc_p, ecc_gy);
 
            ecc_curve = new fpcurve(ecc_p, ecc_a, ecc_b);
            ecc_point_g = new fppoint(ecc_curve, ecc_gx_fieldelement, ecc_gy_fieldelement);
 
            ecc_bc_spec = new ecdomainparameters(ecc_curve, ecc_point_g, ecc_n);
 
            eckeygenerationparameters ecc_ecgenparam;
            ecc_ecgenparam = new eckeygenerationparameters(ecc_bc_spec, new securerandom());
 
            ecc_key_pair_generator = new eckeypairgenerator();
            ecc_key_pair_generator.init(ecc_ecgenparam);
        }
 
        public virtual byte[] sm2getz(byte[] userid, ecpoint userkey)
        {
            sm3digest sm3 = new sm3digest();
            byte[] p;
            // userid length
            int len = userid.length * 8;
            sm3.update((byte)(len >> 8 & 0x00ff));
            sm3.update((byte)(len & 0x00ff));
 
            // userid
            sm3.blockupdate(userid, 0, userid.length);
 
            // a,b
            p = ecc_a.tobytearray();
            sm3.blockupdate(p, 0, p.length);
            p = ecc_b.tobytearray();
            sm3.blockupdate(p, 0, p.length);
            // gx,gy
            p = ecc_gx.tobytearray();
            sm3.blockupdate(p, 0, p.length);
            p = ecc_gy.tobytearray();
            sm3.blockupdate(p, 0, p.length);
 
            // x,y
            //p = userkey.x.tobiginteger().tobytearray();
            //sm3.blockupdate(p, 0, p.length);
            //p = userkey.y.tobiginteger().tobytearray();
            //sm3.blockupdate(p, 0, p.length);
            p = userkey.x.tobiginteger().tobytearray();
            sm3.blockupdate(p, 0, p.length);
            p = userkey.y.tobiginteger().tobytearray();
            sm3.blockupdate(p, 0, p.length);
 
            // z
            byte[] md = new byte[sm3.getdigestsize()];
            sm3.dofinal(md, 0);
 
            return md;
        }
 
    }
}



using system;
using system.collections.generic;
using system.linq;
using system.text;
using org.bouncycastle.math;
using org.bouncycastle.utilities.encoders;
using org.bouncycastle.math.ec;
using org.bouncycastle.crypto.parameters;
using org.bouncycastle.crypto;
 
namespace consoleapplication1
{
    public class sm2utils
    {
        public static list<byte[]> generatekeypair()
        {
            list<byte[]> list = new list<byte[]>();
            sm2 sm2 = sm2.instance;
            asymmetriccipherkeypair key = sm2.ecc_key_pair_generator.generatekeypair();
            ecprivatekeyparameters ecpriv = (ecprivatekeyparameters)key.private;
            ecpublickeyparameters ecpub = (ecpublickeyparameters)key.public;
            biginteger privatekey = ecpriv.d;
            ecpoint publickey = ecpub.q;
            byte[] pubkey = hex.encode(publickey.getencoded());
            list.add(pubkey);
            byte[] prikey = hex.encode(privatekey.tobytearray());
            list.add(prikey);
            //system.console.out.writeline("公钥: " + encoding.default.getstring(hex.encode(publickey.getencoded())).toupper());
            //system.console.out.writeline("私钥: " + encoding.default.getstring(hex.encode(privatekey.tobytearray())).toupper());
            return list;
        }
 
        public static list<string> generatekeypair(string t)
        {
            list<string> list = new list<string>();
            sm2 sm2 = sm2.instance;
            asymmetriccipherkeypair key = sm2.ecc_key_pair_generator.generatekeypair();
            ecprivatekeyparameters ecpriv = (ecprivatekeyparameters)key.private;
            ecpublickeyparameters ecpub = (ecpublickeyparameters)key.public;
            biginteger privatekey = ecpriv.d;
            ecpoint publickey = ecpub.q;
            string pubkey = encoding.default.getstring(hex.encode(publickey.getencoded())).toupper();
            list.add(pubkey);
            string prikey = encoding.default.getstring(hex.encode(privatekey.tobytearray())).toupper();
            list.add(prikey);
            //system.console.out.writeline("公钥: " + encoding.default.getstring(hex.encode(publickey.getencoded())).toupper());
            //system.console.out.writeline("私钥: " + encoding.default.getstring(hex.encode(privatekey.tobytearray())).toupper());
            return list;
        }
 
        public 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.ecc_curve.decodepoint(publickey);
 
            ecpoint c1 = cipher.init_enc(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();
        }
 
        public 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.ecc_curve.decodepoint(c1bytes);
            cipher cipher = new cipher();
            cipher.init_dec(userd, c1);
            cipher.decrypt(c2);
            cipher.dofinal(c3);
 
            return c2;
        }
 
 
 
        #region myregion
 
        //[stathread]
        //public static void main()
        //{
        //    generatekeypair();
 
        //    string plaintext = "ererfeiisgod";
        //    byte[] sourcedata = encoding.default.getbytes(plaintext);
 
        //    //下面的秘钥可以使用generatekeypair()生成的秘钥内容  
        //    // 国密规范正式私钥  
        //    string prik = "3690655e33d5ea3d9a4ae1a1add766fdea045cdeaa43a9206fb8c430cefe0d94";
        //    // 国密规范正式公钥  
        //    string pubk = "04f6e0c3345ae42b51e06bf50b98834988d54ebc7460fe135a48171bc0629eae205eede253a530608178a98f1e19bb737302813ba39ed3fa3c51639d7a20c7391a";
 
        //    system.console.out.writeline("加密: ");
        //    string ciphertext = sm2utils.encrypt(hex.decode(pubk), sourcedata);
        //    system.console.out.writeline(ciphertext);
        //    system.console.out.writeline("解密: ");
        //    plaintext = encoding.default.getstring(sm2utils.decrypt(hex.decode(prik), hex.decode(ciphertext)));
        //    system.console.out.writeline(plaintext);
 
        //    console.readline();
        //} 
        #endregion
    }
}



using system;
using system.collections.generic;
using system.linq;
using system.text;
using org.bouncycastle.crypto;
 
namespace consoleapplication1
{
    public abstract class generaldigest : idigest
    {
        private const int byte_length = 64;
 
        private byte[] xbuf;
        private int xbufoff;
 
        private long bytecount;
 
        internal generaldigest()
        {
            xbuf = new byte[4];
        }
 
        internal generaldigest(generaldigest t)
        {
            xbuf = new byte[t.xbuf.length];
            array.copy(t.xbuf, 0, xbuf, 0, t.xbuf.length);
 
            xbufoff = t.xbufoff;
            bytecount = t.bytecount;
        }
 
        public void update(byte input)
        {
            xbuf[xbufoff++] = input;
 
            if (xbufoff == xbuf.length)
            {
                processword(xbuf, 0);
                xbufoff = 0;
            }
 
            bytecount++;
        }
 
        public void blockupdate(
            byte[] input,
            int inoff,
            int length)
        {
            //
            // fill the current word
            //
            while ((xbufoff != 0) && (length > 0))
            {
                update(input[inoff]);
                inoff++;
                length--;
            }
 
            //
            // process whole words.
            //
            while (length > xbuf.length)
            {
                processword(input, inoff);
 
                inoff += xbuf.length;
                length -= xbuf.length;
                bytecount += xbuf.length;
            }
 
            //
            // load in the remainder.
            //
            while (length > 0)
            {
                update(input[inoff]);
 
                inoff++;
                length--;
            }
        }
 
        public void finish()
        {
            long bitlength = (bytecount << 3);
 
            //
            // add the pad bytes.
            //
            update(unchecked((byte)128));
 
            while (xbufoff != 0) update(unchecked((byte)0));
            processlength(bitlength);
            processblock();
        }
 
        public virtual void reset()
        {
            bytecount = 0;
            xbufoff = 0;
            array.clear(xbuf, 0, xbuf.length);
        }
 
        public int getbytelength()
        {
            return byte_length;
        }
 
        internal abstract void processword(byte[] input, int inoff);
        internal abstract void processlength(long bitlength);
        internal abstract void processblock();
        public abstract string algorithmname { get; }
        public abstract int getdigestsize();
        public abstract int dofinal(byte[] output, int outoff);
    }
 
    public class supportclass
    {
        /// <summary>
        /// performs an unsigned bitwise right shift with the specified number
        /// </summary>
        /// <param name="number">number to operate on</param>
        /// <param name="bits">ammount of bits to shift</param>
        /// <returns>the resulting number from the shift operation</returns>
        public static int urshift(int number, int bits)
        {
            if (number >= 0)
                return number >> bits;
            else
                return (number >> bits) + (2 << ~bits);
        }
 
        /// <summary>
        /// performs an unsigned bitwise right shift with the specified number
        /// </summary>
        /// <param name="number">number to operate on</param>
        /// <param name="bits">ammount of bits to shift</param>
        /// <returns>the resulting number from the shift operation</returns>
        public static int urshift(int number, long bits)
        {
            return urshift(number, (int)bits);
        }
 
        /// <summary>
        /// performs an unsigned bitwise right shift with the specified number
        /// </summary>
        /// <param name="number">number to operate on</param>
        /// <param name="bits">ammount of bits to shift</param>
        /// <returns>the resulting number from the shift operation</returns>
        public static long urshift(long number, int bits)
        {
            if (number >= 0)
                return number >> bits;
            else
                return (number >> bits) + (2l << ~bits);
        }
 
        /// <summary>
        /// performs an unsigned bitwise right shift with the specified number
        /// </summary>
        /// <param name="number">number to operate on</param>
        /// <param name="bits">ammount of bits to shift</param>
        /// <returns>the resulting number from the shift operation</returns>
        public static long urshift(long number, long bits)
        {
            return urshift(number, (int)bits);
        }
 
 
    }
 
    public class sm3digest : generaldigest
    {
        public override string algorithmname
        {
            get
            {
                return "sm3";
            }
 
        }
        public override int getdigestsize()
        {
            return digest_length;
        }
 
        private const int digest_length = 32;
 
        private static readonly int[] v0 = new int[] { 0x7380166f, 0x4914b2b9, 0x172442d7, unchecked((int)0xda8a0600), unchecked((int)0xa96f30bc), 0x163138aa, unchecked((int)0xe38dee4d), unchecked((int)0xb0fb0e4e) };
 
        private int[] v = new int[8];
        private int[] v_ = new int[8];
 
        private static readonly int[] x0 = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
        private int[] x = new int[68];
        private int xoff;
 
        private int t_00_15 = 0x79cc4519;
        private int t_16_63 = 0x7a879d8a;
 
        public sm3digest()
        {
            reset();
        }
 
        public sm3digest(sm3digest t)
            : base(t)
        {
 
            array.copy(t.x, 0, x, 0, t.x.length);
            xoff = t.xoff;
 
            array.copy(t.v, 0, v, 0, t.v.length);
        }
 
        public override void reset()
        {
            base.reset();
 
            array.copy(v0, 0, v, 0, v0.length);
 
            xoff = 0;
            array.copy(x0, 0, x, 0, x0.length);
        }
 
        internal override void processblock()
        {
            int i;
 
            int[] ww = x;
            int[] ww_ = new int[64];
 
            for (i = 16; i < 68; i++)
            {
                ww[i] = p1(ww[i - 16] ^ ww[i - 9] ^ (rotate(ww[i - 3], 15))) ^ (rotate(ww[i - 13], 7)) ^ ww[i - 6];
            }
 
            for (i = 0; i < 64; i++)
            {
                ww_[i] = ww[i] ^ ww[i + 4];
            }
 
            int[] vv = v;
            int[] vv_ = v_;
 
            array.copy(vv, 0, vv_, 0, v0.length);
 
            int ss1, ss2, tt1, tt2, aaa;
            for (i = 0; i < 16; i++)
            {
                aaa = rotate(vv_[0], 12);
                ss1 = aaa + vv_[4] + rotate(t_00_15, i);
                ss1 = rotate(ss1, 7);
                ss2 = ss1 ^ aaa;
 
                tt1 = ff_00_15(vv_[0], vv_[1], vv_[2]) + vv_[3] + ss2 + ww_[i];
                tt2 = gg_00_15(vv_[4], vv_[5], vv_[6]) + vv_[7] + ss1 + ww[i];
                vv_[3] = vv_[2];
                vv_[2] = rotate(vv_[1], 9);
                vv_[1] = vv_[0];
                vv_[0] = tt1;
                vv_[7] = vv_[6];
                vv_[6] = rotate(vv_[5], 19);
                vv_[5] = vv_[4];
                vv_[4] = p0(tt2);
            }
            for (i = 16; i < 64; i++)
            {
                aaa = rotate(vv_[0], 12);
                ss1 = aaa + vv_[4] + rotate(t_16_63, i);
                ss1 = rotate(ss1, 7);
                ss2 = ss1 ^ aaa;
 
                tt1 = ff_16_63(vv_[0], vv_[1], vv_[2]) + vv_[3] + ss2 + ww_[i];
                tt2 = gg_16_63(vv_[4], vv_[5], vv_[6]) + vv_[7] + ss1 + ww[i];
                vv_[3] = vv_[2];
                vv_[2] = rotate(vv_[1], 9);
                vv_[1] = vv_[0];
                vv_[0] = tt1;
                vv_[7] = vv_[6];
                vv_[6] = rotate(vv_[5], 19);
                vv_[5] = vv_[4];
                vv_[4] = p0(tt2);
            }
            for (i = 0; i < 8; i++)
            {
                vv[i] ^= vv_[i];
            }
 
            // reset
            xoff = 0;
            array.copy(x0, 0, x, 0, x0.length);
        }
 
        internal override void processword(byte[] in_renamed, int inoff)
        {
            int n = in_renamed[inoff] << 24;
            n |= (in_renamed[++inoff] & 0xff) << 16;
            n |= (in_renamed[++inoff] & 0xff) << 8;
            n |= (in_renamed[++inoff] & 0xff);
            x[xoff] = n;
 
            if (++xoff == 16)
            {
                processblock();
            }
        }
 
        internal override void processlength(long bitlength)
        {
            if (xoff > 14)
            {
                processblock();
            }
 
            x[14] = (int)(supportclass.urshift(bitlength, 32));
            x[15] = (int)(bitlength & unchecked((int)0xffffffff));
        }
 
        public static void inttobigendian(int n, byte[] bs, int off)
        {
            bs[off] = (byte)(supportclass.urshift(n, 24));
            bs[++off] = (byte)(supportclass.urshift(n, 16));
            bs[++off] = (byte)(supportclass.urshift(n, 8));
            bs[++off] = (byte)(n);
        }
 
        public override int dofinal(byte[] out_renamed, int outoff)
        {
            finish();
 
            for (int i = 0; i < 8; i++)
            {
                inttobigendian(v[i], out_renamed, outoff + i * 4);
            }
 
            reset();
 
            return digest_length;
        }
 
        private int rotate(int x, int n)
        {
            return (x << n) | (supportclass.urshift(x, (32 - n)));
        }
 
        private int p0(int x)
        {
            return ((x) ^ rotate((x), 9) ^ rotate((x), 17));
        }
 
        private int p1(int x)
        {
            return ((x) ^ rotate((x), 15) ^ rotate((x), 23));
        }
 
        private int ff_00_15(int x, int y, int z)
        {
            return (x ^ y ^ z);
        }
 
        private int ff_16_63(int x, int y, int z)
        {
            return ((x & y) | (x & z) | (y & z));
        }
 
        private int gg_00_15(int x, int y, int z)
        {
            return (x ^ y ^ z);
        }
 
        private int gg_16_63(int x, int y, int z)
        {
            return ((x & y) | (~x & z));
        }
 
        //[stathread]
        //public static void  main()
        //{
        //    byte[] md = new byte[32];
        //    byte[] msg1 = encoding.default.getbytes("ererfeiisgod");
        //    sm3digest sm3 = new sm3digest();
        //    sm3.blockupdate(msg1, 0, msg1.length);
        //    sm3.dofinal(md, 0);
        //    system.string s = new utf8encoding().getstring(hex.encode(md));
        //    system.console.out.writeline(s.toupper());
 
        //    console.readline();
        //}
    }
}
using system;
using system.collections.generic;
using system.linq;
using system.text;
using org.bouncycastle.math;
using org.bouncycastle.math.ec;
using org.bouncycastle.crypto;
using org.bouncycastle.crypto.parameters;
 
namespace consoleapplication1
{
    public class cipher
    {
        private int ct = 1;
 
 
        private ecpoint p2;
        private sm3digest sm3keybase;
        private sm3digest sm3c3;
 
 
        private byte[] key = new byte[32];
        private byte keyoff = 0;
 
 
        public cipher()
        {
        }
 
 
        private void reset()
        {
            sm3keybase = new sm3digest();
            sm3c3 = new sm3digest();
 
 
            byte[] p;
 
            //p = p2.x.tobiginteger().tobytearray();
            p = p2.x.tobiginteger().tobytearray();
            sm3keybase.blockupdate(p, 0, p.length);
            sm3c3.blockupdate(p, 0, p.length);
 
            p = p2.y.tobiginteger().tobytearray();
            //p = p2.y.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 init_enc(sm2 sm2, ecpoint userkey)
        {
            biginteger k = null;
            ecpoint c1 = null;
 
 
            asymmetriccipherkeypair key = sm2.ecc_key_pair_generator.generatekeypair();
            ecprivatekeyparameters ecpriv = (ecprivatekeyparameters)key.private;
            ecpublickeyparameters ecpub = (ecpublickeyparameters)key.public;
            k = ecpriv.d;
            c1 = ecpub.q;
 
 
            p2 = userkey.multiply(k);
            reset();
 
 
            return c1;
        }
 
 
        public virtual void encrypt(byte[] data)
        {
            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 init_dec(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.y.tobiginteger().tobytearray();
            //byte[] p = p2.y.tobiginteger().tobytearray();
            sm3c3.blockupdate(p, 0, p.length);
            sm3c3.dofinal(c3, 0);
            reset();
        }
    }
}



using system;
using system.collections.generic;
using system.linq;
using system.text;
 
namespace consoleapplication1
{
    public class sm4
    {
        public const int sm4_encrypt = 1;
        public const int sm4_decrypt = 0;
 
        private long get_ulong_be(byte[] b, int i)
        {
            long n = (long)(b[i] & 0xff) << 24 | (long)((b[i + 1] & 0xff) << 16) | (long)((b[i + 2] & 0xff) << 8) | (long)(b[i + 3] & 0xff) & 0xffffffffl;
            return n;
        }
        private void put_ulong_be(long n, byte[] b, int&nb