错误的XOR解密

Ken*_*nny 0 c# xor

我编写了一个程序,使用随机键对文本进行编码。使用密钥时,即使我仅使用一个字母进行编码,解码器的结果也是完全错误的

这是用于加密/解密的函数,以及用于生成具有确定长度的随机密钥的函数:

string XOR_String(string text, string key)
{
    var result = new StringBuilder();

    for (int c = 0; c < text.Length; c++)
        result.Append((char)((uint)text[c] ^ (uint)key[c % key.Length]));

    return result.ToString();
}

private static string RandomString(int Size)
{
    Random random = new Random();
    string input = "abcdefghijklmnopqrstuvwxyz0123456789";
    var chars = Enumerable.Range(0, Size)
                           .Select(x => input[random.Next(0, input.Length)]);
    return new string(chars.ToArray());
}
Run Code Online (Sandbox Code Playgroud)

解密:

private void button1_Click(object sender, EventArgs e)
{
  openFileDialog1.FileName = "data.txt";
  openFileDialog1.Title = "Open file";
  openFileDialog1.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal);

  if (openFileDialog1.ShowDialog() == DialogResult.OK)
  {
      file = openFileDialog1;

      fs = new System.IO.FileStream(file.FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
      reader = new System.IO.StreamReader(fs);
      file_contents = reader.ReadToEnd();

      if (textBox1.Text != "")
      {
          data = XOR_String(file_contents, textBox1.Text);
          reader.Close();
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

加密:

private void button2_Click(object sender, EventArgs e)
{
    System.IO.FileInfo file_info = new System.IO.FileInfo(file.FileName);
    long file_info_length = file_info.Length;
    int file_length = checked((int)file_info_length);
    String key = RandomString(file_length);
    textBox1.Text = key;
    data = XOR_String(file_contents, key);
    System.IO.File.WriteAllText(file.FileName, data);
    reader.Close();
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*rey 5

您确实意识到C#/。Net / CLR世界中的字符串是UTF-16编码的Unicode,对吗?

http://en.wikipedia.org/wiki/UTF-16

基本多语言平面中代码点处的那些字符(范围U + 0000–U + D7FF和U + E000–U + FFFF)仅表示为单个16位字符。

您对字符进行随机XOR运算将导致随机内容无法往返:它将是无效的UTF-16或替代对

那是你的问题。

如果要编码这样的内容,请尝试以下操作:

  • 使用选择的编码byte[]从要编码的字符串中创建一个。
  • 异或。
  • 使用将所得的byte[]密文转换为Base64编码的字符串Convert.ToBase64String()

要对其进行解码,请逆向处理:

  • 将Base64编码的字符串转换为byte[]using Convert.FromBase64String()
  • 异或
  • byte[]使用最初使用的相同编码将结果纯文本转换回C#/。Net字符串。

编辑注意:

只是为了好玩...

  • 一个测试用例:

    MyNotVerySecureCrypto crypto = new MyNotVerySecureCrypto("cat" ) ;
    
    string plainText  = "The quick brown fox jumped over the lazy dog." ;
    string cipherText = crypto.Encrypt(plainText) ;
    string plainText1 = crypto.Decrypt(cipherText) ;
    
    Debug.Assert(plainText.Equals(plainText1,StringComparison.Ordinal));
    
    Run Code Online (Sandbox Code Playgroud)
  • 要测试此代码:

    public class MyNotVerySecureCrypto
    {
      private byte[]   Key      { get ; set ; }
      private Encoding Encoding { get ; set ; }
    
      public MyNotVerySecureCrypto( string key , Encoding encoding )
      {
        this.Encoding = encoding ;
        this.Key      = Encoding.GetBytes(key).Where( b => b != 0 ).ToArray() ;
        return ;
      }
      public MyNotVerySecureCrypto( string key ) : this ( key , Encoding.UTF8 )
      {
        return ;
      }
    
      public string Encrypt( string plainText )
      {
        int i = 0 ;
        byte[] octets = Encoding
                        .GetBytes(plainText)
                        .Select( b => (byte) (b^Key[(++i)%Key.Length]) )
                        .ToArray()
                        ;
        string cipherText = Convert.ToBase64String(octets) ;
        return cipherText ;
      }
    
      public string Decrypt( string cipherText )
      {
        int i = 0 ;
        byte[] octets = Convert
                        .FromBase64String(cipherText)
                        .Select( b => (byte) (b^Key[(++i)%Key.Length]) )
                        .ToArray()
                        ;
        string plainText = Encoding.GetString( octets ) ;
        return plainText ;
      }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)