2017-09-01 17 views
0

私はAESでUTF-8文字列を暗号化および復号化するメソッドで適切なIVプラクティスを実装しようとしていました。参照としてthis質問を使用して、私は、生成されたIVをBase64変換の前にバイト配列に追加しています。私はdecryptメソッドがランダムな迷惑メール(暗号化アーティファクト?)の50文字でUTF-8文字列を返す問題を抱えています。 decryptメソッドが一貫して暗号化された文字列を返すので、私は問題が暗号化にあるとは思わない。問題は他の変換ステップの1つにあると思いますが、どこから来るのか分かりません。どんな助けでも大いに感謝します。C#UTF8からAESからBase64への変換のペイロード前のジャンクバイト

暗号化方式

public static string EncryptString(string input, string key) 
    { 
     using (var aes = new AesCryptoServiceProvider()) 
     { 

      aes.Key = System.Convert.FromBase64String(key); 
      aes.Mode = CipherMode.CBC; 
      aes.Padding = PaddingMode.PKCS7; 

      byte[] rawData = Encoding.UTF8.GetBytes(input); 
      // IV is the 16 byte AES Initialization Vector 
      aes.GenerateIV(); 

      using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV)) 
      { 
       using (var ms = new MemoryStream()) 
       { 
        ms.Write(aes.IV, 0, aes.IV.Length); // aes.IV.Length should be 16 
        using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) 
        { 
         cs.Write(rawData, 0, rawData.Length); 
         cs.FlushFinalBlock(); 
        } 
        byte[] encryptedData = ms.ToArray(); 

        // this will hold the IV prepended to the encrypted data 
        byte[] output = new byte[aes.IV.Length + encryptedData.Length]; 

        Array.Copy(aes.IV, output, aes.IV.Length); // save the iv 
        Array.Copy(encryptedData, 0, output, aes.IV.Length, encryptedData.Length); // save the data 

        // now encode the whole thing as base 64 
        return System.Convert.ToBase64String(output); 

       } 
      } 

     } 

    } 

解読方法

public static string DecryptString(string input, string key) 
    { 

     using (var aes = new AesCryptoServiceProvider()) 
     { 
      aes.Key = Convert.FromBase64String(key); 
      aes.Mode = CipherMode.CBC; 
      aes.Padding = PaddingMode.PKCS7; 

      byte[] rawData = Convert.FromBase64String(input); 
      byte[] IV = new byte[16]; // aes.IV.Length should be 16 

      Array.Copy(rawData, IV, IV.Length); 
      using (var ms = new MemoryStream()) 
      { 
       using (var cs = new CryptoStream(ms, aes.CreateDecryptor(aes.Key, IV), CryptoStreamMode.Write)) 
       { 
        using (var binaryWriter = new BinaryWriter(cs)) 
        { 
         binaryWriter.Write(rawData,IV.Length ,rawData.Length - IV.Length); 
        } 
       } 
       return Encoding.UTF8.GetString(ms.ToArray()); 
      } 
     } 
    } 

私のテスト

static void Main(string[] args) 
    { 
     string payload = "My super secret string"; 
     string key = "tR4mPn7mBQ8G6HWusyFnGk/gqdd/enWiUTr7YbhNrJg="; 

     Console.WriteLine(payload); 
     Console.WriteLine(key); 

     Console.WriteLine(""); 
     string encrypted = EncryptString(payload, key); 
     Console.WriteLine(encrypted); 

     Console.WriteLine(""); 
     string decrypted = DecryptString(encrypted, key); 
     Console.WriteLine(decrypted); 

     Console.WriteLine(decrypted.Length.ToString() + " " + encrypted.Length.ToString()); 

     Console.ReadKey(); 

    } 

編集追加する - これは出力例:

XQ = F] DあなたがEncryptStringで二回出力にIVを書いている私のスーパーの秘密の文字列

+0

、あなたは、問題が表示されます、Base64ではコンピュータではなく、人間のためです。 – zaph

答えて

3

?。まず、あなたは:

ms.Write(aes.IV, 0, aes.IV.Length); // aes.IV.Length should be 16 

encryptedDataの先頭です。あなたは、新しいバイト配列に(すでにIVを含みます)IVとencryptedDataをコピーします。

// this will hold the IV prepended to the encrypted data 
byte[] output = new byte[aes.IV.Length + encryptedData.Length]; 

Array.Copy(aes.IV, output, aes.IV.Length); // save the iv 
Array.Copy(encryptedData, 0, output, aes.IV.Length, encryptedData.Length); // save the data 

IVのこの倍増は、余分なバイトを引き起こしているものです。

2回目のコピーは不要です。ただ、直接64をベースとそれを返すためにencryptedDataを変換:六角として出力を調べ

return System.Convert.ToBase64String(encryptedData); 
+0

これは正しいです。私はそれが簡単な間違いだと思った。私の疲れた金曜日の目はちょうどそれを捕まえられなかった。 –

関連する問題