2016-05-26 92 views
1

我在Rabbit微處理器上使用Dynamic C編程語言。我相信Dynamic C是基於ANSI-C89的,有一些非常微小的變化。他們有一個AES加密庫,我試圖用它來加密數據,然後再將它發送到我的服務器(很少成功)。AES加密/解密 - 動態C到C#

下面是我使用的基於C-AES功能的文檔:

AESinitStream

語法:void AESinitStream(AESstreamState *狀態, 爲const char *鍵, 常量char * init_vector);

描述:設置流狀態結構以開始加密或解密流。一個特定的流狀態只能用於一個方向的 。

PARAMETER1:狀態 - 一個AESstreamState結構被初始化

PARAMETER2:鍵 - 16字節的加密密鑰,使用NULL指針將防止 被重新計算現有的密鑰。

PARAMETER3:init_vector - 一個16字節的數組,表示反饋寄存器的初始狀態 。數據流的兩端必須以相同的初始化向量和密鑰開頭,即 。

AESencryptStream

語法:void AESencryptStream(AESstreamState *狀態, 字符*數據, 詮釋計數);

說明:加密字節

的陣列PARAMETER1:狀態 - AESstreamState結構

PARAMETER2:數據 - 將代替被加密的字節的陣列。

參數3:計數 - 數據數組的大小

這是我的C代碼:

const char key[] = {'\x41', '\x41', '\x37', '\x44', 
         '\x44', '\x34', '\x30', '\x33', 
         '\x30', '\x35', '\x39', '\x4e', 
         '\x36', '\x37', '\x30', '\x38'}; 
    AESstreamState encrypt_state; //built in Dynamic C type 
    char init_vector[16]; 
    int i; 
    int bufLength; 

    sprintf(Buf, "%s", "testabc"); 
    bufLength = strlen(Buf); 

    for (i = 0; i < 16; i++) 
     init_vector[i] = rand() % 255; 

    printf("Key: "); 
    for (i = 0; i < sizeof(key); i++) 
     printf("%d ", key[i]); 
    printf("\n"); 

    AESinitStream(&encrypt_state, key, init_vector); //built in Dynamic C function 
    AESencryptStream(&encrypt_state, Buf, bufLength); //built in Dynamic C function 

    printf("Data: "); 
    for (i = 0; i < strlen(Buf); i++) 
     printf("%d ", Buf[i]); 
    printf("\n"); 

    //set first byte to something that lets the server know it's encrypted 
    //set 2nd through 16th byte to the IV (initialization vector) so every message will be different even if they have the same contents 
    for (i = bufLength-1; i >= 0; i--) 
     Buf[i+17] = Buf[i]; 
    Buf[0] = 237; //φ 

    printf("IV: "); 
    for (i = 1; i < 17; i++) 
    { 
     printf("%d ", init_vector[i-1]); 
     Buf[i] = init_vector[i-1]; 
    } 
    printf("\n"); 

輸出:

鍵:65 65 55 68 68 52 48 51 48 53 57 78 54 55 48 56

Data:249 78 60 83 130 167 37

IV:74 121 108 165 83 120 36 27 161 192 84 76 105 239 34 214

這是我的C#代碼:

private string DecryptAES(byte[] cipherText, byte[] IV) 
    { 
     byte[] key = { 
      0x41, 0x41, 0x37, 0x44, 
      0x44, 0x34, 0x30, 0x33, 
      0x30, 0x35, 0x39, 0x4e, 
      0x36, 0x37, 0x30, 0x38 
     }; 

     // Check arguments. 
     if (cipherText == null || cipherText.Length <= 0) 
     { 
      throw new ArgumentNullException("cipherText"); 
     } 
     else if (IV == null || IV.Length <= 0 || IV.Length != 16) 
     { 
      throw new ArgumentNullException("IV"); 
     } 

     Console.Write("Key: "); 
     for (int i = 0; i < key.Length; i++) 
      Console.Write("{0} ", key[i]); 
     Console.WriteLine(); 

     Console.Write("Data: "); 
     for (int i = 0; i < cipherText.Length; i++) 
      Console.Write("{0} ", cipherText[i]); 
     Console.WriteLine(); 

     Console.Write("IV: "); 
     for (int i = 0; i < IV.Length; i++) 
      Console.Write("{0} ", IV[i]); 
     Console.WriteLine(); 

     // Create an RijndaelManaged object 
     // with the specified key and IV. 
     using (RijndaelManaged rijAlg = new RijndaelManaged()) 
     { 
      rijAlg.Mode = CipherMode.CFB; 
      rijAlg.FeedbackSize = 8; 
      rijAlg.BlockSize = 128; 
      rijAlg.Padding = PaddingMode.None; 

      rijAlg.Key = key; 
      rijAlg.IV = IV; 

      // Create a decrytor to perform the stream transform. 
      ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV); 

      // Create the streams used for decryption. 
      using (System.IO.MemoryStream msDecrypt = new System.IO.MemoryStream(cipherText)) 
      { 
       using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 
       { 
        using (System.IO.StreamReader srDecrypt = new System.IO.StreamReader(csDecrypt)) 
        { 
         // Read the decrypted bytes from the decrypting stream 
         // and place them in a string. 
         string plaintext = null; 

         plaintext = srDecrypt.ReadToEnd(); 

         Console.WriteLine("Decrypted: " + plaintext); 

         return plaintext; 
        } 
       } 

      } 
     } 
    } 

輸出:

鍵:65 65 55 68 68 52 48 51 48 53 57 78 54 55 48 56

Data:249 78 60 83 130 167 37

IV:74 121 108 165 83 120 36 27 161 192 84 76 105 239 34 214

解密:噸{^^ D2

正如你可以看到,我發現了一些奇怪的?輸出在我的解密文本中。任何人都可以指引我走向正確的方向嗎?

我曾嘗試使用動態C成功解密,但如果您認爲內置動態C AES庫是罪魁禍首,您會推薦什麼?

編輯: 所以我決定在這個用C#的AES庫加密,並得到了不同的密碼:

private byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV) 
    { 
     // Check arguments. 
     if (plainText == null || plainText.Length <= 0) 
     { 
      throw new ArgumentNullException("plainText"); 
     } 
     if (Key == null || Key.Length <= 0) 
     { 
      throw new ArgumentNullException("Key"); 
     } 
     if (IV == null || IV.Length <= 0) 
     { 
      throw new ArgumentNullException("IV"); 
     } 
     byte[] encrypted = null; 
     // Create an RijndaelManaged object 
     // with the specified key and IV. 
     using (RijndaelManaged rijAlg = new RijndaelManaged()) 
     { 
      rijAlg.Mode = CipherMode.CFB; 
      rijAlg.FeedbackSize = 8; 
      rijAlg.BlockSize = 128; 
      rijAlg.Padding = PaddingMode.None; 

      rijAlg.Key = Key; 
      rijAlg.IV = IV; 

      // Create a decrytor to perform the stream transform. 
      ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV); 
      // Create the streams used for encryption. 
      using (System.IO.MemoryStream msEncrypt = new System.IO.MemoryStream()) 
      { 
       using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
       { 
        using (System.IO.StreamWriter swEncrypt = new System.IO.StreamWriter(csEncrypt)) 
        { 

         //Write all data to the stream. 
         swEncrypt.Write(plainText); 
        } 
        encrypted = msEncrypt.ToArray(); 
       } 
      } 
     } 

     // Return the encrypted bytes from the memory stream. 
     return encrypted; 

    } 

調用帶有相同的字符串,鍵上面的函數,& IV我最初使用結果在下面的密碼:

249(這是正確的),43,74,118,241,179,235

我將FeedbackSize更改爲16,前兩個字節正確,但它也給我一個錯誤(要加密的數據的長度無效),並將數組大小減小到6個字節。我無能爲力。

這裏是一些使用AESencryptStream的兔子示例代碼片段(他們選擇將IV設置爲與鍵值相同的值)。看來,我正確地使用這個功能,但請告訴我,如果我錯了:

const char key[16] = { 
    '\x06', '\xa9', '\x21', '\x40', '\x36', '\xb8', '\xa1', '\x5b', 
    '\x51', '\x2e', '\x03', '\xd5', '\x34', '\x12', '\x00', '\x06' 
}; 
char bblock[8192]; 
AESstreamState ass; 
memset(bblock, 'A', sizeof(bblock)); 
AESinitStream(&ass, key, key); 
AESencryptStream(&ass, bblock, sizeof(bblock)); 
AESinitStream(&ass, key, key); 
AESdecryptStream(&ass, bblock, sizeof(bblock)); 
+0

哪個鏈接模式你的C AES庫使用?另外你的密文長度沒有意義,因爲它應該是塊長度的多倍(16字節) –

+0

更新:它看起來像你濫用加密函數以及..不能告訴更多,因爲我沒有文檔。但它對我來說沒有多大意義,你對可憐的Buf做了什麼...... –

+0

我正在使用CFB,它不需要是塊長度的倍數(或者至少我認爲)。我將在今天晚些時候發佈文檔中的一些示例代碼:) –

回答

1

看網上AES Encryption作爲參考。

Hex values: 
plaintext: 74657374616263 
key:  41413744443430333035394e36373038 
iv:  000102030405060708090A0B0C0D0E0F 

我沒有測試過如下的代碼,請測試它在您的PC。

DC(動態C)

#use AES_CRYPT.LIB 
#define AES_CFB_BLOCK_SIZE 16 
#define PLAINTEXT_SIZE 7 

//41413744443430333035394e36373038 
const char key[AES_CFB_BLOCK_SIZE] = { 
    '\x41', '\x41', '\x37', '\x44', '\x44', '\x34', '\x30', '\x33', 
    '\x30', '\x35', '\x39', '\x4e', '\x36', '\x37', '\x30', '\x38' 
}; 

//000102030405060708090A0B0C0D0E0F 
const char iv[AES_CFB_BLOCK_SIZE] = { 
    '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', 
    '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F' 
}; 

//testabc = 74657374616263 
const char plntxt[PLAINTEXT_SIZE] = 
{ 
    't', 'e', 's', 't', 'a', 'b', 'c' 
}; 

int main(void) { 
    auto int i; 
    auto char text[256]; 
    auto AESstreamState encrypt_state, decrypt_state; 

    printf("Test case 1 - encrypt aes cfb\n"); 
    AESinitStream(&encrypt_state, key, iv); 

    memcpy(text, plntxt, sizeof(plntxt)); 
    AESencryptStream(&encrypt_state, text, AES_CFB_BLOCK_SIZE); 
    printf("Encrypted text:\n"); 
    for (i = 0; i < sizeof(plntxt); i++) { 
     printf("%02x.", (int) text[i]); 
     if (0 == ((i+1) % PLAINTEXT_SIZE)) printf("\n"); 
    } 
    printf("\n"); 


    printf("Test case 2 - decrypt aes cfb \n"); 
    AESinitStream(&decrypt_state, key, iv); 

    //memcpy(text, cyptxt, sizeof(cyptxt)); 
    AESdecryptStream(&decrypt_state, text, AES_CFB_BLOCK_SIZE); 
    printf("Decrypted text:\n"); 
    for (i = 0; i < sizeof(cyptxt); i++) { 
     printf("%02x.", (int) text[i]); 
     if (0 == ((i+1) % PLAINTEXT_SIZE)) printf("\n"); 
    } 
    printf("\n"); 

    return 0; 
} 

C#

using System; 
using System.IO; 
using System.Security.Cryptography; 


namespace TestAES_CFB 
{ 
    class Program 
    { 

     static byte[] AES_CFB_Encrypt(string plainText, byte[] Key, byte[] IV) 
     { 
      byte[] encrypted; 
      using (Aes aes = Aes.Create()) 
      { 
       aes.KeySize = 128; // 16 bytes 
       aes.BlockSize = 128; // 16 bytes 
       aes.Key = Key; 
       aes.IV = IV; 
       aes.Padding = PaddingMode.Zeros; 
       aes.Mode = CipherMode.CFB; 

       ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); 
       using (MemoryStream msEncrypt = new MemoryStream()) 
       { 
        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
        { 
         using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
         { 
          swEncrypt.Write(plainText); 
         } 
         encrypted = msEncrypt.ToArray(); 
        } 
       } 
      } 

      return encrypted; 
     } 

     static string AES_CFB_Decrypt(byte[] cipherText, byte[] Key, byte[] IV) 
     { 
      string plaintext = null; 

      using (Aes aes = Aes.Create()) 
      { 
       aes.KeySize = 128; // 16 bytes 
       aes.BlockSize = 128; // 16 bytes 
       aes.Key = Key; 
       aes.IV = IV; 
       aes.Padding = PaddingMode.Zeros; 
       aes.Mode = CipherMode.CFB; 


       ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); 
       using (MemoryStream msDecrypt = new MemoryStream(cipherText)) 
       { 
        using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 
        { 
         using (StreamReader srDecrypt = new StreamReader(csDecrypt)) 
         { 

          plaintext = srDecrypt.ReadToEnd(); 
         } 
        } 
       } 

      } 
      return plaintext; 
     } 


     static void Main(string[] args) 
     { 
      const int AES_CFB_BLOCK_SIZE = 16; 
      const int PLAINTEXT_SIZE = 7; 

      //41413744443430333035394e36373038 
      byte[] key = new byte[AES_CFB_BLOCK_SIZE] {0x41, 0x41, 0x37, 0x44, 0x44, 0x34, 0x30, 0x33, 0x30, 0x35, 0x39, 0x4e, 0x36, 0x37, 0x30, 0x38}; 

      //000102030405060708090A0B0C0D0E0F 
      byte[] iv = new byte[AES_CFB_BLOCK_SIZE] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; 

      //testabc = 74657374616263 
      string plntxt = "testabc"; 

      using (Aes myAes = Aes.Create()) 
      { 

       byte[] encrypted = AES_CFB_Encrypt(plntxt, key, iv); 

       string decrypted = AES_CFB_Decrypt(encrypted, key, iv); 

       Console.WriteLine("Encrypted: {0}", BitConverter.ToString(encrypted)); 
       Console.WriteLine("Decrypted: {0}", decrypted); 
       Console.ReadLine(); 
      } 

     } 
    } 
}