SM2非对称算法加解密

时间:2023-02-02 21:11:50

作者:彭金龙   原文地址:http://www.jonllen.cn/jonllen/work/164.aspx

在前面文章我们已经可以制作SM2证书了,主要应用了SM2签名验证算法和SM3摘要算法,在本文中主要介绍SM2公钥加密算法。这里我们使用SM2数字证书来做SM2非对称加密,然后使用硬件加密设备做解密,比如加密文件只能由指定的智能密码钥匙UKey才能解开。

SM2加密算法

SM2加密同样使用接收方公钥加密,公钥由一个曲线坐标点组成,在X.509证书中的共钥表示为04标记开始的2个32byte的BigInteger,即曲线点P(x,y)。SM2公钥加密算法比RSA相对复杂,加密结果由3个部分组成,SM2加密过程中使用了随机数,因此同样的明文数据每一次加密结果都不一样。SM2加密算法流程如下图所示。

SM2非对称算法加解密

根据国密推荐的SM2椭圆曲线公钥密码算法,首先产生随机数计算出曲线点C1,2个32byte的BigInteger大数,即为SM2加密结果的第1部分。第2部分则是真正的密文,是对明文的加密结果,长度和明文一样。第3部分是杂凑值,用来效验数据。按国密推荐的256位椭圆曲线,明文加密结果比原长度会大96byte。

SM2加密算法同样也可以基于使用BouncyCastle库实现。一般使用数字证书来标识身份,同时使用证书中公钥加密数据。如下SM2Cipher类是C#下SM2软算法实现。

 
SM2非对称算法加解密SM2Cipher.cs
1 SM2非对称算法加解密public class SM2Cipher 2 SM2非对称算法加解密 { 3SM2非对称算法加解密private int ct = 1; 4SM2非对称算法加解密 5SM2非对称算法加解密private ECPoint p2; 6SM2非对称算法加解密private SM3Digest sm3keybase; 7SM2非对称算法加解密private SM3Digest sm3c3; 8SM2非对称算法加解密 9SM2非对称算法加解密private byte[] key = new byte[32]; 10SM2非对称算法加解密private byte keyOff = 0; 11SM2非对称算法加解密 12SM2非对称算法加解密public SM2Cipher() { } 13SM2非对称算法加解密 14SM2非对称算法加解密 15SM2非对称算法加解密 16SM2非对称算法加解密private void Reset() 17SM2非对称算法加解密{ 18SM2非对称算法加解密 sm3keybase = new SM3Digest(); 19SM2非对称算法加解密 sm3c3 = new SM3Digest(); 20SM2非对称算法加解密 21SM2非对称算法加解密byte[] p; 22SM2非对称算法加解密 23SM2非对称算法加解密 p = p2.X.ToBigInteger().ToByteArrayUnsigned(); 24SM2非对称算法加解密 sm3keybase.BlockUpdate(p, 0, p.Length); 25SM2非对称算法加解密 sm3c3.BlockUpdate(p, 0, p.Length); 26SM2非对称算法加解密 27SM2非对称算法加解密 p = p2.Y.ToBigInteger().ToByteArrayUnsigned(); 28SM2非对称算法加解密 sm3keybase.BlockUpdate(p, 0, p.Length); 29SM2非对称算法加解密 30SM2非对称算法加解密 ct = 1; 31SM2非对称算法加解密 NextKey(); 32SM2非对称算法加解密 } 33SM2非对称算法加解密 34SM2非对称算法加解密private void NextKey() 35SM2非对称算法加解密{ 36SM2非对称算法加解密 SM3Digest sm3keycur = new SM3Digest(sm3keybase); 37SM2非对称算法加解密 sm3keycur.Update((byte)(ct >> 24 & 0x00ff)); 38SM2非对称算法加解密 sm3keycur.Update((byte)(ct >> 16 & 0x00ff)); 39SM2非对称算法加解密 sm3keycur.Update((byte)(ct >> 8 & 0x00ff)); 40SM2非对称算法加解密 sm3keycur.Update((byte)(ct & 0x00ff)); 41SM2非对称算法加解密 sm3keycur.DoFinal(key, 0); 42SM2非对称算法加解密 keyOff = 0; 43SM2非对称算法加解密 ct++; 44SM2非对称算法加解密 } 45SM2非对称算法加解密 46SM2非对称算法加解密public virtual ECPoint InitEncipher(ECPoint userKey) 47SM2非对称算法加解密{ 48SM2非对称算法加解密 BigInteger k = null; 49SM2非对称算法加解密 ECPoint c1 = null; 50SM2非对称算法加解密 51SM2非对称算法加解密if (1==1) 52SM2非对称算法加解密{ 53SM2非对称算法加解密 AsymmetricCipherKeyPair key = SM2CryptoServiceProvider.SM2KeyPairGenerator.GenerateKeyPair(); 54SM2非对称算法加解密 ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private; 55SM2非对称算法加解密 ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public; 56SM2非对称算法加解密 57SM2非对称算法加解密 k = ecpriv.D; 58SM2非对称算法加解密 c1 = ecpub.Q; 59SM2非对称算法加解密 } 60SM2非对称算法加解密 61SM2非对称算法加解密 p2 = userKey.Multiply(k); 62SM2非对称算法加解密 Reset(); 63SM2非对称算法加解密 64SM2非对称算法加解密return c1; 65SM2非对称算法加解密 66SM2非对称算法加解密 } 67SM2非对称算法加解密 68SM2非对称算法加解密public virtual void Encrypt(byte[] data) 69SM2非对称算法加解密{ 70SM2非对称算法加解密 sm3c3.BlockUpdate(data, 0, data.Length); 71SM2非对称算法加解密for (int i = 0; i < data.Length; i++) 72SM2非对称算法加解密{ 73SM2非对称算法加解密if (keyOff == key.Length) 74SM2非对称算法加解密 NextKey(); 75SM2非对称算法加解密 76SM2非对称算法加解密 data[i] ^= key[keyOff++]; 77SM2非对称算法加解密 } 78SM2非对称算法加解密 } 79SM2非对称算法加解密 80SM2非对称算法加解密public virtual void InitDecipher(BigInteger userD, ECPoint c1) 81SM2非对称算法加解密{ 82SM2非对称算法加解密 p2 = c1.Multiply(userD); 83SM2非对称算法加解密 Reset(); 84SM2非对称算法加解密 } 85SM2非对称算法加解密 86SM2非对称算法加解密public virtual void Decrypt(byte[] data) 87SM2非对称算法加解密{ 88SM2非对称算法加解密for (int i = 0; i < data.Length; i++) 89SM2非对称算法加解密{ 90SM2非对称算法加解密if (keyOff == key.Length) 91SM2非对称算法加解密 NextKey(); 92SM2非对称算法加解密 93SM2非对称算法加解密 data[i] ^= key[keyOff++]; 94SM2非对称算法加解密 } 95SM2非对称算法加解密 sm3c3.BlockUpdate(data, 0, data.Length); 96SM2非对称算法加解密 } 97SM2非对称算法加解密 98SM2非对称算法加解密public virtual void Dofinal(byte[] c3) 99SM2非对称算法加解密{100SM2非对称算法加解密byte[] p = p2.Y.ToBigInteger().ToByteArrayUnsigned();101SM2非对称算法加解密 sm3c3.BlockUpdate(p, 0, p.Length);102SM2非对称算法加解密 sm3c3.DoFinal(c3, 0);103SM2非对称算法加解密 Reset();104SM2非对称算法加解密 }105SM2非对称算法加解密106SM2非对称算法加解密107SM2非对称算法加解密/// <summary>108SM2非对称算法加解密/// 使用SM2公钥加密数据109SM2非对称算法加解密/// </summary>110SM2非对称算法加解密/// <param name="pubKey"></param>111SM2非对称算法加解密/// <param name="plaintext"></param>112SM2非对称算法加解密/// <returns></returns>113SM2非对称算法加解密 public string Encrypt(ECPoint pubKey, byte[] plaintext)114SM2非对称算法加解密{115SM2非对称算法加解密116SM2非对称算法加解密byte[] data = new byte[plaintext.Length];117SM2非对称算法加解密 Array.Copy(plaintext, data, plaintext.Length);118SM2非对称算法加解密119SM2非对称算法加解密 ECPoint c1 = InitEncipher(pubKey);120SM2非对称算法加解密 Encrypt(data);121SM2非对称算法加解密122SM2非对称算法加解密byte[] c3 = new byte[32];123SM2非对称算法加解密 Dofinal(c3);124SM2非对称算法加解密125SM2非对称算法加解密string hexString = c1.X.ToBigInteger().ToString(16) + c1.Y.ToBigInteger().ToString(16)126SM2非对称算法加解密+ Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(data)127SM2非对称算法加解密+ Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(c3);128SM2非对称算法加解密129SM2非对称算法加解密return hexString;130SM2非对称算法加解密131SM2非对称算法加解密 }132SM2非对称算法加解密133SM2非对称算法加解密/// <summary>134SM2非对称算法加解密/// 使用SM2解密数据135SM2非对称算法加解密/// </summary>136SM2非对称算法加解密/// <param name="privateKey"></param>137SM2非对称算法加解密/// <param name="ciphertext"></param>138SM2非对称算法加解密/// <returns></returns>139SM2非对称算法加解密 public byte[] Decrypt(BigInteger privateKey, string ciphertext)140SM2非对称算法加解密{141SM2非对称算法加解密142SM2非对称算法加解密string hexString = ciphertext;143SM2非对称算法加解密string c1X = hexString.Substring(0, 64);144SM2非对称算法加解密string c1Y = hexString.Substring(0 + c1X.Length, 64);145SM2非对称算法加解密string encrypData = hexString.Substring(c1X.Length + c1Y.Length, hexString.Length - c1X.Length - c1Y.Length - 64);146SM2非对称算法加解密string c3 = hexString.Substring(hexString.Length - 64);147SM2非对称算法加解密148SM2非对称算法加解密byte[] data = SM2CryptoServiceProvider.StrToToHexByte(encrypData);149SM2非对称算法加解密150SM2非对称算法加解密 ECPoint c1 = CreatePoint(c1X, c1Y);151SM2非对称算法加解密152SM2非对称算法加解密 InitDecipher(privateKey, c1);153SM2非对称算法加解密 Decrypt(data);154SM2非对称算法加解密155SM2非对称算法加解密byte[] c3_ = new byte[32];156SM2非对称算法加解密 Dofinal(c3_);157SM2非对称算法加解密158SM2非对称算法加解密string decryptData = Encoding.Default.GetString(data);159SM2非对称算法加解密bool isDecrypt = Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(c3_) == c3;160SM2非对称算法加解密161SM2非对称算法加解密return (isDecrypt ? data : new byte[0]);162SM2非对称算法加解密 }163SM2非对称算法加解密164SM2非对称算法加解密165SM2非对称算法加解密/// <summary>166SM2非对称算法加解密/// 创建坐标点167SM2非对称算法加解密/// </summary>168SM2非对称算法加解密/// <param name="x"></param>169SM2非对称算法加解密/// <param name="y"></param>170SM2非对称算法加解密/// <returns></returns>171SM2非对称算法加解密 public static ECPoint CreatePoint(string x, string y)172SM2非对称算法加解密{173SM2非对称算法加解密174SM2非对称算法加解密 BigInteger biX = new BigInteger(x, 16);175SM2非对称算法加解密 BigInteger biY = new BigInteger(y, 16);176SM2非对称算法加解密 ECFieldElement fx = new FpFieldElement(SM2CryptoServiceProvider.ecc_p, biX);177SM2非对称算法加解密 ECFieldElement fy = new FpFieldElement(SM2CryptoServiceProvider.ecc_p, biY);178SM2非对称算法加解密 ECPoint point = new FpPoint(SM2CryptoServiceProvider.ecc_curve, fx,fy);179SM2非对称算法加解密return point;180SM2非对称算法加解密 }181SM2非对称算法加解密182SM2非对称算法加解密183SM2非对称算法加解密184SM2非对称算法加解密}

SM2解密算法

SM2解密算法是加密逆运算。首先需要从密文中取出加密结果的3部分值,然后通过私钥计算出 M'明文值,最后效验数据。SM2解密算法流程如下图所示。 

SM2非对称算法加解密

 SM2解密同样也可以使用软算法实现。但因为涉及到私钥运算,为保护私钥安全,建议在硬件设备中运行,例如UKey等存储介质这样可以更好的保护密钥安全。拿文件加密来说,首先拿UKey里面的加密证书加密,这部分可在应用系统内完成。解密的话则需要加密证书对应UKey才能做解密,由应用系统调用UKey解密接口,在物理硬件内完成数据解密,同时可以受设备Ping码保护。

附:SM2算法加解密在线测试工具