在程序检测中,由于不允许密码以明文的形式出现。所以需要加密存储,再解密使用。这里使用SM4和DES来制作一个案例,故制作了一个dome实现简单的加解密。
一、实验准备
1、创建Winform项目(我这里依赖.net framework)
2、NuGet包引入国密包(点击安装即可,我这里选择上面的一个)
(右击项目引用 -> 选择管理NuGet程序包 -> 点击左上角浏览,输入KYSharp.SM点击安装即可)
3、DES是System.Security.Cryptography包下的类,如果需要使用其他加密方式,DES 类 (System.Security.Cryptography) | Microsoft Learn是官网连接。
二、案例实现
1、代码展示(只需提取加密解密方法即可)
using KYSharp.SM;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private string password;
//秘钥
private string key = "Gt@3k&g8";
//初始化向量
private string iv = "25dH%7K5";
private string SM4key = "Gt@3k&g8Gt@3k&g8";
//初始化向量
private string SM4iv = "25dH%7K525dH%7K5";
private int type = 1;
private SM4Utils sM4 = new SM4Utils();
public Form1()
{
InitializeComponent();
}
//加密
private void button2_Click(object sender, EventArgs e)
{
//DES加密
if (1 == type)
{
//byte[] keyByte = Encoding.UTF8.GetBytes(key);
byte[] keyByte = UnicodeEncoding.Unicode.GetBytes(key);
byte[] ivByte = UnicodeEncoding.Unicode.GetBytes(iv);
byte[] passwordByte = UnicodeEncoding.Unicode.GetBytes(password);
using(DESCryptoServiceProvider dESCryptoServiceProvider = new DESCryptoServiceProvider())
{
Array.Resize(ref keyByte, 8);
Array.Resize(ref ivByte, 8);
dESCryptoServiceProvider.Key = keyByte;
dESCryptoServiceProvider.IV = ivByte;
ICryptoTransform transform = dESCryptoServiceProvider.CreateEncryptor();
byte[] paaswordEncodeByte = transform.TransformFinalBlock(passwordByte, 0, passwordByte.Length);
label4.Text = UnicodeEncoding.Unicode.GetString(paaswordEncodeByte);
}
}
else
{
if (sM4.secretKey == null||"".Equals(sM4.secretKey))
{
sM4.secretKey = SM4key;
sM4.iv = SM4iv;
}
string sM4PasswordEncodeStr = sM4.Encrypt_CBC(password);
label4.Text = sM4PasswordEncodeStr;
}
}
//解密
private void button3_Click(object sender, EventArgs e)
{
if (1 == type)
{
//byte[] keyByte = Encoding.UTF8.GetBytes(key);
byte[] keyByte = UnicodeEncoding.Unicode.GetBytes(key);
byte[] ivByte = UnicodeEncoding.Unicode.GetBytes(iv);
byte[] passwordByte = UnicodeEncoding.Unicode.GetBytes(label4.Text);
using (DESCryptoServiceProvider dESCryptoServiceProvider = new DESCryptoServiceProvider())
{
Array.Resize(ref keyByte, 8);
Array.Resize(ref ivByte, 8);
dESCryptoServiceProvider.Key = keyByte;
dESCryptoServiceProvider.IV = ivByte;
ICryptoTransform transform = dESCryptoServiceProvider.CreateDecryptor();
byte[] paaswordEncodeByte = transform.TransformFinalBlock(passwordByte, 0, passwordByte.Length);
label5.Text = UnicodeEncoding.Unicode.GetString(paaswordEncodeByte);
}
}
else
{
if (sM4.secretKey == null || "".Equals(sM4.secretKey))
{
sM4.secretKey = SM4key;
sM4.iv = SM4iv;
}
string sM4PasswordDecodeStr = sM4.Decrypt_CBC(label4.Text);
label5.Text = sM4PasswordDecodeStr;
}
}
private void button1_Click(object sender, EventArgs e)
{
if (type == 1)
{
this.type = 2;
label4.Text = "加密密码";
label5.Text = "解密密码";
label2.Text = "SM4";
}
else
{
this.type = 1;
label5.Text = "解密密码";
label4.Text = "加密密码";
label2.Text = "DES";
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
this.password = textBox1.Text;
}
}
}
2、结果展示
SM4结果展示
DES结果展示
3、SM4的秘钥(代码中SM4key)是128位(16字节),偏移量(即随机数,一般随机生成)和秘钥相同。秘钥和偏移量均可大小写字母、数字和特殊字符组成。SM4有两种模式(CBC、DCB),我这里选择CBC模式。
三、总结
1、由于时间有限,并没有过多研究加解密。在案例中使用的是对称加密的方式,在国内SM4是不错的选择。
2、案例中DES加密,虽然能够成功加解密,但加密后输出的是乱码文字(可能是使用Unicode编码造成,没有过多研究)。
3、案例中秘钥和偏移量是设置固定值,也可以随机生成。