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