从EVP_CIPHER_CTX获取AES键

时间:2022-04-12 14:32:17

I'm using openssl trying to use an RSA public key, to encrypt an AES key, and use that AES to send large-ish data over HTTP(s) to a 3rd party site. I know that's a lot of encryption, the second layer comes when the network is down, and the data has to be cached on disk until it can be POSTed.

我正在使用openssl尝试使用RSA公钥加密AES密钥,并使用该公钥通过HTTP(s)向第三方站点发送大数据。我知道这需要大量的加密,当网络关闭时,第二层就会出现,数据必须被缓存到磁盘上,直到可以发布为止。

I've been using the example code from this blog, a chunk of which is inlined below:

我一直在使用这个博客的示例代码,其中一段代码如下所示:

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;
}

I'd like to stick with his aes_init() function, but I can't find a way to get the key out of the EVP_CIPHER_CTX once it has been initialised.

我希望继续使用他的aes_init()函数,但是一旦EVP_CIPHER_CTX被初始化,我就无法找到从它获取密钥的方法。

apropos lists a few functions relating to EVP_CIPHER_CTX:

列出了与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 looks promising, but is there then some magical offset from which I have to read the EVP_CIPHER_CTX? Otherwise, I'll have to modify his function to return the key (and the iv), or throw away the function and inline the code.

EVP_CIPHER_CTX_set_key_length看起来很有希望,但是是否有一些不可思议的偏移量,我必须读取EVP_CIPHER_CTX?否则,我将不得不修改他的函数来返回键(和iv),或者丢弃函数并内联代码。

The end goal here is to encrypt a large portion of data using AES, and encrypt the AES key using our RSA public key, base64 encode both, and broadcast them to the server. (Which I believe is the correct way of doing things)

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

The only issue then, is extracting the key from the EVP_CIPHER_CTX.

那么,惟一的问题就是从EVP_CIPHER_CTX中提取密钥。

1 个解决方案

#1


2  

Why would you want to build your own solution to this kind of hybrid cryptography? There are already existing standards and methods that can help you.

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

I recommend you look into the PKCS#7 standard, which is the basis for S/MIME. OpenSSL has a direct interface to it. You tell it which data you want to encrypt using an asymmetric key and it handles the rest for you.

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

Look at pkcs7_encrypt and pkcs7_decrypt as well as the i2d_PKCS7_* functions for how to extract that data into a transmittable format (and d2i_PKCS7_* for reverse). See OpenSSL's documentation: PKCS7_encrypt, PKCS7_decrypt and you might want to familiarize yourself with the i2d/d2i convention used by OpenSSL (this is X509 but the d2i part applies here as well.

看看pkcs7_encrypt pkcs7_decrypt以及i2d_PKCS7_ *函数如何提取数据到剧增格式(反向和d2i_PKCS7_ *)。看到OpenSSL文档:PKCS7_encrypt PKCS7_decrypt,您可能想要熟悉i2d / d2i公约所使用OpenSSL(这是X509但d2i部分在这里也同样适用。

Edit: Here is an example for encryption (decryption is analogous):

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

#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;
}

I have uploaded the full example to my repository.

我已经将完整的示例上载到我的存储库中。

#1


2  

Why would you want to build your own solution to this kind of hybrid cryptography? There are already existing standards and methods that can help you.

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

I recommend you look into the PKCS#7 standard, which is the basis for S/MIME. OpenSSL has a direct interface to it. You tell it which data you want to encrypt using an asymmetric key and it handles the rest for you.

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

Look at pkcs7_encrypt and pkcs7_decrypt as well as the i2d_PKCS7_* functions for how to extract that data into a transmittable format (and d2i_PKCS7_* for reverse). See OpenSSL's documentation: PKCS7_encrypt, PKCS7_decrypt and you might want to familiarize yourself with the i2d/d2i convention used by OpenSSL (this is X509 but the d2i part applies here as well.

看看pkcs7_encrypt pkcs7_decrypt以及i2d_PKCS7_ *函数如何提取数据到剧增格式(反向和d2i_PKCS7_ *)。看到OpenSSL文档:PKCS7_encrypt PKCS7_decrypt,您可能想要熟悉i2d / d2i公约所使用OpenSSL(这是X509但d2i部分在这里也同样适用。

Edit: Here is an example for encryption (decryption is analogous):

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

#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;
}

I have uploaded the full example to my repository.

我已经将完整的示例上载到我的存储库中。