2012-02-07 83 views
1

爲什麼我在使用openssl aes命令工具和openssl AES apis時會得到不同的密文?當我使用OpenSSL AES命令行工具和OpenSSL AES API時,會出現不同的密文?

我已經使用三種類型的加密:在javax.cryto

  • A型)的OpenSSL命令行工具
  • B型)類
  • C型)的OpenSSL C API。

使用類型(a)和(b),我得到了相同的密文。但是當使用(c)時我得到了不同的密文。

我想在使用方法c和方法a/b時得到相同的密文。 我認爲c類型有問題,但找不到它。請注意,我在上述三種方法中使用了相同的KEY,IV對。

鍵入

openssl enc -aes-128-cbc -e -a -in pt.txt -out ct.txt -K 01010101010101010101010101010101 -iv 01010101010101010101010101010101 -p 

b型
Java代碼使用javax.crypto中。我不會粘貼代碼,因爲這樣我得到了與Type a相同的密文。

鍵入c: C代碼使用OpenSSL API:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <openssl/aes.h> 

int main(int argc, char** argv) { 

    AES_KEY aes; 
    unsigned char key[AES_BLOCK_SIZE];  // AES_BLOCK_SIZE = 16 
    unsigned char iv[AES_BLOCK_SIZE];  // init vector 
    unsigned char* input_string; 
    unsigned char* encrypt_string; 
    unsigned char* decrypt_string; 
    unsigned int len;  // encrypt length (in multiple of AES_BLOCK_SIZE) 
    unsigned int i; 

    // check usage 
    if (argc != 2) { 
     fprintf(stderr, "%s <plain text>\n", argv[0]); 
     exit(-1); 
    } 

    // set the encryption length 
    len = 0; 
    if (strlen(argv[1])>=AES_BLOCK_SIZE || 
     (strlen(argv[1]) + 1) % AES_BLOCK_SIZE == 0) { 
     len = strlen(argv[1]) + 1; 
    } else { 
     len = ((strlen(argv[1]) + 1)/AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE; 
    } 

    // set the input string 
    input_string = (unsigned char*)calloc(len, sizeof(unsigned char)); 
    if (input_string == NULL) { 
     fprintf(stderr, "Unable to allocate memory for input_string\n"); 
     exit(-1); 
    } 
    strncpy((char*)input_string, argv[1], strlen(argv[1])); 

    // Generate AES 128-bit key 
    memset(key, 0x01, AES_BLOCK_SIZE); 

    // Set encryption key 
    memset(iv, 0x01, AES_BLOCK_SIZE); 
    if (AES_set_encrypt_key(key, 128, &aes) < 0) { 
     fprintf(stderr, "Unable to set encryption key in AES\n"); 
     exit(-1); 
    } 

    // alloc encrypt_string 
    encrypt_string = (unsigned char*)calloc(len, sizeof(unsigned char));  
    if (encrypt_string == NULL) { 
     fprintf(stderr, "Unable to allocate memory for encrypt_string\n"); 
     exit(-1); 
    } 

    // encrypt (iv will change) 
    AES_cbc_encrypt(input_string, encrypt_string, len, &aes, iv, AES_ENCRYPT); 

    ///////////////////////////////////// 

    // alloc decrypt_string 
    decrypt_string = (unsigned char*)calloc(len, sizeof(unsigned char)); 
    if (decrypt_string == NULL) { 
     fprintf(stderr, "Unable to allocate memory for decrypt_string\n"); 
     exit(-1); 
    } 

    // Set decryption key 
    memset(iv, 0x01, AES_BLOCK_SIZE); 
    if (AES_set_decrypt_key(key, 128, &aes) < 0) { 
     fprintf(stderr, "Unable to set decryption key in AES\n"); 
     exit(-1); 
    } 

    // decrypt 
    AES_cbc_encrypt(encrypt_string, decrypt_string, len, &aes, iv, 
      AES_DECRYPT); 

    // print 
    printf("input_string =%s\n", input_string); 
    printf("encrypted string ="); 
    for (i=0; i<len; ++i) { 
     printf("%u ", encrypt_string[i]);  
    } 
    printf("\n"); 
    printf("decrypted string =%s\n", decrypt_string); 

    return 0; 
} 

有什麼能爲不同的輸出的原因嗎?

+0

什麼是輸入和不同的輸出?它們是完全不同的,還是隻在最後一塊? – 2012-02-09 23:11:53

+0

我在這裏無法過去我的結果,bcz這個網站抱怨這種格式!所以我把結果通過另一個網站,請參閱http://topic.csdn.net/u/20120207/16/48183c46-8afd-47d9-a260-7a5eb571f877.html?seed=661539550&r=77510138#r_77510138中文deveplop bbs ,請參閱分組四。謝謝! – user1194299 2012-02-10 05:40:17

回答

2

在你的C代碼,你基本上是使用零填充:您分配由零填充(由calloc)的存儲區域,然後將純文本複製到這個區域,留下末尾的零不變。

openssl enc使用與您的C代碼不同的填充。該documentation for openssl enc說(由我強調):

所有塊密碼通常使用PKCS#5填充也稱爲標準 塊填充:這允許進行基本的完整性和口令檢查。 但是由於隨機數據通過測試的機會比256更好,所以它不是一個很好的測試。

另外,openssl enc命令默認使用salt,它將密文隨機化。鹽與每個消息初始化向量(IV)具有類似的用途。但是你使用明確的IV,所以鹽是而不是隨機化密文。

documentation for javax.crypto.Cipher(我想你使用)表示:

的變換的形式是:

  • 「算法/模式/填充」
  • 「算法「

(在後一種情況下,模式的供應商特定默認值和填充 使用方案)。例如,以下是有效的轉換:

Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding"); 

所以,如果你只是使用AESARS/CBC沒有標明填充模式,它使用任何它找到配件,而你的情況正好是相同的就像OpenSSL使用的那樣(即PKCS#5填充)。

要改變你的C程序,你必須自己做相同的填充(本質上,填充塊的數量x字節,所有這些都與這個數字相同的值,同時附加一個整體當最後一個塊已滿時,塊填充16) - 或者使用更高級別的EVP功能,它應該爲您提供一種指定密碼填充模式的方法。

+0

Paulo Ebermann,你完全正確!這是填充問題!我犯了那個愚蠢的錯誤!我會將結果粘貼到網站http://topic.csdn.net/u/20120207/16/48183c46-8afd-47d9-a260-7a5eb571f877.html。非常感謝你的幫助。我想和你交朋友。我的電子郵件是dungeonsnd#126.com或dungeonsnd#gmail.com。再次感謝。 – user1194299 2012-02-10 17:10:37

+1

如果我的答案幫助您找到解決方案,請隨時通過單擊旁邊的大複選標記圖標將其標記爲*接受*。這是*在本網站上說「謝謝」的方式。 – 2012-02-10 18:27:29