1

私はopensslを使用して、RSA公開鍵を使用し、AES鍵を暗号化し、そのAESを使用してHTTP経由で大きなデータをサードパーティのサイトに送信しようとしています。POST私はそれが多くの暗号化であることを知っています.2番目のレイヤーはネットワークがダウンしたときに来ます.データは編集できるようになるまでディスクにキャッシュする必要があります.

このブログのサンプル コードを使用してきました。その一部を以下にインライン化します。

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 公開キーを使用して AES キーを暗号化し、両方を base64 エンコードして、サーバーにブロードキャストすることです。(これが正しいやり方だと私は信じています)

唯一の問題は、からキーを抽出することEVP_CIPHER_CTXです。

4

1 に答える 1

2

この種のハイブリッド暗号化に対する独自のソリューションを構築する必要があるのはなぜですか? あなたを助けることができる既存の標準と方法がすでにあります。

S/MIME の基礎となっているPKCS#7標準を調べることをお勧めします。OpenSSL には、それへの直接インターフェースがあります。非対称キーを使用して暗号化するデータを指定すると、残りは処理されます。

そのデータを送信可能な形式に抽出する方法 (および逆方向) については、pkcs7_encryptおよび関数を参照してください。OpenSSL のドキュメント: PKCS7_encryptPKCS7_decryptを参照してください。OpenSSL で使用されるi2d/d2i 規則に慣れる必要があるかもしれません(これは X509 ですが、d2i の部分はここでも適用されます。pkcs7_decrypti2d_PKCS7_*d2i_PKCS7_*

編集:これは暗号化の例です(復号化は類似しています):

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

完全な例を自分のリポジトリにアップロードしました。

于 2013-04-14T18:40:13.873 に答える