2012-02-07 82 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