目录
浅谈加解密实现方式
MD5加密
DES加密
AES加密
RSA加密
SSL加密认证
关于RSA加解密实现
简单数据加解密的实现
分块加解密实现
附录
浅谈加解密实现方式
关于数据加解密方式,我们一般分为不可逆加密、对称可逆加密、非对称加密、综合加密应用等,简单介绍下我所了解的一些加密方式。
MD5加密
MD5加密属于不可逆加密,原文加密过后生成的密文无法解密出原文。
其特点包括:
- 相同原文加密结果一致
- 不同长度的内容加密过后都是32位
- 原文差别很小,密文差别很大
- 不管文件多大,都能产生32位长度摘要,文件内容不变,名字变了,密文不会变
一般使用场景包括:
- 防止被篡改:校验数据是否一致、源代码管理器
- 防止明文存储:密码保存
- 防止抵赖:数字签名
DES加密
DES加密属于对称可逆加密,通信的双方使用同一个秘钥,通过秘钥加密过后的密文,可使用秘钥解密出原文。
其特点包括:
- 加密解密速度快,但密匙的安全问题有待解决
- 不具有个体原子性,一个密钥被共享,泄露几率会大大增加
- 适合大量数据
一般用于资讯传输数据的加密
AES加密
AES加密属于对称可逆加密,通信的双方使用同一个秘钥,通过秘钥加密过后的密文,可使用秘钥解密出原文。安全性高于DES加密
一般用于数据库加密存储隐私数据
其特点包括:
- 加密简单快速,但不具有个体原子性,一个密钥被共享,泄露几率会大大增加
- 适合大量数据
- 可利于并行计算
- 分为不同的工作模式,ECB,CBC,OFB,CFB,CFB8,CTR,GCM,除了ECB无须设置初始化向量IV而不安全之外,其它AES工作模式都必须设置向量IV
RSA加密
RSA属于非对称可逆加密,加密秘钥和解密秘钥为两个不同的秘钥,两个秘钥称之为公钥和私钥,公钥是公开的,通信双方都持有的,用来加密原文数据;私钥为通信的其中一方持有,用来解密数据来获取原文数据。
其特点包括:
- 公钥和私钥是一对
- 公钥和私钥不可相互推导,只有密文,没有解密key,也推导不出原文
- 加解密速度慢,安全性好
一般用于网络数据传输,从而保证信息的保密性、认证性,比如数字签名,即私钥持有者对信息进行签名,验证者可以根据公开的公钥进行验证签名是否正确和有效,即实现了认证性,以及不可抵赖性。
SSL加密认证
SSL加密是数字证书加密,属于加解密综合应用,https协议使用(https协议=HTTP协议+SSL/TLS协议)
其证书构成为:
- 持有者姓名
- 发证机关
- 有效期
- 证书持有人公钥
- 扩展信息
- 发证机关对该证书的数字签名(数字签名=前5点信息MD5摘要,然后用CA的私钥加密下)
SSL加密模式可以用于发送安全电子邮件、访问安全站点、网上招标与投标、网上签约、网上订购、安全网上公文传送、网上办公、网上缴费、网上缴税以及网上购物等安全的网上电子交易活动,交易时,双方需要使用数字签名来表明自己的身份,并使用数字签名来进行有关的交易操作,防止交易过程中出现数据被泄露或篡改的情况
关于RSA加解密实现
使用RSA加解密的实现,需要引用System.Security.Cryptography
简单数据加解密的实现
public void RSACheck(string txtValue)
{
var rsaClient = new RSACryptoServiceProvider(2048);
var privakeKeyByte = rsaClient.ExportRSAPrivateKey();
var publicKeyByte = rsaClient.ExportRSAPublicKey();
string privateKey = Convert.ToBase64String(privakeKeyByte);
string publicKey= Convert.ToBase64String(publicKeyByte);
int privateBytesRead = 0;
RSACryptoServiceProvider rsaPrivate = new RSACryptoServiceProvider();
rsaPrivate.ImportRSAPrivateKey(privakeKeyByte, out privateBytesRead);
int publicBytesRead = 0;
RSACryptoServiceProvider rsaPublic = new RSACryptoServiceProvider();
rsaPublic.ImportRSAPublicKey(publicKeyByte, out publicBytesRead);
Console.WriteLine("原始字符串:" + txtValue);
//公钥加密
string enStr = Convert.ToBase64String(rsaPublic.Encrypt(System.Text.Encoding.UTF8.GetBytes(txtValue), RSAEncryptionPadding.Pkcs1));
Console.WriteLine("加密字符串:" + enStr);
//私钥解密
string deStr = System.Text.Encoding.UTF8.GetString(rsaPrivate.Decrypt(Convert.FromBase64String(enStr),RSAEncryptionPadding.Pkcs1));
Console.WriteLine("解密字符串:" + deStr);
私钥签名
//string signStr = rsa.Sign(txtValue);
//Console.WriteLine("字符串签名:" + signStr);
公钥验证签名
//bool signVerify = rsa.Verify(txtValue, signStr);
//Console.WriteLine("验证签名:" + signVerify);
}
实现效果
分块加解密实现
RSA加解密数据时,对于加解密的数据长度有一定的限制,其长度规则限制为
需要加密的字节数不能超过密钥的长度值除以 8 再减去 11(RSACryptoServiceProvider.KeySize / 8 - 11),而加密后得到密文的字节数,正好是密钥的长度值除以 8(即:RSACryptoServiceProvider.KeySize / 8)
因此对于加密/解密数据长度超过最大长度限制时,使用分块加密/解密的方式
分块加密实现
/// <summary>
/// 获取RSA私钥加密数据
/// </summary>
/// <param name="publicKey">加密公钥</param>
/// <param name="txtValue">加密原文数据</param>
/// <returns></returns>
public string GetRSAEncrypt(string publicKey,string txtValue)
{
byte[] publicKeyByte = Convert.FromBase64String(publicKey);
int publicBytesRead = 0;
RSACryptoServiceProvider rsaPublic = new RSACryptoServiceProvider();
rsaPublic.ImportRSAPublicKey(publicKeyByte, out publicBytesRead);
int maxBlockSize = rsaPublic.KeySize / 8 - 11;//加密块最大长度限制
//公钥加密
string enStr = "";
byte[] jsonByte = System.Text.Encoding.UTF8.GetBytes(txtValue);
if (jsonByte.Length <= maxBlockSize)
{
enStr = Convert.ToBase64String(rsaPublic.Encrypt(jsonByte, RSAEncryptionPadding.Pkcs1));
}
else
{
//待加密的字节数不能超过密钥的长度值除以 8 再减去 11(即:RSACryptoServiceProvider.KeySize / 8 - 11),
//而加密后得到密文的字节数,正好是密钥的长度值除以 8(即:RSACryptoServiceProvider.KeySize / 8)。
//加密数据长度超过最大长度限制时,使用分块加密的方式
using (MemoryStream plaiStream = new MemoryStream(jsonByte))
using (MemoryStream crypStream = new MemoryStream())
{
byte[] buffer = new byte[maxBlockSize];
int blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
while (blockSize > 0)
{
byte[] toEncrypt = new byte[blockSize];
Array.Copy(buffer, 0, toEncrypt, 0, blockSize);
byte[] cryptograph = rsaPublic.Encrypt(toEncrypt, RSAEncryptionPadding.Pkcs1);
crypStream.Write(cryptograph, 0, cryptograph.Length);
blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
}
enStr = Convert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None);
}
}
return enStr;
}
分块解密实现
/// <summary>
/// RSA解密
/// </summary>
/// <param name="cipherText">密文数据</param>
/// <param name="privateKey">解密私钥</param>
/// <returns></returns>
public string DeRsaData(string cipherText, string privateKey)
{
string deStr = "";
int bytesRead = 0;
RSACryptoServiceProvider rsaPrivate = new RSACryptoServiceProvider();
rsaPrivate.ImportRSAPrivateKey(Convert.FromBase64String(privateKey), out bytesRead);
int maxBlockSize = rsaPrivate.KeySize / 8; //解密块最大长度限制
byte[] ciphertextData = Convert.FromBase64String(cipherText);
if (ciphertextData.Length <= maxBlockSize)
{
deStr = System.Text.Encoding.UTF8.GetString(rsaPrivate.Decrypt(Convert.FromBase64String(cipherText), RSAEncryptionPadding.Pkcs1));
}
else
{
//需要解密的数据长度超过解密块最大长度时,使用分块解密
using (MemoryStream crypStream = new MemoryStream(ciphertextData))
using (MemoryStream plaiStream = new MemoryStream())
{
byte[] buffer = new byte[maxBlockSize];
int blockSize = crypStream.Read(buffer, 0, maxBlockSize);
while (blockSize > 0)
{
byte[] toDecrypt = new byte[blockSize];
Array.Copy(buffer, 0, toDecrypt, 0, blockSize);
byte[] plaintext = rsaPrivate.Decrypt(toDecrypt, RSAEncryptionPadding.Pkcs1);
plaiStream.Write(plaintext, 0, plaintext.Length);
blockSize = crypStream.Read(buffer, 0, maxBlockSize);
}
deStr = System.Text.Encoding.UTF8.GetString(plaiStream.ToArray());
}
}
return deStr;
}
附录
关于System.Security.Cryptography的使用学习AesCryptoServiceProvider 类 (System.Security.Cryptography) | Microsoft Learn