c#decryption产生错误结果[更新1]

时间:2015-04-17 22:02:42

标签: c# encryption rijndael

在我的程序中会发生以下情况。

  1. 生成并加密随机字符串 这是加密例程:

    private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };
        //TODO: The SALT needs to be derived and unique for each user!
    
        internal  byte[] Encrypt(byte[] plain)
        {
            string password = Properties.Settings.Default.PasswordOne;
            MemoryStream memoryStream;
            CryptoStream cryptoStream;
            Rijndael rijndael = Rijndael.Create();
            rijndael.Padding = PaddingMode.Zeros;
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
            rijndael.Key = pdb.GetBytes(32);
            rijndael.IV = pdb.GetBytes(16);
            memoryStream = new MemoryStream();
            cryptoStream = new CryptoStream(memoryStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write);
            cryptoStream.Write(plain, 0, plain.Length);
            cryptoStream.Close();
            return memoryStream.ToArray();
        }
    
  2. 此加密字符串将保存到名为DEFT的文件中 这是保存例程:

     private void CreateDeft2(FileSystemEncryption fse, string Deft2FileName, string drive)
    {
        if (DrivesLog != null) DrivesLog("Creating DEFT2");
        FileStream fs = null;
        StreamWriter sw = null;
        string location = Path.Combine(drive, Deft2FileName);
        try
        {
            fs = new FileStream(location, FileMode.CreateNew, FileAccess.Write, FileShare.None);
            sw = new StreamWriter(fs, Encoding.Unicode);
    
            if (DrivesLog != null) DrivesLog("Creating Random Contents");
            string fakeContents = CreateRandomString(1024000);      // Create the fake contents
            if (DrivesLog != null) DrivesLog("Converting Random Contents to Bytes");
            byte[] bFakeContents = GetBytes(fakeContents);          // Convert to bytes
            if (DrivesLog != null) DrivesLog("Encrypting Random Content Bytes");
            byte[] ebFakeContents = fse.Encrypt(bFakeContents);     // Encrypt
            if (DrivesLog != null) DrivesLog("Converting Encrypted Bytes to String");
            string sedFakeContents = GetString(ebFakeContents);     // Convert to string
    
            if (DrivesLog != null) DrivesLog("Writing DEFT2");
            sw.Write(sedFakeContents);                              // Write it out
            fs.Flush();                                             // Flush the buffer
    
            sw.Close();
            fs.Close();
            if (DrivesLog != null) DrivesLog("Successfully Created DEFT2");
        }
        catch (Exception ex)
        {
            if (DrivesLog != null) DrivesLog("Failed to Create DEFT2 " + ex.Message);
            sw.Close();
            fs.Close();
        }
    }
    
  3. 在DEFT文件中的特定位置创建并保存另一个包含32个字符的字符串 这是代码:

    private void InsertDEFT2NameLength(FileSystemEncryption fse, FileStream fs, StreamWriter sw)
        {
            if (DrivesLog != null) DrivesLog("Inserting DEFT2 Name");
            string deft2NameLength = "0";                                       // init the length
            if (DrivesLog != null) DrivesLog("Converting DEFT2 Name to Bytes");
            if (fDEFT2Name.Length < 32)
            {
                for (int idx = fDEFT2Name.Length; idx < 32; idx++)
                {
                    fDEFT2Name = fDEFT2Name + "!";
                }
            }
            byte[] bdeft2Name = GetBytes(fDEFT2Name);                        // convert filename to bytes
            if (DrivesLog != null) DrivesLog("Encrypting DEFT2 Name");
            byte[] ebdeft2Name = fse.Encrypt(bdeft2Name);                       // Encrypt
            if (DrivesLog != null) DrivesLog("Getting Length of Encrypted DEFT2 Name");
            long ebdeft2NameLength = ebdeft2Name.LongLength;                    // Get Length of the Encrypted Bytes as a long
            if (DrivesLog != null) DrivesLog("Converting DEFT2 Name Length to String");
            string sebdeft2NameLength = ebdeft2NameLength.ToString();     // Convert Length to string Add Shebang so we know when we have read the full length
            if (DrivesLog != null) DrivesLog("Converting DEFT2 Name Length to Bytes");
            byte[] bsebdeft2NameLength = GetBytes(sebdeft2NameLength);          // Convert length string to bytes
            if (DrivesLog != null) DrivesLog("Encrypting DEFT2 Name Length");
            byte[] ebsebdeft2NameLength = fse.Encrypt(bsebdeft2NameLength);     // Encrypt
            if (DrivesLog != null) DrivesLog("Converting Encrypted DEFT2 Name Length to String");
            deft2NameLength = GetString(ebsebdeft2NameLength);                  // Convert to string
    
            if (DrivesLog != null) DrivesLog("Seeking to Correct Location");
            long startPos = GenerateDEFT2LengthStartPosition();
            fs.Seek(startPos, SeekOrigin.Current);    // Seek to correct location
            if (DrivesLog != null) DrivesLog("New Position " + startPos.ToString("N0"));
            if (DrivesLog != null) DrivesLog("Writing Encrypted Name Length to New Position");
            sw.Write(deft2NameLength);                                          // Write the Encrypted length
            fs.Flush();                                                         // Flush the buffer immediately
        }
    
    1. 然后我尝试解密那个新字符串。 解密字符串(或者至少应该!)

      private long ReadDEFT2Len(string DEFT,long lenPos,FileSystemEncryption fse)     {         if(DrivesLog!= null)DrivesLog(&#34;读取DEFT2名称长度&#34;);         StringBuilder sb = new StringBuilder();

          FileStream fs = null;
          StreamReader sr = null;
      
          try
          {
              fs = new FileStream(DEFT, FileMode.Open, FileAccess.Read, FileShare.Read);
              sr = new StreamReader(fs, Encoding.Unicode);
      
              char[] C = new char[32];
              fs.Seek(lenPos, SeekOrigin.Begin);
              sr.Read(C, 0, 32);
      
              string sC = new string(C);
              byte[] bsC = GetBytes(sC);
      
              byte[] dRes = fse.Decrypt(bsC);
              string sbdRes = GetString(dRes);
              foreach (char ic in sbdRes)
              {
                  if (ic == '!') break;
                  sb.Append(ic.ToString());
              }
      
              sr.Close();
              fs.Close();
      
              if (DrivesLog != null) DrivesLog("DEFT2 Name Length = " + sb.ToString());
              return long.Parse(sb.ToString());
          }
          catch (Exception ex)
          {
              if (DrivesLog != null) DrivesLog("ERROR Reading DEFT2 Name Length " + ex.Message);
              if (sr != null) sr.Close();
              if (fs != null) fs.Close();
              return -1;
          }
      
      }
      
  4. 原谅格式化 - 它只是赢得了不错!

    解密例程不解密原始字符串 - 它只返回难以理解的文本。 解密路由在此处:

    internal  byte[] Decrypt(byte[] cipher)
        {
            string password = Properties.Settings.Default.PasswordOne;
            MemoryStream memoryStream;
            CryptoStream cryptoStream;
            Rijndael rijndael = Rijndael.Create();
            rijndael.Padding = PaddingMode.Zeros;
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
            rijndael.Key = pdb.GetBytes(32);
            rijndael.IV = pdb.GetBytes(16);
            memoryStream = new MemoryStream();
            cryptoStream = new CryptoStream(memoryStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write);
            cryptoStream.Write(cipher, 0, cipher.Length);
            cryptoStream.FlushFinalBlock();
            cryptoStream.Close();
            return memoryStream.ToArray();
        }
    

    它使用与加密器相同的盐。密码相同,读取的字节数相同,并且从文件中的正确位置开始。那么,任何想法为什么会这样呢?

    更新1:

    此代码为我提供了我将在先前创建的加密DEFT文件中插入新信息的位置。

    private long GenerateDEFT2LengthStartPosition()
            {
                if (DrivesLog != null) DrivesLog("Generating DEFT2 Length Start Position");
                return long.Parse((Properties.Settings.Default.PasswordOne.Length * Properties.Settings.Default.PasswordOne.Length).ToString());
            }
    

    只要我使用与保存时相同的密码(出于测试目的),它将返回相同的位置以插入新加密的文本。在这种情况下,它总是100返回。

    但是,在Hex编辑器中使用Decimals作为偏移量时,它显示新加密的文本存储在偏移量418处。

    为什么要保存这样的文字:

    long startPos = GenerateDEFT2LengthStartPosition();
                fs.Seek(startPos, SeekOrigin.Current);    // Seek to correct location                
                sw.Write(deft2NameLength);                                          
    

    并加载它:

    long lenPos = GenerateDEFT2LengthStartPosition();
     char[] C = new char[32];
                    fs.Seek(lenPos, SeekOrigin.Begin);
                    sr.Read(C, 0, 32);
    

    将我置于文件中完全不同的位置?

      

    所以问题:为什么使用相同的值100来编写和读取   文件中的加密文本,将文本放在不同的位置   从哪里读取?

0 个答案:

没有答案