使用对称加/解密时,要注意考虑填充

简介:


原问题1:
加密时是直接写入文件的,解密时是一边读加密后的文件,一边解。对于有的字符串就对,有的就不对,我怀疑那个DES加密的类有问题。
public   static   void  DesEncrypt(Stream inStream,Stream outStream, byte [] desKey, byte [] desIV)
{
        DES des
=new DESCryptoServiceProvider();
        CryptoStream cs
=new CryptoStream(outStream,des.CreateEncryptor(desKey,desIV),CryptoStreamMode.Write);
        
byte[] buf=new byte[1024];
        
int len=0;
        
while ((len=inStream.Read(buf,0,buf.Length))>0)
        
{
                cs.Write(buf,
0,len);
        }

        cs.Close();
}


public   static   void  DesDeEncrypt(Stream inStream,Stream outStream, byte [] desKey, byte [] desIV)
{
        DES des
=new DESCryptoServiceProvider();
        CryptoStream cs
=new CryptoStream(inStream,des.CreateDecryptor(desKey,desIV),CryptoStreamMode.Read);
        
byte[] buf=new byte[1024];
        
int len=0;
        
while ((len=cs.Read(buf,0,buf.Length))>0)
        
{
                outStream.Write(buf,
0,len);
        }

}

 


原问题2:
发现加密类RijndaelManaged的问题,根据MSDN的这个例子发现的问题,例子源码(VS2003)
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/cpref/html/frlrfSystemSecurityCryptographyRijndaelManagedClassTopic.htm
问题描述:在最后的Console.WriteLine("Round Trip: {0}", roundtrip );这行代码后面追加下面的代码
Console.WriteLine(original.Length == roundtrip.Length);
运行一下看看,按照正常想法应该是解密后的内容应该与原文完全相同,输出True,但是却输出False。

 

 

      这两个问题都差不多,都是因为不了解对称加密(AES/DES等)的加密原理,而误认为.net framework的加密算法有问题。

      AES/DES都是块式加密的(块的大小等于密钥的大小)。对于AES算法,其密钥大小为128bit(16byte),故每块16byte,在加密之前要对加密数据进行填充(例如:如果要用AES算法加密100byte的数据,则填充成112byte构成16的倍数,加密之后的数据大小为112byte;如果要加密112byte,则要另外填充16byte,构成128byte,加密之后的数据大小为128byte)。现在回过头来看看问题2,我们将MSDN中的代码改成下面这样则可以返回true了:
fromEncrypt = new byte[toEncrypt.Length];//MSDN中使用的是encrypted.Length;
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
这是因为按照MSDN的示例执行加密后,由于填充的缘故,encrypted的长度要比toEncrypt大,而MSDN的示例中是以encrypted的长度来设定fromEncrypt的长度,故解密之后fromEncrypt后面有一段是空的,得到的解密后字符串roundtrip中的后面有一截是以'\0'进行填充了,故长度不一样了。而使用toEncrypt.Length来设定fromEncrypt的长度,则申请的空间刚刚够用,不用填充。


      下面再来看看第一个问题:每次取1024byte进行加密,加密时系统会自动填充8个byte(DES的密钥长度为64bit),加密后得到1024+8byte的数据,所以你解密的时候要每次取1024+8byte进行解密。而对于加密前文件大小小于或等于1016byte的文件,加密后大小小于或等于1024byte,故循环只执行一次,按照问题中的解密代码可以解密成功,而对于再大一点或更大的文件,则必然解密失败,所以才出现问题中的“对于有的字符串就对,有的就不对”。修正后的测试代码如下:

DESCryptoServiceProvider des  =   new  DESCryptoServiceProvider();
des.GenerateKey();
des.GenerateIV();
FileStream fs1 
=   new  FileStream( " 自然.mp3 " , FileMode.Open, FileAccess.Read);
FileStream fs2 
=   new  FileStream( " Encrypted.mp3 " , FileMode.OpenOrCreate, FileAccess.Write);

// 加密
CryptoStream csEnCrypt = new  CryptoStream(fs2,des.CreateEncryptor(des.Key,des.IV),CryptoStreamMode.Write);
byte [] buf = new   byte [ 1024 ];
int  len  =   0 ;
while  ((len = fs1.Read(buf, 0 ,buf.Length)) > 0 )
{                
   csEnCrypt.Write(buf,
0,len);
   csEnCrypt.Flush();
   Console.WriteLine(
"Encrypt: " + len.ToString());
}

Console.ReadLine();
Console.WriteLine(
"   " );
csEnCrypt.Close();
fs1.Close();
fs2.Close();

// 解密
FileStream fs4  =   new  FileStream( " Encrypted.mp3 " , FileMode.OpenOrCreate, FileAccess.Read);
FileStream fs3 
=   new  FileStream( " Decrypted.mp3 " , FileMode.OpenOrCreate, FileAccess.Write);
CryptoStream csDecrypt 
=   new  CryptoStream(fs4, des.CreateDecryptor(des.Key, des.IV), CryptoStreamMode.Read);
byte [] buf2  =   new   byte [ 1024 + 8 ];
while  ((len  =  csDecrypt.Read(buf2,  0 , buf2.Length))  >   0 )
{
    Console.WriteLine(
"Decrypt: " + len.ToString());
    fs3.Write(buf2, 
0,len);
    fs3.Flush();
}

csDecrypt.Close();
fs3.Close();
// 可以正常播放了
fs4.Close();

 

补充 :.Net数据安全
1.填充模式(Padding Mode): None,PKCS7,Zeros.


2.加密模式(Cipher Mode):CBC,CFB,CTS,ECB,OFB.


3.对称加密:
  DESCryptoServiceProvider:     Key- 64bit          IV- 64bit
  RC2CryptoServiceProvider:     Key-128bit          IV- 64bit
  DijndaeManaged(AES)     :     Key-256/128/192bit  IV-128bit
  TripDESCryptoServiceProvider: key-192bit          IV- 64bit
  CreateDecryptor()构造解密器,CreateEncryptor()构造加密器。


4.非对称加密:
  DSA:KeySize=1024bit
      DSASignatrueFommatter类:创建数字签名;
      DSASignatrueDefommatter类:验证数字签名;
  RSA:KeySize=1024bit
      加密:RSA.Encrypt(byte[] DataEncrypt,bool Padding)
      解密:RSA.Decrypt(byte[] DataEncrypt,bool Padding)
      导出/导入密钥:RSA.ToXmlString(bool)/RSA.FromXml(string)
      签名/验证:RSA.SignData()/RSA.VerifyData()


5.消息摘要:
  HMACSHA1
  MACTripleDES
  MD5CryptoServiceProvider(128bit)
  SHA1Managed(160bit)
  SHA256Managed(256bit)
  SHA384Managed(384bit)
  SHA512Managed(512bit)

 

参考文献:
[1] MSDN
[2] 《应用密码学》Bruce Schneier[著],吴世忠等[译]


本文转自Silent Void博客园博客,原文链接:http://www.cnblogs.com/happyhippy/archive/2006/10/31/601225.html,如需转载请自行联系原作者

相关文章
|
6天前
|
人工智能 运维 安全
|
4天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
6天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
565 20
|
12天前
|
人工智能 JavaScript 测试技术
Qwen3-Coder入门教程|10分钟搞定安装配置
Qwen3-Coder 挑战赛简介:无论你是编程小白还是办公达人,都能通过本教程快速上手 Qwen-Code CLI,利用 AI 轻松实现代码编写、文档处理等任务。内容涵盖 API 配置、CLI 安装及多种实用案例,助你提升效率,体验智能编码的乐趣。
923 109
|
5天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。