AES CFB 256位加密输出是否比输入长?

时间:2011-11-29 22:55:59

标签: .net aes encryption

我想问一下,这两个程序vb.net 2010和动态c下面的输出有什么不同?为什么加密数据的长度不同(vb.net - 16字节= 0x878e086ec00cbfeaafc9fc91edc8294c和动态C - 10字节= 0x878e086ec00cbfeaafc9),尽管使用密钥,初始向量(IV)和plaint文本相同。哪个输出正确? THANKYOU

我正在尝试使用AES CFB 256 BIT使用vb.net 2010加密Decrypt,结果如下:

  

密钥:0x603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4(256位= 32 BYTE)

     

IV:0x000102030405060708090A0B0C0D0E0F(16字节)

     

纯文字:0123456789(10字节)

     

加密:0x878e086ec00cbfeaafc9fc91edc8294c(16字节)?????比明文长6byte = fc91edc8294c

     

解密:0123456789(10字节)

使用AES CFB 256 BIT加密Decrypt使用Dynamic C,结果如下:

  

密钥:0x603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4(256位= 32 BYTE)

     

IV:0x000102030405060708090A0B0C0D0E0F(16字节)

     

纯文字:0123456789(10字节)

     

加密:0x878e086ec00cbfeaafc9(10字节)?????长度与明文相同

     

解密:0123456789(10字节)


' VB.NET

Imports System
Imports System.IO
Imports System.Security.Cryptography
Imports System.Text

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Dim original As String = "0123456789"
    Dim roundtrip As String
    Dim textConverter As New ASCIIEncoding()
    Dim myRijndael As New RijndaelManaged()
    Dim fromEncrypt() As Byte
    Dim encrypted() As Byte
    Dim toEncrypt() As Byte
    Dim key() As Byte
    Dim IV() As Byte

    'Create a new key and initialization vector.
    'myRijndael.GenerateKey()
    'myRijndael.GenerateIV()

    Debug.Print("Original:   " & original)

    myRijndael.Mode = CipherMode.CFB
    myRijndael.BlockSize = 128
    myRijndael.KeySize = 256
    myRijndael.Key = StringToByteArray("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4")
    myRijndael.IV = StringToByteArray("000102030405060708090A0B0C0D0E0F")


    'Get the key and IV.
    key = myRijndael.Key
    IV = myRijndael.IV

    'Get an encryptor.
    Dim encryptor As ICryptoTransform = myRijndael.CreateEncryptor(key, IV)

    'Encrypt the data.
    Dim msEncrypt As New MemoryStream()
    Dim csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)

    'Convert the data to a byte array.
    toEncrypt = textConverter.GetBytes(original)

    'Write all data to the crypto stream and flush it.
    csEncrypt.Write(toEncrypt, 0, toEncrypt.Length)
    csEncrypt.FlushFinalBlock()

    'Get encrypted array of bytes.
    encrypted = msEncrypt.ToArray()
    Debug.Print("Encrypted:  " & ByteArrayToString(encrypted))

    'This is where the message would be transmitted to a recipient
    ' who already knows your secret key. Optionally, you can
    ' also encrypt your secret key using a public key algorithm
    ' and pass it to the mesage recipient along with the RijnDael
    ' encrypted message.            
    'Get a decryptor that uses the same key and IV as the encryptor.
    Dim decryptor As ICryptoTransform = myRijndael.CreateDecryptor(key, IV)

    'Now decrypt the previously encrypted message using the decryptor
    ' obtained in the above step.
    Dim msDecrypt As New MemoryStream(encrypted)
    Dim csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)

    fromEncrypt = New Byte(encrypted.Length) {}

    'Read the data out of the crypto stream.
    csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length)

    'Convert the byte array back into a string.
    roundtrip = textConverter.GetString(fromEncrypt)

    'Display the original data and the decrypted data.
    Debug.Print("Decrypt:    " & roundtrip)
    Debug.Print("")

End Sub

Public Function ByteArrayToString(ByVal ba As Byte()) As String
    Dim hex As New StringBuilder(ba.Length * 2)
    For Each b As Byte In ba
        hex.AppendFormat("{0:x2}", b)
    Next
    Return hex.ToString()
End Function

Public Function StringToByteArray(ByVal hex As [String]) As Byte()
    Dim NumberChars As Integer = hex.Length
    Dim bytes As Byte() = New Byte(NumberChars \ 2 - 1) {}
    For i As Integer = 0 To NumberChars - 1 Step 2
        bytes(i \ 2) = Convert.ToByte(hex.Substring(i, 2), 16)
    Next
    Return bytes
End Function

End Class

//////////////////////////////////////
//DYNAMIC C
//////////////////////////////////////
#use AES_CRYPT.LIB
#define AES_BLOCK_SIZE 16
#define BUFFER_SIZE 128

const char AES_KEY[AES_BLOCK_SIZE * 2] = {
  '\x60', '\x3d', '\xeb', '\x10', '\x15', '\xca', '\x71', '\xbe',
  '\x2b', '\x73', '\xae', '\xf0', '\x85', '\x7d', '\x77', '\x81',
  '\x1f', '\x35', '\x2c', '\x07', '\x3b', '\x61', '\x08', '\xd7',
  '\x2d', '\x98', '\x10', '\xa3', '\x09', '\x14', '\xdf', '\xf4',
};

const char AES_IV[AES_BLOCK_SIZE] = {
  '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
  '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F',
};


void ENC_AES_CFB_256(char data_in[], char data_out[]){
  static char buffer[BUFFER_SIZE];
  AESstreamState state;

  memset(buffer,'\0',sizeof(buffer));
  AESinitStream256(&state, AES_KEY, AES_IV);
  memcpy(buffer, data_in, strlen(data_in));
  AESencryptStream(&state, buffer, strlen(buffer));
  strcpy(data_out, buffer);
}

void DEC_AES_CFB_256(char data_in[], char data_out[]){
  static char buffer[BUFFER_SIZE];
  AESstreamState state;

  memset(buffer,'\0',sizeof(buffer));
  AESinitStream256(&state, AES_KEY, AES_IV);
  memcpy(buffer, data_in, strlen(data_in));
  AESdecryptStream(&state, buffer, strlen(buffer));
  strcpy(data_out, buffer);
}


int main(void) {
  static char ot[128], buf1[128];
  int i;

  memset(ot,'\0',sizeof(ot));
  memset(buf1,'\0',sizeof(buf1));

  ENC_AES_CFB_256("0123456789", ot);
  for (i = 0; i < strlen(ot); i++) {
    printf("%02x", ot[i]);
  }
  printf("\n");

  DEC_AES_CFB_256(ot, buf1);
  for (i = 0; i < strlen(buf1); i++) {
    printf(" %c ", buf1[i]);
  }
  printf("\n");

  return 0;
}

///////////////////////////////////////         动态C的更新 //////////////////////////////////////

    #class auto

    #use AES_CRYPT.LIB

    #define AES_BLOCK_SIZE    16  // BYTE
    #define MD5_BLOCK_SIZE    16  // BYTE
    #define AES_BUFFER_SIZE   128 // BYTE

    const char AES_KEY[AES_BLOCK_SIZE * 2] = {
      '\x60', '\x3d', '\xeb', '\x10', '\x15', '\xca', '\x71', '\xbe',
      '\x2b', '\x73', '\xae', '\xf0', '\x85', '\x7d', '\x77', '\x81',
      '\x1f', '\x35', '\x2c', '\x07', '\x3b', '\x61', '\x08', '\xd7',
      '\x2d', '\x98', '\x10', '\xa3', '\x09', '\x14', '\xdf', '\xf4',
    };

    const char AES_IV[AES_BLOCK_SIZE] = {
      '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
      '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F',
    };


    /////////////////// AES CFB - KEY: 32 Byte (256 bit) and BLOCK: 16 byte (128 bit) ///////////////////

    void ENC_AES_CFB_32(char data_in[], char data_out[], int count) { 
       AESstreamState enc_state;
       static char enc_buffer[AES_BUFFER_SIZE];

       memset(enc_buffer,'\0', sizeof(enc_buffer));
       memcpy(enc_buffer, data_in, count);
       enc_buffer[count]='\0';

       AESinitStream256(&enc_state, AES_KEY, AES_IV);
       AESencryptStream(&enc_state, enc_buffer, sizeof(enc_buffer));

       memcpy(data_out, enc_buffer, count);
       data_out[count]='\0';
    }

    void DEC_AES_CFB_32(char data_in[], char data_out[], int count){
       AESstreamState dec_state;
       static char dec_buffer[AES_BUFFER_SIZE];

       memset(dec_buffer,'\0', sizeof(dec_buffer));
       memcpy(dec_buffer, data_in, count);
       dec_buffer[count]='\0';

       AESinitStream256(&dec_state, AES_KEY, AES_IV);
       AESdecryptStream(&dec_state, dec_buffer, sizeof(dec_buffer));

       memcpy(data_out, dec_buffer, count);
       data_out[count]='\0';
    }


    ////////////// MAIN PROGRAM ////////////////////

    int main(void) {

       static char in[AES_BUFFER_SIZE], ot[AES_BUFFER_SIZE], buf[AES_BUFFER_SIZE];
       int i, cnt;

       ////////////// INITIALIZE INPUT CFB ////////////////////

       memset(in,'\0',sizeof(in));          // CLEAR INPUT BUFFER

       //// DATA INPUT (TEST 1)  ////
       //cnt = 10;                           // DATA INPUT LENGTH
       //sprintf(in,"%s","0123496785");      // DATA INPUT

       //// DATA INPUT (TEST 2) ////
      cnt = 82;                            // DATA INPUT LENGTH
      sprintf(in,"%s","0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()_+{}|:L<>?ABCDEFGHIJKLMNOPQRSTUVWXYZ"); // DATA INPUT   

      printf("PLAINT TEXT : %s", in);      // PRINT INPUT
      printf("\n\n");


      ////////////// TEST ENCRYPT WITH CFB ////////////////////

      memset(ot,'\0',sizeof(ot));     // CLEAR OUTPUT BUFFER

      ENC_AES_CFB_32(in, ot, cnt);    // CALL ENCRYPT FUNCTION

      printf("ENCRYPT     : ");       // PRINT OUTPUT
      for (i = 0; i < cnt; i++){
         printf("%02x", ot[i]);
      }
      printf("\n\n");


      ////////////// TEST DECRYPT WITH CFB ////////////////////

      memset(buf,'\0',sizeof(buf));     // CLEAR OUTPUT BUFFER

      DEC_AES_CFB_32(ot, buf, cnt);     // CALL DECRYPT FUNCTION

      printf("DECRYPT     : ");         // PRINT OUTPUT
      for (i = 0; i < cnt; i++) {
         printf("%c", buf[i]);
      }
      printf("\n\n");

      return 0;

    }


    /////////////  OUTPUT TEST 1 ////////////

    // PLAINT TEXT : 0123496785
    // ENCRYPT     : 878e086ec000bfeaafc5
    // DECRYPT     : 0123496785

     /////////////  OUTPUT TEST 2 ////////////

     // PLAINT TEXT : 0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()_+{}|:L<>?ABCDEFGHIJKLMNOPQRSTUVWXYZ
     // ENCRYPT     : 878e086ec00cbfeaafc99bf588aa4a2cbefd574850365f17d882f1dd19fa601e80bbcf845a5f213800d72a5ab8b1aafc87df077ed8695c92e38ce8d3b54071d87274349f806b8afae15f6f3730dbaf8dc4c5
     // DECRYPT     : 0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()_+{}|:L<>?ABCDEFGHIJKLMNOPQRSTUVWXYZ

2 个答案:

答案 0 :(得分:2)

问题是您的VB代码使用的是PKCS#5填充(.NET中的PKCS7)。

你不应该使用CFB填充;作为流模式,永远不会有需要填充的部分块。但是,.NET将PKCS7填充设置为默认值。明确地覆盖它:

…
myRijndael.Mode = CipherMode.CFB
myRijndael.Padding = PaddingMode.None
…

答案 1 :(得分:1)

在C程序中的密文上使用strlenstrcpy可能是问题的一部分。加密数据很容易在其中包含零,因此使用那些期望NULL终止字符串的C函数是不可靠的。在这种特殊情况下,这可能不是问题,但最终可能会导致问题并导致错误。

相关问题