1

C#에서 (128 비트 AES)를 사용하여 임의의 IV로 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 

나는을 것은 RijndaelManagedPaddingMode을 찾을 수있을 것 같지 않습니다.

다음 중 어떻게 할 수 있습니까?

  • 가변 길이 패딩

편집 :

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"과 매우 비슷합니다. 패딩 방식에 대한 패딩 (위의 방금 편집 한)의 Wikipedia 페이지를 참조하십시오. 일반적으로 바이트가 아닌 1로 설정된 단일 비트로 시작하므로 첫 번째 바이트는 0x01 대신 0x80이됩니다.

이 패딩 노드는 아마도 빌드되어 있지 않습니다. 실험을 원하면 Bouncy Castle 라이브러리를 권장합니다. 그렇지 않으면 거의 유비쿼터스 PKCS # 7 패딩으로 전환해야합니다.

+0

@KhurramMajeed 감사합니다. 내 스마트 폰에서 게시했습니다. 편집하기가 어렵습니다. :) –

3

을 테스트하기 위해 나는 당신의 패딩 방식에 익숙하지 않은 해요,하지만 확실히 그물에 내장 아니에요. PaddingModeNone으로 설정하고 패드를 입력 메시지에 보류 상태로 게시 할 수 있으며, 해독하는 항목에 대해 동일한 결과를 가져야합니다. 해독하는 경우 패드를 직접 제거해야합니다.

+0

출력 결과가 제대로 작동하지 않습니다. 무엇이 문제입니까, 패딩 기능이 가변 길이 메시지를 작동시키지 않습니다. '..'는'100 ..00'에 없습니다. – jbtule

+0

업데이트 된 OP –

+0

을 참조하십시오 선택한 암호문 공격 숙제를하지 않으면 첫 번째 질문은 C#에서 특정 패딩을 수행하는 방법이었습니다. 수정 된 질문은 스택 오버플로 질문이 아니며 가능한 질문을하는 경우 crypto.stackoverflow 질문 일 수 있습니다. CBC가 작동하는 방식과 관련이 있습니다. – jbtule

관련 문제