【.NET Core】加解密
概述
编码、加密、哈希的区别
- 编码:是信息从一种形式或格式转换成另一种的过程,是可逆的。如:url编码、base64、utf-8
- 加密:是可逆的,通过特定的秘钥加解密,加解密算法算法有两种:对称加密、非对称加密
- 哈希:也叫散列,把任意长度的数据转换成固定长度的指纹,过程不可逆
Hash算法
MD5、SHA系列(1、224、256、384、512)……
无论消息有多长,计算出的摘要长度都是固定的
用途:文件校验、数字签名(防篡改),建议用SHA系列
Hmac算法
为了防止黑客通过彩虹表根据哈希值反推原始口令,在计算哈希的时候,不能仅针对原始输入计算,需要增加一个salt来使得相同的输入也能得到不同的哈希,这样,大大增加了黑客破解的难度。
如果salt是我们自己随机生成的,通常我们计算MD5时采用md5(message + salt)
,这实际上就是Hmac算法。Hmac通过一个标准算法,在计算哈希的过程中,把key混入计算过程中。采用Hmac替代我们自己的salt算法,可以使程序算法更标准化,也更安全。
Hmac算法针对所有哈希算法都通用,如:HMAC-MD5
、HMAC-SHA1
、HMAC-SHA256
、HMAC-SHA384
...
对称加密算法
AES(也称为Rijndael)、DES、3DES、IDEA、RC2、RC4、SKIPJACKTripleDES 算法……
加解密使用相同密钥,这个是对称加密。对称加密相比非对称加密优点是速度快
DES已破解,被AES取代,弃用
3DES有安全漏洞,弃用
非对称加密算法
RSA、DSA、DH、ECC、EL GAMAL……
公钥加密数据,然后私钥解密的情况被称为加密解密;
因为公钥加密的数据只有它相对应的私钥可以解开,所以你可以把公钥给人和人,让他加密他想要传送给你的数据,这个数据只有到了有私钥的你这里,才可以解开成有用的数据,其他人就是得到了,也看懂内容
实际应用中,一般都是和对方交换公钥,然后你要发给对方的数据,用他的公钥加密,他得到后用他的私钥解密,他要发给你的数据,用你的公钥加密,你得到后用你的私钥解密,这样最大程度保证了安全性.
缺点:速度慢
RSA签名、验签
上面的Hash算法属于对称签名,RSA签名是非对称签名
私钥签名和公钥验证签名;如果你用你的私钥对数据进行签名,那这个数据就只有配对的公钥可以解开,有这个私钥的只有你,所以如果配对的公钥解开了数据,就说明这数据是你发的,相反,则不是.这个被称为签名。数字签名的意义就是这些数据与原文数据比对是否修改过。
算法实现
各种算法微软都有实现,都是基于 System.Security.Cryptography.Algorithms
这个程序集实现的。
文档地址:https://docs.microsoft.com/zh-cn/dotnet/api/system.security.cryptography?view=netcore-3.1
源码地址:https://github.com/dotnet/corefx/tree/master/src/System.Security.Cryptography.Algorithms
Hash
//MD5
{
var srcString = "fan001";
//(和后面开源库的实现相比多了些 -,可以利用replace去掉)
var md5 = MD5.Create();
byte[] result = md5.ComputeHash(Encoding.UTF8.GetBytes(srcString));
string md5String= BitConverter.ToString(result).Replace("-","");
}
//SHA系列
{
var srcString = "fan001";
//SHA-256,SHA-384 和 SHA-512 用法类似(和后面开源库的实现相比多了些-,可以利用replace去掉)
var sha1 = SHA1.Create();
byte[] result = sha1.ComputeHash(Encoding.UTF8.GetBytes(srcString));
string sha1HashString = BitConverter.ToString(result).Replace("-", "");
}
HMAC
//HMAC相关
{
var secretKey = "sflkasfkksfs";
var srcString = "fan001";
//HMAC-SHA384、HMAC-SHA512的用法类似 (和后面开源库的实现相比多了些-,可以利用replace去掉)
HMACSHA1 hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secretKey));
HMACSHA256 hmacsha2 = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey));
byte[] bytes1 = hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(srcString));
byte[] bytes2 = hmacsha2.ComputeHash(Encoding.UTF8.GetBytes(srcString));
string hmacSha1String = BitConverter.ToString(bytes1).Replace("-", "");
string hmacSha2String = BitConverter.ToString(bytes2).Replace("-", "");
}
对称加密
DesEncrypt
public class DesEncrypt
{
//8位长度
private static byte[] rgbKey = ASCIIEncoding.ASCII.GetBytes("ioeruwoe"); //密钥(转为byte数组)
private static byte[] rgbIV = ASCIIEncoding.ASCII.GetBytes("fan00001"); //矢量(配合密钥更加安全)
#region 01-DES加密
/// <summary>
/// DES 加密
/// </summary>
/// <param name="strValue">需要加密的字符串</param>
/// <returns></returns>
public static string Encrypt(string strValue)
{
DESCryptoServiceProvider dsp = new DESCryptoServiceProvider();
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream crypStream = new CryptoStream(memStream, dsp.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
byte[] buffer = Encoding.Default.GetBytes(strValue);
crypStream.Write(buffer, 0, buffer.Length);
crypStream.FlushFinalBlock();
memStream.Flush();
return Convert.ToBase64String(memStream.GetBuffer(), 0, (int)memStream.Length);
}
}
#endregion
#region 02-DES解密
/// <summary>
/// DES解密
/// </summary>
/// <param name="EncValue">加密后的结果</param>
/// <returns></returns>
public static string Decrypt(string EncValue)
{
DESCryptoServiceProvider dsp = new DESCryptoServiceProvider();
byte[] buffer = Convert.FromBase64String(EncValue);
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream crypStream = new CryptoStream(memStream, dsp.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
crypStream.Write(buffer, 0, buffer.Length);
crypStream.FlushFinalBlock();
return ASCIIEncoding.UTF8.GetString(memStream.ToArray());
}
}
#endregion
}
//DES算法
{
//具体实现详见:DesEncrypt
string msg1 = "mr1";
//密钥写在DesEncrypt类中了
string result1 = DesEncrypt.Encrypt(msg1);
string result2 = DesEncrypt.Decrypt(result1);
}
非对称加密
另一篇文章
Core版算法开源库
说明:通过Nuget安装:Install-Package NETCore.Encrypt
包括的算法有:Base64
、MD5
、SHA系列
、HAMC系列
、AES
、DES
、RSA
。
PS:还支持
MD5
、SHA系列
、HMAC系列
对于String类型
的扩展,如:var hashed3 = "fan".MD5()
; 大部分算法支持string
和byte[]
两种格式。
案例
{
//1. Base64的编码和解码
var srcString = "fan001";
var hashed1 = EncryptProvider.Base64Encrypt(srcString); //default encoding is UTF-8
var hashed2 = EncryptProvider.Base64Encrypt(srcString, Encoding.ASCII); //按照ascii进行编码
var strValue1 = EncryptProvider.Base64Decrypt(hashed1); //default encoding is UTF-8
var strValue2 = EncryptProvider.Base64Decrypt(hashed2, Encoding.ASCII); //按照ascii进行解码
}
{
//2. MD5
var srcString = "fan001";
var hashed1 = EncryptProvider.Md5(srcString); //默认32位
var hashed2 = EncryptProvider.Md5(srcString, MD5Length.L16); //16位
Console.WriteLine($"fan001的MD5加密(32位):{hashed1}");
Console.WriteLine($"fan002的MD5加密(64位):{hashed2}");
//扩展用法
var hashed3 = srcString.MD5();
}
{
//3. SHA相关
var srcString = "fan001";
var hashed1 = EncryptProvider.Sha1(srcString);
var hashed2 = EncryptProvider.Sha256(srcString);
var hashed3 = EncryptProvider.Sha384(srcString);
var hashed4 = EncryptProvider.Sha512(srcString);
//扩展用法(如下,其余类似)
var extHash = srcString.SHA1();
}
{
//4. HAMC相关
var secretKey = "sflkasfkksfs";
var srcString = "fan001";
var hashed1 = EncryptProvider.HMACMD5(srcString, secretKey);
var hashed2 = EncryptProvider.HMACSHA1(srcString, secretKey);
var hashed3 = EncryptProvider.HMACSHA256(srcString, secretKey);
var hashed4 = EncryptProvider.HMACSHA384(srcString, secretKey);
var hashed5 = EncryptProvider.HMACSHA512(srcString, secretKey);
//扩展用法(如下,其余类似)
var extHash = srcString.HMACSHA1(secretKey);
}
{
//5. AES
//利用算法生成key和iv(32位和16位),当然这里可以自己指定并保存好
//var aesKey = EncryptProvider.CreateAesKey();
//var key = aesKey.Key;
//var iv = aesKey.IV;
var secretKey = "asdfjketjnddkkaakkuyerbdsbgrtsaw"; //这里的key得32位
var iv = "ioeruwoeruo2aqwe"; //加密和解密的过程中可以加上iv矢量,使其安全性更高,这里的iv得16位
var srcString = "fan001";
//加密
var encrypted1 = EncryptProvider.AESEncrypt(srcString, secretKey);
var encrypted2 = EncryptProvider.AESEncrypt(srcString, secretKey, iv);
//解密
var decrypted1 = EncryptProvider.AESDecrypt(encrypted1, secretKey);
var decrypted2 = EncryptProvider.AESDecrypt(encrypted2, secretKey, iv);
//PS:这里除了string加密,还可以对byte数组加密
}
{
//6. DES
//利用算法生成key(24位),当然这里可以自己指定并保存好
//var desKey = EncryptProvider.CreateDesKey();
var secretKey = "asdfjketjnddkkaakkuyerbd"; //这里的key得24位
var srcString = "fan001";
//加密
var encrypted1 = EncryptProvider.DESEncrypt(srcString, secretKey);
//解密
var decrypted1 = EncryptProvider.DESDecrypt(encrypted1, secretKey);
//PS:这里除了string加密,还可以对byte数组加密
}
{
//7.RSA
//利用算法生成公钥和私钥,然后保存;当然这里可以自己指定并保存好
var rsaKey = EncryptProvider.CreateRsaKey(); //default is 2048
// var rsaKey = EncryptProvider.CreateRsaKey(RsaSize.R3072);
var publicKey = rsaKey.PublicKey;
var privateKey = rsaKey.PrivateKey;
var srcString = "fan001";
//加密
var encrypted1 = EncryptProvider.RSAEncrypt(publicKey, srcString); //公钥加密
//解密
var decrypted = EncryptProvider.RSADecrypt(privateKey, encrypted1); //私钥解密
}
public enum RsaSize
{
R2048 = 2048,
R3072 = 3072,
R4096 = 4096
}
助手类封装
点击查看代码
/// <summary>
/// 各种加密解密算法
/// 依赖程序集【NETCore.Encrypt】
/// </summary>
public class SecurityHelp
{
/// <summary>
/// Base64编码
/// </summary>
/// <param name="srcString">需要编码的字符串</param>
/// <returns></returns>
public static string Base64Encrypt(string srcString)
{
return EncryptProvider.Base64Encrypt(srcString); //default encoding is UTF-8
}
/// <summary>
/// Base64编码
/// </summary>
/// <param name="encString">需要解码的字符串</param>
/// <returns></returns>
public static string Base64Decrypt(string encString)
{
return EncryptProvider.Base64Decrypt(encString); //default encoding is UTF-8
}
/// <summary>
/// MD5加密
/// </summary>
/// <param name="srcString">需要加密的字符串</param>
/// <param name="num">位数,默认为32位,也可以是16位</param>
/// <returns></returns>
public static string Md5(string srcString, int num = 32)
{
if (num == 32)
{
return EncryptProvider.Md5(srcString); //默认32位
}
else
{
return EncryptProvider.Md5(srcString, MD5Length.L16); //16位
}
}
/// <summary>
/// SHA系列算法
/// </summary>
/// <param name="srcString">需要加密的字符串</param>
/// <param name="kind">类型</param>
/// <returns></returns>
public static string SHA(string srcString, string kind = "Sha512")
{
if (kind.Equals("Sha1"))
{
return EncryptProvider.Sha1(srcString);
}
else if (kind.Equals("Sha256"))
{
return EncryptProvider.Sha256(srcString);
}
else if (kind.Equals("Sha384"))
{
return EncryptProvider.Sha384(srcString);
}
else
{
return EncryptProvider.Sha512(srcString);
}
}
/// <summary>
/// HMAC系列算法
/// </summary>
/// <param name="srcString">需要加密的字符串</param>
/// <param name="secretKey">密钥</param>
/// <param name="kind">类型</param>
/// <returns></returns>
public static string HMAC(string srcString, string secretKey, string kind = "HMACSHA512")
{
if (kind.Equals("HMACMD5"))
{
return EncryptProvider.HMACMD5(srcString, secretKey);
}
else if (kind.Equals("HMACSHA1"))
{
return EncryptProvider.HMACSHA1(srcString, secretKey);
}
else if (kind.Equals("HMACSHA256"))
{
return EncryptProvider.HMACSHA256(srcString, secretKey);
}
else if (kind.Equals("HMACSHA384"))
{
return EncryptProvider.HMACSHA384(srcString, secretKey);
}
else
{
return EncryptProvider.HMACSHA512(srcString, secretKey);
}
}
/// <summary>
/// 生成AES算法所需的Key和iv
/// (当然这里可以自己指定并保存好)
/// </summary>
/// <param name="key">加密所需的key</param>
/// <param name="iv">加密所需的矢量</param>
public static void CreateAesKey(ref string key, ref string iv)
{
//利用算法生成key和iv(32位和16位),当然这里可以自己指定并保存好
var aesKey = EncryptProvider.CreateAesKey();
key = aesKey.Key;
iv = aesKey.IV;
}
/// <summary>
/// AES加密算法
/// </summary>
/// <param name="srcString">需要加密的字符串</param>
/// <param name="secretKey">密钥</param>
/// <param name="iv">矢量(可以不填)</param>
/// <returns></returns>
public static string AESEncrypt(string srcString, string secretKey, string iv = "")
{
if (string.IsNullOrEmpty(iv))
{
return EncryptProvider.AESEncrypt(srcString, secretKey); //表示不需要iv矢量的AES加密算法
}
else
{
return EncryptProvider.AESEncrypt(srcString, secretKey, iv); //表示需要iv矢量的AES加密算法
}
}
/// <summary>
/// AES解密算法
/// </summary>
/// <param name="encString">需要解密的字符串</param>
/// <param name="secretKey">密钥</param>
/// <param name="iv">矢量(可以不填)</param>
/// <returns></returns>
public static string AESDecrypt(string encString, string secretKey, string iv = "")
{
if (string.IsNullOrEmpty(iv))
{
return EncryptProvider.AESDecrypt(encString, secretKey); //表示不需要iv矢量的AES解密算法
}
else
{
return EncryptProvider.AESDecrypt(encString, secretKey, iv); //表示需要iv矢量的AES解密算法
}
}
/// <summary>
/// DES加密算法
/// </summary>
/// <param name="srcString">需要加密的字符串</param>
/// <param name="secretKey">密钥(这里的密钥需要是24位)</param>
/// <returns></returns>
public static string EDSEncrypt(string srcString, string secretKey)
{
return EncryptProvider.DESEncrypt(srcString, secretKey);
}
/// <summary>
/// DES解密算法
/// </summary>
/// <param name="encString">需要解密的字符串</param>
/// <param name="secretKey">密钥</param>
/// <returns></returns>
public static string DESDecrypt(string encString, string secretKey)
{
return EncryptProvider.DESDecrypt(encString, secretKey);
}
/// <summary>
/// 生成RSA算法所需的Key和iv
/// (当然这里可以自己指定并保存好)
/// </summary>
/// <param name="PublicKey">公钥</param>
/// <param name="PrivateKey">私钥</param>
public static void CreateRsaKey(ref string PublicKey, ref string PrivateKey)
{
//利用算法生成公钥和私钥,然后保存;当然这里可以自己指定并保存好
var rsaKey = EncryptProvider.CreateRsaKey(); //default is 2048
// var rsaKey = EncryptProvider.CreateRsaKey(RsaSize.R3072);
PublicKey = rsaKey.PublicKey;
PrivateKey = rsaKey.PrivateKey;
}
/// <summary>
/// RSA加密算法
/// </summary>
/// <param name="srcString">需要加密的字符串</param>
/// <param name="publicKey">公钥 加密</param>
/// <returns></returns>
public static string RSAEncrypt(string srcString, string publicKey)
{
return EncryptProvider.RSAEncrypt(publicKey, srcString); //公钥加密
}
/// <summary>
/// RSA解密算法
/// </summary>
/// <param name="encString">需要解密的字符串</param>
/// <param name="privateKey">私钥 解密</param>
/// <returns></returns>
public static string RSADecrypt(string encString, string privateKey)
{
return EncryptProvider.RSADecrypt(privateKey, encString); //私钥解密
}
}
public enum RsaSize
{
R2048 = 2048,
R3072 = 3072,
R4096 = 4096
}