2013-04-14 184 views
1

我正在使用openssl尝试使用RSA公钥来加密AES密钥,并使用该AES通过HTTP将大数据发送到第三方站点。我知道这是很多加密技术,第二层出现在网络关闭时,并且数据必须缓存在磁盘上,直到它可以是POST ed。从EVP_CIPHER_CTX获取AES密钥

我一直在使用的示例代码this blog,一大块,其中内联如下:

int aes_init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx) 
{ 
    int i, nrounds = 5; 
    unsigned char key[32], iv[32]; 
    /* 
    * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material. 
    * nrounds is the number of times the we hash the material. More rounds are more secure but 
    * slower. 
    */ 
    i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, key_data_len, nrounds, key, iv); 
    if (i != 32) { 
    printf("Key size is %d bits - should be 256 bits\n", i); 
    return -1; 
    } 
    for(int x = 0; x<32; ++x) 
    printf("Key: %x iv: %x \n", key[x], iv[x]); 
    for(int x = 0; x<8; ++x) 
    printf("salt: %x\n", salt[x]); 
    EVP_CIPHER_CTX_init(e_ctx); 
    EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv); 
    return 0; 
} 

我想坚持与他aes_init()功能,但我不能找到一种方法,一旦它被初始化,从EVP_CIPHER_CTX中获得密钥。

apropos列出有关EVP_CIPHER_CTX几个功能:

$ apropos EVP_CIPHER_CTX 
EVP_CIPHER_CTX_block_size (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_cipher (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_cleanup (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_ctrl (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_flags (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_get_app_data (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_init (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_iv_length (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_key_length (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_mode (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_nid (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_set_app_data (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_set_key_length (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_set_padding (3ssl) - EVP cipher routines 
EVP_CIPHER_CTX_type (3ssl) - EVP cipher routines 

EVP_CIPHER_CTX_set_key_length看起来很有希望,但有那么一些神奇的偏移从我读EVP_CIPHER_CTX?否则,我将不得不修改其功能以返回key(和iv),或丢弃该函数并内联代码。

这里的最终目标是使用AES加密大部分数据,并使用我们的RSA公钥对base64密码进行加密,然后将它们广播到服务器。 (我相信这是正确的做事方式)

唯一的问题是,从EVP_CIPHER_CTX中提取密钥。

+0

为什么密钥和IV不是密钥和IV,你正在寻找 – doptimusprime

+0

我只是需要足够的解密它在th? e另一面 –

+0

我是否只需要key_data和salt? –

回答

2

为什么要为这种混合密码构建自己的解决方案?现有的标准和方法可以帮助您。

我建议你看一下PKCS#7标准,这是S/MIME的基础。 OpenSSL有一个直接的接口。您可以使用非对称密钥来告诉您要加密哪些数据,并为您处理剩余的数据。

请看pkcs7_encryptpkcs7_decrypt以及i2d_PKCS7_*如何将数据提取为可传输格式(和d2i_PKCS7_*反向)。请参阅OpenSSL的文档:PKCS7_encryptPKCS7_decrypt你可能需要熟悉与OpenSSL的使用i2d/d2i convention(这是X509,但D2I部分在这里也适用

编辑:这里是加密的一个例子(解密类似):

#include <stdio.h> 
#include <openssl/pem.h> 
#include <openssl/crypto.h> 
#include <openssl/err.h> 


int main() 
{ 
    STACK_OF(X509) *certs; 
    FILE *fp; 
    BIO *bio; 
    PKCS7 *p7; 

    ERR_load_crypto_strings(); 
    OpenSSL_add_all_algorithms(); 

    certs = sk_X509_new_null(); 
    fp = fopen("cert.pem", "r"); 
    sk_X509_push(certs, PEM_read_X509(fp, NULL, NULL, NULL)); 
    fclose(fp); 

    bio = BIO_new_file("data.txt", "r"); 
    p7 = PKCS7_encrypt(certs, bio, EVP_des_ede3_cbc(), 0); 
    BIO_free(bio); 

    bio = BIO_new_file("data.txt.enc", "w"); 
    i2d_PKCS7_bio(bio, p7); 
    BIO_flush(bio); 
    BIO_free(bio); 

    ERR_print_errors_fp(stdout); 
    return 0; 
} 

我已经上传了完整的例子来my repository

+0

嗨javex,谢谢你的回应。我欣赏小费!我探索了SMIME,但是多部分发布等的想法看起来与我所需要的相反。如果我可以简化我的代码,那么越好。 –

+0

假设我可以使用RSA公钥加密任意大小,然后的数据块的一位同事被告知正确的解决方案是使用RSA加密AES密钥,并加密后我会在这个方向我的数据与该密钥。使用标准解决方案我会更快乐。 –

+0

而且,我在我的内联德'/ d2i'格式钥匙到我的项目的目标文件,所以我已经部分地在这条道路! –