在用户登录和修改密码的地方,将密码直接传输到后台能看到传输密码的明文参数,所以需要加密一次。此处用RSA加密的方法,至于优缺点,我再研究。
首先定义一个RsaEncrypt公用类
public class GetRsaPublicKeyResult
{
public int Code { get; set; }
public string RsaPublicKey { get; set; }
public string Key { get; set; }
}
/// <summary>
///
/// </summary>
public class RsaEncrypt
{
/// <summary>
/// 产生一组RSA公钥、私钥
/// </summary>
/// <returns></returns>
public static Dictionary<string, string> CreateRsaKeyPair()
{
var keyPair = new Dictionary<string, string>();
var rsaProvider = new RSACryptoServiceProvider(1024);
RSAParameters parameter = rsaProvider.ExportParameters(true);
keyPair.Add("PUBLIC", BytesToHexString(parameter.Exponent) + "," + BytesToHexString(parameter.Modulus));
keyPair.Add("PRIVATE", rsaProvider.ToXmlString(true));
return keyPair;
}
/// <summary>
/// RSA解密字符串
/// </summary>
/// <param name="encryptData">密文</param>
/// <param name="privateKey">私钥</param>
/// <returns>明文</returns>
public static string DecryptRSA(string encryptData, string privateKey)
{
string decryptData = "";
try
{
var provider = new RSACryptoServiceProvider();
provider.FromXmlString(privateKey);
byte[] result = provider.Decrypt(HexStringToBytes(encryptData), false);
ASCIIEncoding enc = new ASCIIEncoding();
decryptData = enc.GetString(result);
}
catch (Exception e)
{
throw new Exception("RSA解密出错!", e);
}
return decryptData;
}
private static string BytesToHexString(byte[] input)
{
StringBuilder hexString = new StringBuilder(64);
for (int i = 0; i < input.Length; i++)
{
hexString.Append(String.Format("{0:X2}", input[i]));
}
return hexString.ToString();
}
public static byte[] HexStringToBytes(string hex)
{
if (hex.Length == 0)
{
return new byte[] { 0 };
}
if (hex.Length % 2 == 1)
{
hex = "0" + hex;
}
byte[] result = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length / 2; i++)
{
result[i] = byte.Parse(hex.Substring(2 * i, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
}
return result;
}
}
在登录的地方生成秘钥:
public ActionResult GetRsaPublicKey()
{
var rsaKeys = RsaEncrypt.CreateRsaKeyPair();
var key = Guid.NewGuid().ToString();
Session[key] = rsaKeys["PRIVATE"];
var result = new GetRsaPublicKeyResult()
{
Code = 0,
RsaPublicKey = rsaKeys["PUBLIC"],
Key = key
};
return Json(result,JsonRequestBehavior.AllowGet);
}
在对应的页面中,首先引用js,下载地址:http://www.cnblogs.com/csqb-511612371/p/4898437.html
<script src="~/Scripts/RSA/Barrett.js"></script>
<script src="~/Scripts/RSA/BigInt.js"></script>
<script src="~/Scripts/RSA/RSA.js"></script>
在登录的地方,页面加载出来时就生成秘钥,不然登录时再生成秘钥体验不太好:
var getPublicKey = function () {
var publicKey = "";
if ($.cookie("publicKey") == undefined || $.cookie("publicKey") === "null") {
$.ajax({
url: "/Login/GetRsaPublicKey",
type: "get",
contentType: "application/x-www-form-urlencoded; charset=utf-8",
async: false,
data: {},
dataType: "json",
success: function (data) {
if (data.Code == 0) {
publicKey = data.RsaPublicKey + "," + data.Key;
$.cookie("publicKey", publicKey);// 此处存储时间应该小于后台缓存时间
} else {
return null;
}
}
});
} else {
publicKey = $.cookie("publicKey");
}
return publicKey;
}
var rsaEncrypt = function (pwd) {
$.cookie("publicKey", null);
var publicKey = getPublicKey();
$.easyui.removeLoading();
setMaxDigits(129);
var rsaKey = new RSAKeyPair(publicKey.split(",")[0], "", publicKey.split(",")[1]);
var pwdRtn = encryptedString(rsaKey, pwd);
return pwdRtn + "," + publicKey.split(",")[2];
}
在登录时加密:
var rsastr= rsaEncrypt(uPwd);
参数:
txtPass: rsastr.split(",")[0],
key:rsastr.split(",")[1]
后台代码中解密:
if (Session[key]!=null)
{
var privatekey = Session[key].ToString();
txtPass = RsaEncrypt.DecryptRSA(txtPass, privatekey);
}
整个过程就完成了!