RSA:非对称加密算法


关于RSA,简单解释一下原理:

  1. 乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。

  2. 甲方获取乙方的公钥,然后用它对信息加密。

  3. 乙方得到加密后的信息,用私钥解密。

对比手中项目的实践如下:

  1. 使用公钥同时加密站点数与服务器MAC地址

  2. 将获取的站点加密与MAC加密保存数据库

  3. 将私钥与程序一起发布,保留公钥

  4. 登陆使用私钥解密数据库中加密信息

代码片段如下:

private void btnGenerate_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txbHospitalName.Text.Trim()) || string.IsNullOrEmpty(txbStationCount.Text.Trim()))
{
MessageBox.Show("请输入医院名称和站点数");
return;
}
string strHospitalName = txbHospitalName.Text.Trim();
int countStation = 0;
if (!int.TryParse(txbStationCount.Text.Trim(), out countStation))
{
MessageBox.Show("站点数格式不正确");
return;
}
if (countStation <= 0)
{
MessageBox.Show("站点数数量不正确");
return;
}

TargetPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strHospitalName);
listTargetPath.Clear();
listTargetPath.Add(TargetPath);
listTargetPath.Add(Path.Combine(ServerPath, strHospitalName));
Tools.CreateRSAKeys(listTargetPath, PrivateKeyFileName, PublicKeyFileName);
string publicKey = Path.Combine(TargetPath, PublicKeyFileName);
string stationCountRSA = Tools.RSAEncrypt(countStation.ToString(), publicKey);
string serverMacRSA = Tools.RSAEncrypt(GetInputMac(), publicKey);

rtbStationInfo.Text = stationCountRSA;
rtbServerMac.Text = serverMacRSA;
CommonBLL<MacInfo> MacinfoBLL = new CommonBLL<MacInfo>();
MacInfo authorization = new MacInfo()
{
    AppId = (int)(Station.Unknow),
    StationInfo = txbStationCount.Text,
    HospitalName = txbHospitalName.Text,
    ServerMac = GetInputMac(),
    Remark=richremark.Text
};
MacinfoBLL.Save(authorization);
new NotifyHelper().ShowNotify("保存成功");

//私钥跟程序放一起 公钥放服务器保留
File.Delete(publicKey);
//把要存数据库的内容写成文件
FileStream fs = new FileStream(TargetPath + "\\StationInfo.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(stationCountRSA);
sw.Close();
fs = new FileStream(TargetPath + "\\ServerMac.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
sw = new StreamWriter(fs);
sw.WriteLine(serverMacRSA);
sw.Close();
fs = new FileStream(TargetPath + "\\HospitalName.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
sw = new StreamWriter(fs);
sw.WriteLine(strHospitalName);
sw.Close();
//打开目录
System.Diagnostics.Process.Start(TargetPath);
}

上诉代码中使用到一个工具类,代码片段如下::

// <summary>
/// 使用RSA实现解密,通过配置文件读取私钥
/// 产品中只保留解密方法,加密和产生密钥的方法内部使用即可保证产品无法通过反编译再解密的手段破解
/// </summary>
/// <param name="data">解密数据</param>
/// <returns></returns>
public static string RSADecrypt(string data)
{
try
{
string privateKeyPath = ConfigurationManager.AppSettings["KeyPath"];
if (string.IsNullOrEmpty(privateKeyPath))
{
throw new Exception("未能找到应用配置KeyPath节点");
}
//创建RSA对象并载入[私钥]
var rsaPrivate = new RSACryptoServiceProvider();
rsaPrivate.FromXmlString(File.ReadAllText(privateKeyPath));
//对数据进行解密
return Encoding.UTF8.GetString(rsaPrivate.Decrypt(Convert.FromBase64String(data), false));
}
catch (Exception)
{
//返回任意无法猜测的文本即可,拿去校验时一定无法和rsa后的密文匹配上
return new Guid().ToString();
}
}

public static string RSADecrypt(string data, string privateKey)
{
try
{
if (string.IsNullOrEmpty(privateKey))
{
throw new Exception("未能找到应用配置KeyPath节点");
}
//创建RSA对象并载入[私钥]
var rsaPrivate = new RSACryptoServiceProvider();
rsaPrivate.FromXmlString(privateKey);
//对数据进行解密
return Encoding.UTF8.GetString(rsaPrivate.Decrypt(Convert.FromBase64String(data), false));
}
catch (Exception)
{
//返回任意无法猜测的文本即可,拿去校验时一定无法和rsa后的密文匹配上
return new Guid().ToString();
}
}

emmm~

只是对RSA在项目中运用做一个简单的笔记。