Skip to content

Commit

Permalink
重新调式SM2加密和解密算法,增加了Hex.encode() 和Hex.decode()
Browse files Browse the repository at this point in the history
  • Loading branch information
njk888 committed Nov 3, 2018
1 parent 8425e70 commit c6aaa9b
Show file tree
Hide file tree
Showing 19 changed files with 1,563 additions and 1,619 deletions.
1,246 changes: 0 additions & 1,246 deletions SM2.cs

This file was deleted.

22 changes: 22 additions & 0 deletions SM2Crypto.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SM2Crypto", "SM2Crypto\SM2Crypto.csproj", "{DFC19643-ABE0-49F7-A087-31314B742408}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DFC19643-ABE0-49F7-A087-31314B742408}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DFC19643-ABE0-49F7-A087-31314B742408}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DFC19643-ABE0-49F7-A087-31314B742408}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DFC19643-ABE0-49F7-A087-31314B742408}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
6 changes: 6 additions & 0 deletions SM2Crypto/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
94 changes: 94 additions & 0 deletions SM2Crypto/Lib/ByteUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System;
using System.Globalization;
using System.Text;

namespace SM2Crypto.Lib
{
/// <summary>
/// 字节数组操作扩展类
/// </summary>
static class ByteUtils
{
internal static byte[] AsciiBytes(string s)
{
byte[] bytes = new byte[s.Length];

for (int i = 0; i < s.Length; i++)
{
bytes[i] = (byte)s[i];
}

return bytes;
}

internal static byte[] HexToByteArray(this string hexString)
{
byte[] bytes = new byte[hexString.Length / 2];

for (int i = 0; i < hexString.Length; i += 2)
{
string s = hexString.Substring(i, 2);
bytes[i / 2] = byte.Parse(s, NumberStyles.HexNumber, null);
}

return bytes;
}

internal static string ByteArrayToHex(this byte[] bytes)
{
StringBuilder builder = new StringBuilder(bytes.Length * 2);

foreach (byte b in bytes)
{
builder.Append(b.ToString("X2"));
}

return builder.ToString();
}

internal static string ByteArrayToHex(this byte[] bytes, int len)
{
return ByteArrayToHex(bytes).Substring(0, len * 2);
}

internal static byte[] RepeatByte(byte b, int count)
{
byte[] value = new byte[count];

for (int i = 0; i < count; i++)
{
value[i] = b;
}

return value;
}

internal static byte[] SubBytes(this byte[] bytes, int startIndex, int length )
{
byte[] res = new byte[length];
Array.Copy(bytes, startIndex, res, 0, length);
return res;
}

internal static byte[] XOR(this byte[] value)
{
byte[] res = new byte[value.Length];
for (int i = 0; i < value.Length; i++)
{
res[i] ^= value[i];
}
return res;
}

internal static byte[] XOR(this byte[] valueA, byte[] valueB)
{
int len = valueA.Length;
byte[] res = new byte[len];
for (int i = 0; i < len; i++)
{
res[i] = (byte)(valueA[i] ^ valueB[i]);
}
return res;
}
}
}
136 changes: 136 additions & 0 deletions SM2Crypto/Lib/Chiper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.Text;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;

namespace SM2Crypto.Lib
{
public class Cipher
{
private int ct;
private ECPoint p2;
private SM3Digest sm3keybase;
private SM3Digest sm3c3;
private byte[] key;
private byte keyOff;

public Cipher()
{
this.ct = 1;
this.key = new byte[32];
this.keyOff = 0;
}

public static byte[] byteConvert32Bytes(BigInteger n)
{
byte[] tmpd = null;
if (n == null)
{
return null;
}

if (n.ToByteArray().Length == 33)
{
tmpd = new byte[32];
Array.Copy(n.ToByteArray(), 1, tmpd, 0, 32);
}
else if (n.ToByteArray().Length == 32)
{
tmpd = n.ToByteArray();
}
else
{
tmpd = new byte[32];
for (int i = 0; i < 32 - n.ToByteArray().Length; i++)
{
tmpd[i] = 0;
}
Array.Copy(n.ToByteArray(), 0, tmpd, 32 - n.ToByteArray().Length, n.ToByteArray().Length);
}
return tmpd;
}

private void Reset()
{
this.sm3keybase = new SM3Digest();
this.sm3c3 = new SM3Digest();

byte[] p = byteConvert32Bytes(p2.Normalize().XCoord.ToBigInteger());
this.sm3keybase.BlockUpdate(p, 0, p.Length);
this.sm3c3.BlockUpdate(p, 0, p.Length);

p = byteConvert32Bytes(p2.Normalize().YCoord.ToBigInteger());
this.sm3keybase.BlockUpdate(p, 0, p.Length);
this.ct = 1;
NextKey();
}

private void NextKey()
{
SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);
sm3keycur.Update((byte)(ct >> 24 & 0xff));
sm3keycur.Update((byte)(ct >> 16 & 0xff));
sm3keycur.Update((byte)(ct >> 8 & 0xff));
sm3keycur.Update((byte)(ct & 0xff));
sm3keycur.DoFinal(key, 0);
this.keyOff = 0;
this.ct++;
}

public ECPoint Init_enc(SM2 sm2, ECPoint userKey)
{
AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.GenerateKeyPair();
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;
ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;
BigInteger k = ecpriv.D;
ECPoint c1 = ecpub.Q;
this.p2 = userKey.Multiply(k);
Reset();
return c1;
}

public void Encrypt(byte[] data)
{
this.sm3c3.BlockUpdate(data, 0, data.Length);
for (int i = 0; i < data.Length; i++)
{
if (keyOff == key.Length)
{
NextKey();
}
data[i] ^= key[keyOff++];
}
}

public void Init_dec(BigInteger userD, ECPoint c1)
{
this.p2 = c1.Multiply(userD);
Reset();
}

public void Decrypt(byte[] data)
{
for (int i = 0; i < data.Length; i++)
{
if (keyOff == key.Length)
{
NextKey();
}
data[i] ^= key[keyOff++];
}

this.sm3c3.BlockUpdate(data, 0, data.Length);
}

public void Dofinal(byte[] c3)
{
byte[] p = byteConvert32Bytes(p2.Normalize().YCoord.ToBigInteger());
this.sm3c3.BlockUpdate(p, 0, p.Length);
this.sm3c3.DoFinal(c3, 0);
Reset();
}
}
}
124 changes: 124 additions & 0 deletions SM2Crypto/Lib/SM2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.Text;
using Org.BouncyCastle.Crypto.Digests;

namespace SM2Crypto.Lib
{
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.AffineXCoord.ToBigInteger().ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = userKey.AffineYCoord.ToBigInteger().ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);

// Z
byte[] md = new byte[sm3.GetDigestSize()];
sm3.DoFinal(md, 0);

return md;
}
}
}
Loading

0 comments on commit c6aaa9b

Please sign in to comment.