Openssl 从EVP_CIPHER_CTX获取AES密钥

Openssl 从EVP_CIPHER_CTX获取AES密钥,openssl,aes,rsa,libssl,Openssl,Aes,Rsa,Libssl,我正在使用openssl尝试使用RSA公钥加密AES密钥,并使用该AES通过HTTP将大型ish数据发送到第三方站点。我知道这需要很多加密,第二层在网络关闭时出现,数据必须缓存在磁盘上,直到可以POSTed 我一直在使用中的示例代码,其中一部分内联在下面: int aes_init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx) { int i, nrounds =

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

我一直在使用中的示例代码,其中一部分内联在下面:

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;
}
EVP\u CIPHER\u CTX\u set\u key\u length
看起来很有希望,但是否存在某种神奇的偏移量,我必须从中读取
EVP\u CIPHER\u CTX
?否则,我将不得不修改他的函数以返回
键(和
iv
),或者丢弃函数并内联代码

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


那么,唯一的问题就是从
EVP\u CIPHER\u CTX

中提取密钥,为什么要为这种混合加密构建自己的解决方案?现有的标准和方法可以帮助您

我建议您研究一下标准,它是S/MIME的基础。OpenSSL有一个直接的接口。您可以使用非对称密钥告诉它要加密哪些数据,它会为您处理其余的数据

查看
pkcs7\u encrypt
pkcs7\u decrypt
以及
i2d\u pkcs7.*
函数,了解如何将数据提取为可传输格式(以及
d2i\u pkcs7.*
反向)。请参阅OpenSSL的文档:,您可能希望熟悉OpenSSL使用的(这是X509,但d2i部分也适用于此处)

编辑:下面是一个加密示例(解密类似):

#包括
#包括
#包括
#包括
int main()
{
一堆(X509)*证书;
文件*fp;
生物*生物;
PKCS7*p7;
错误加载加密字符串();
OpenSSL_添加_所有算法();
证书=sk_X509_new_null();
fp=fopen(“cert.pem”、“r”);
sk_X509_push(证书、PEM_读取_X509(fp、NULL、NULL、NULL));
fclose(fp);
bio=bio_新_文件(“data.txt”、“r”);
p7=PKCS7加密(证书、bio、执行副总裁des_ede3_cbc(),0);
不含生物素(BIO);
bio=bio_新_文件(“data.txt.enc”、“w”);
i2d_PKCS7_bio(bio,p7);
生物冲洗(BIO);
不含生物素(BIO);
错误打印错误fp(标准输出);
返回0;
}

我已将完整的示例上载到。

为什么密钥和iv不是您要查找的密钥和iv?我只需要足够的数据在另一端对其进行解密。我只需要密钥和盐吗?然后您需要密钥和iv安全地传输到另一端。另一端的相同密钥和iv将完成此工作。因为您使用的是函数EVP_BytesToKey,你可以在另一端使用密钥数据和salt进行解密。密钥数据和salt或密钥和iv都可以安全地在另一端使用。谢谢,将其作为answe发布,当我能够使代码正常工作时,我很乐意接受。随机填充会造成多大问题?另一端需要。密钥数据,salt和nrounds值,什么关于EVP例程使用的填充?嗨,javex,谢谢你的回复。我很感激这个提示!我探索了SMIME,但多部分发布等的想法似乎与我的需要相反。如果我可以简化代码,越多越好。在假设我可以使用RSA公钥加密Arbir的一大块数据后,我会朝这个方向走y大小,然后一位同事告诉我正确的解决方案是使用RSA加密AES密钥,并使用该密钥加密我的数据。如果使用标准解决方案,我会更高兴。而且,我正在将我的
der/d2i
格式密钥内联到我项目的目标文件中,所以我已经走了一段路了!如果你找到更好的解决方案,那就太好了解决方案适合您。但注意路上可能出现的问题。首先想到的是:不要使用RSA v1.5填充,尽可能使用OAEP。还要注意不要在对称加密上使用ECB模式。我不是有意贬低您的解决方案,PKCS7看起来很完美,它看起来正是我想要的,我的意思不是o建议SMIME本身对我不起作用,但是人们通常在SMIME电子邮件中看到的两个base64编码块将是完美的。
$ 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
#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;
}