我正在使用openssl尝试使用RSA公钥,加密AES密钥,并使用该AES通过HTTP将大型数据发送到第三方站点。我知道这是很多加密,第二层是在网络关闭时出现的,数据必须缓存在磁盘上,直到它被POST
编辑。
我一直在使用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
(以及EVP_CIPHER_CTX
),或者丢弃函数并内联代码。
这里的最终目标是使用AES加密大部分数据,并使用我们的RSA公钥加密AES密钥,base64编码,并将它们广播到服务器。 (我认为这是正确的做事方式)
唯一的问题是从{{1}}中提取密钥。
答案 0 :(得分:2)
为什么要为这种混合密码术构建自己的解决方案?已有的标准和方法可以帮助您。
我建议您查看PKCS#7标准,这是S / MIME的基础。 OpenSSL有一个直接的接口。您可以使用非对称密钥告诉它要加密哪些数据,并为您处理其余数据。
查看pkcs7_encrypt
和pkcs7_decrypt
以及i2d_PKCS7_*
函数,了解如何将数据提取为可传输格式(以及d2i_PKCS7_*
进行反向)。请参阅OpenSSL的文档:PKCS7_encrypt,PKCS7_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。