1

我想用C#中的隨機IV(128位AES)測試CBC。AES中的填充CBC

在我的問題來解決,我有12個字節的輸入消息。條件是,如果PlainText小於塊大小(16字節),則要使用的填充從0x01開始,然後到6 0x00。

例子:

in ASCII PT  = Pay Bob 100% 

in hex PT  = 50 61 79 20 42 6f 62 20 31 30 30 24 

PT with Padding = 50 61 79 20 42 6f 62 20 31 30 30 24 01 00 00 00 

我似乎沒有能夠找到這個PaddingModeRijndaelManaged的

任何人可以告訴我如何做到以下幾點?

  • 可變長度填充

編輯:

public class CBC 
{ 
    public CBC() 
    { 

    } 

    private static readonly byte[] SALT = new byte[] 
     {0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c}; 

    public static byte[] EncryptCBC(string plainText, string passPhrase, PaddingMode paddingMode) 
    { 
     byte[] result; 
     using (RijndaelManaged cryptoProvider = new RijndaelManaged()) 
     { 
      Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(passPhrase, SALT); 
      cryptoProvider.Mode = CipherMode.CBC; 
      cryptoProvider.GenerateIV(); // generate random IV 

      cryptoProvider.Padding = paddingMode; 

      cryptoProvider.Key = derivedKey.GetBytes(cryptoProvider.KeySize/8); 

      using (MemoryStream msEncrypt = new MemoryStream()) 
      { 
       using (ICryptoTransform encryptor = cryptoProvider.CreateEncryptor(cryptoProvider.Key, cryptoProvider.IV)) 
       { 
        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
        { 
         using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
         { 
          swEncrypt.Write(plainText); 
         } 
        } 
       } 
       // concatenate iv to ciphertext 
       result = cryptoProvider.IV.Concat(msEncrypt.ToArray()).ToArray(); 
      } 
      cryptoProvider.Clear(); 
     } 
     return result; 
    } 

    public static string DecryptCBC(byte[] cipherTextBytes, string passPhrase, PaddingMode paddingMode) 
    { 
     string result = null; 
     using (RijndaelManaged cryptoProvider = new RijndaelManaged()) 
     { 
      Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(passPhrase, SALT); 
      cryptoProvider.Mode = CipherMode.CBC; 
      // take the iv off the beginning of the ciphertext message 
      cryptoProvider.IV = cipherTextBytes.Take(cryptoProvider.BlockSize/8).ToArray(); 


      cryptoProvider.Padding = paddingMode;//PaddingMode.ANSIX923; 



      cryptoProvider.Key = derivedKey.GetBytes(cryptoProvider.KeySize/8); 

      using (MemoryStream msEncrypt = new MemoryStream(cipherTextBytes.Skip(cryptoProvider.BlockSize/8).ToArray())) // skip the IV bytes 
      { 
       using (ICryptoTransform encryptor = cryptoProvider.CreateDecryptor(cryptoProvider.Key, cryptoProvider.IV)) 
       { 
        using (CryptoStream cryptoStream = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Read)) 
        { 
         byte[] plainTextBytes = new byte[cipherTextBytes.Length - cryptoProvider.BlockSize/8]; 
         int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); 

         result = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); 
         cryptoStream.Close(); 
        } 
       } 
      } 

      cryptoProvider.Clear(); 
     } 
     return result; 
    } 

} 

我的填充功能

 private byte[] PaddPlainTextBytes(byte[] plainTextBytes) 
    { 
     byte[] padding = utils.HexToBytes("01000000"); 
     MemoryStream s = new MemoryStream(); 

     s.Write(plainTextBytes, 0, plainTextBytes.Length); 
     s.Write(padding, 0, padding.Length); 

     byte[] paddedPt = s.ToArray(); 

     return paddedPt; 
    } 

方法測試我的CBC

 private void btnTestCBC_Click(object sender, EventArgs e) 
    { 
     string plainText = "Pay Bob 100%"; 

     string passPhrase = "Thisismypassphrase"; 
     ShowMessage(@"Plain Text = " + plainText); 

     byte[] pBytes = PaddPlainTextBytes(Encoding.ASCII.GetBytes(plainText)); 

     string message = Encoding.ASCII.GetString(pBytes); 

     byte[] encryptedBytes = CBC.EncryptCBC(plainText: message, passPhrase: passPhrase, paddingMode: PaddingMode.None); 

     ShowMessage("Encrypted String = " + Encoding.ASCII.GetString(encryptedBytes)); 
     ShowMessage("Encrypted HEX = " + utils.BytesToHex(encryptedBytes)); 


     string decryptedString = CBC.DecryptCBC(encryptedBytes, passPhrase, PaddingMode.None); 
     ShowMessage("Deccrypted String = " + decryptedString); 
    } 
+0

您也可以使用不需要填充的操作模式,如CTR。不是內置的,唉。 – usr

+1

你似乎認爲填充總是固定的長度,而不是對齊函數。 – leppie

回答

1

您所描述的填充方案看起來很像"ISO/IEC 7816-4 Padding",請參閱填充方法的填充(我剛剛編輯過)的維基百科頁面。通常情況下,你從一個位設置爲1開始,而不是一個字節,因此對於第一個字節,這將是0x80而不是0x01。

這個填充節點可能不是內置的。如果你想實驗,我會推薦Bouncy Castle庫,否則切換到幾乎無處不在的PKCS#7填充。

+0

@KhurramMajeed謝謝,從我的智能手機發布,很難編輯:) –

3

我不熟悉你的填充方案,但它沒有內置於.NET是肯定的。您應該可以將PaddingMode設置爲None,並將帖子掛在您的輸入消息中,對於解密它的任何內容應該具有相同的結果。如果你正在解密它,你將不得不自己卸下鍵盤。

+0

那麼你的輸出工作,你的問題是什麼,你的填充函數不起作用可變長度的消息,在'100..00'中沒有「'..'」。 – jbtule

+0

請參閱更新OP –

+0

不做選擇密文攻擊作業,第一個問題是如何在c#中做一定的填充,修改後的問題不是堆棧溢出問題,如果您問問你真的想要問題,它可能是crypto.stackoverflow問題與CBC的工作方式有關。 – jbtule