零、什么是加密解密
发送方可以确定所发送的消息只有预期接收方可以解密,但不保证其他非接收方获得密文,只要保证非接收方获得密文后无法解密即可;
接收方可以确定消息是谁发送的;
接收方可以确定消息在传输过程中没有被篡改,也就是说可以验证消息的完整性。
一般来说常用的加密方式有三种:
不可逆加密;
对称可逆加密;
非堆成可逆加密。
下面我来讲一讲这三种常用的加密方式。
不可逆加密常用的不可逆加密是 MD5 加密,MD5是Message-Digest Algorithm 5英文简称,MD5 的特点如下:
任意长度的输入,经过 MD5 处理后都会输出128位的信息,这个信息称作数字指纹;
输入不同的信息产生的数字指纹不一样,数字指纹是全球唯一的;
无法根据数字指纹推导出加密前的信息。MD5 我们经常用在文档防篡改、密码加密、数字签名、网盘秒传。针对这四个方面我下面简单讲解一下:
文档防篡改
在文档发送前记录文档的 MD5 值,接收方收到文档后计算文档的 MD5 值,如果两个 MD5 值不一样就说明文档在发送过程中被篡改过;
密码加密
如果将密码明文存储在数据库中,泄露后可以别人可以直接登录,在用 MD5 将密码加密后即使泄露了也无法通过密文直接登录。但是这里需要注意,目前网上有很多破解 MD5 密文的网站,这些网站说白了就是利用撞库实现的,这些网站收集了常用的密码组合方式,比如生日、连续相同的数字或密码等,因此我们在验证密码强度时应当将常见的简单密码列,针对所有密码最好将密码中加入随机的信息内容然后再进行 MD5 加密,这就是所谓的加盐;
数字签名
某人写了一个重要文件,这个文件经过认证机构利用 MD5 生成摘要信息进行认证,如果以后这个人不承认这个文件是他写的,只需认证机构再次对文件生成摘要信息和以前的照耀信息进行对比即可知道该文件是所写的;
网盘秒传
网盘记录文件第一次上传的 MD5 值,以后当有人上传具有相同 MD5 值的文件时只需要将存在于网盘中的这个文件的链接发送出去即可。
MD5 的实现很简单代码如下:publicclassMD5{///<summary>//////</summary>///<paramname=”source”>待加密字串</param>///<paramname=”length”>加密结果长度</param>///<returns>加密后的字串</returns>publicstringEncrypt(stringsource,intlength=32){if(string.IsNullOrEmpty(source)){returnstring.Empty;}HashAlgorithmprovider=CryptoConfig.CreateFromName(“MD5”)asHashAlgorithm;byte[]bytes=Encoding.UTF8.GetBytes(source);byte[]hashValue=provider.ComputeHash(bytes);StringBuildersb=newStringBuilder();switch(length){case16:for(inti=4;i<12;i ){sb.Append(hashValue[i].ToString(“x2”));}break;case32:for(inti=0;i<16;i ){sb.Append(hashValue[i].ToString(“x2”));}break;default:for(inti=0;i<hashValue.Length;i ){sb.Append(hashValue[i].ToString(“x2″));}break;}returnsb.ToString();}///<summary>///获取文件的MD5///</summary>///<paramname=”fileName”></param>///<returns></returns>publicstringAbstractFile(stringfileName){FileStreamfile=newFileStream(fileName,FileMode.Open);System.Security.Cryptography.MD5md5=newMD5CryptoServiceProvider();byte[]retVal=md5.ComputeHash(file);file.Close();StringBuildersb=newStringBuilder();for(inti=0;i<retVal.Length;i ){sb.Append(retVal[i].ToString(“x2”));}returnsb.ToString();}}
对称可逆加密对称可逆加密就是用密钥将需要加密的内容进行加密,然后将加密后的内容发送给接收方,接收方街道内容后利用相同的密钥进行解密后就拿到了明文。对称可逆加密方式有一个严重的问题就是要保证密钥的安全,一旦密钥泄密第三方就可以利用这个密钥对解密收到的密文,甚至可以利用密钥伪造信息发送给接收方,接收方也就无法分辨出到底是谁发送的密文。最常用的对称可逆加密算法是 DES ,下面我们通过代码看一下 DES 的实现:publicclassDES{///<summary>///密钥///</summary>privatebyte[]key=ASCIIEncoding.ASCII.GetBytes(“123456”);///<summary>///偏移量///</summary>privatebyte[]iv=ASCIIEncoding.ASCII.GetBytes(“123456″.Insert(0,”w”).Substring(0,8));///<summary>///加密///</summary>///<paramname=”text”>需要加密的值</param>///<returns>加密后的结果</returns>publicstringEncrypt(stringtext){DESCryptoServiceProviderdsp=newDESCryptoServiceProvider();using(MemoryStreammemStream=newMemoryStream()){CryptoStreamcrypStream=newCryptoStream(memStream,dsp.CreateEncryptor(key,iv),CryptoStreamMode.Write);StreamWritersWriter=newStreamWriter(crypStream);sWriter.Write(text);sWriter.Flush();crypStream.FlushFinalBlock();memStream.Flush();returnConvert.ToBase64String(memStream.GetBuffer(),0,(int)memStream.Length);}}///<summary>///解密///</summary>///<paramname=”encryptText”></param>///<returns>解密后的结果</returns>publicstringDecrypt(stringencryptText){DESCryptoServiceProviderdsp=newDESCryptoServiceProvider();byte[]buffer=Convert.FromBase64String(encryptText);using(MemoryStreammemStream=newMemoryStream()){CryptoStreamcrypStream=newCryptoStream(memStream,dsp.CreateDecryptor(key,iv),CryptoStreamMode.Write);crypStream.Write(buffer,0,buffer.Length);crypStream.FlushFinalBlock();returnASCIIEncoding.UTF8.GetString(memStream.ToArray());}}}
非对称可逆加密非对称加密比较麻烦,发送方和接收方都保存有两个密钥,其中一个密钥是公钥,公钥是对外公开的,任何人都可以拿到,另一个是私钥,每个人的私钥不一样。规则是由A公钥加密的信息只能用A的私钥解密,由A的私钥加密的消息只能由A的公钥解密。非对称可逆加密的模式由两种:
加密模式
使用接收方的公钥加密,然后使用接收方的私钥解密,这样可以保证只有特定的接收方能收到信息,但是无法确认发送方是谁。
认证模式
使用发送方的私钥加密,然后使用发送方的公钥解密,这样可以保证特定发送方发送消息,但是无法确定消息是发给了谁。
从上述两种模式的描述中我们可以看到他们存在问题,因此就出现了数字签名,在上述认证模式中加入了散列算法(例如MD5),对明文进行处理后再把信息进行加密后发送出去,接收方收到信息解密后比较信息的散列值和原始消息的散列值就可以确定信息是否被篡改。常用的非对称可逆加密算法常用的是RSA,代码实现如下:publicclassRsa{///<summary>///获取加密/解密对///</summary>///<returns>EncryptDecrypt</returns>publicstaticKeyValuePair<string,string>GetKeyPair(){RSACryptoServiceProviderRSA=newRSACryptoServiceProvider();stringpublicKey=RSA.ToXmlString(false);stringprivateKey=RSA.ToXmlString(true);returnnewKeyValuePair<string,string>(publicKey,privateKey);}///<summary>///加密///</summary>///<paramname=”content”></param>///<paramname=”encryptKey”>加密key</param>///<returns></returns>publicstaticstringEncrypt(stringcontent,stringencryptKey){RSACryptoServiceProviderrsa=newRSACryptoServiceProvider();rsa.FromXmlString(encryptKey);UnicodeEncodingByteConverter=newUnicodeEncoding();byte[]DataToEncrypt=ByteConverter.GetBytes(content);byte[]resultBytes=rsa.Encrypt(DataToEncrypt,false);returnConvert.ToBase64String(resultBytes);}///<summary>///解密///</summary>///<paramname=”content”></param>///<paramname=”decryptKey”>解密key</param>///<returns></returns>publicstaticstringDecrypt(stringcontent,stringdecryptKey){byte[]dataToDecrypt=Convert.FromBase64String(content);RSACryptoServiceProviderRSA=newRSACryptoServiceProvider();RSA.FromXmlString(decryptKey);byte[]resultBytes=RSA.Decrypt(dataToDecrypt,false);UnicodeEncodingByteConverter=newUnicodeEncoding();returnByteConverter.GetString(resultBytes);}///<summary>///产生一组新的密钥///</summary>///<paramname=”content”></param>///<paramname=”encryptKey”>加密key</param>///<paramname=”decryptKey”>解密key</param>///<returns>加密后结果</returns>privatestaticstringEncrypt(stringcontent,outstringpublicKey,outstringprivateKey){RSACryptoServiceProviderrsaProvider=newRSACryptoServiceProvider();publicKey=rsaProvider.ToXmlString(false);privateKey=rsaProvider.ToXmlString(true);UnicodeEncodingByteConverter=newUnicodeEncoding();byte[]DataToEncrypt=ByteConverter.GetBytes(content);byte[]resultBytes=rsaProvider.Encrypt(DataToEncrypt,false);returnConvert.ToBase64String(resultBytes);}}
总结
【END】