EVP Асимметричное шифрование и дешифрование оболочки на C - PullRequest
0 голосов

Я пытаюсь использовать пример openssl https://wiki.openssl.org/index.php/EVP_Asymmetric_Encryption_and_Decryption_of_an_Envelope,, и там были найдены слабые ключи.

Существует 3 пользователя.Каждый пользователь генерирует свои собственные открытые и закрытые ключи RSA.Затем с помощью envelope_seal сообщение становится зашифрованным, и каждый пользователь получает зашифрованный симметричный ключ.

#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>

typedef unsigned char byte;

#define error(message)\
    printf("ERROR: to %s!\n", message);\
    exit(0);

// generate rsa's private and public key pair
void generate_rsa_keys(int bits, RSA **rsa_private, RSA **rsa_public) {
    BIGNUM *bne = BN_new();
    BN_set_word(bne, RSA_F4);
    RSA *rsa = NULL;
    rsa = RSA_new();
    if (1 != RSA_generate_key_ex(rsa, bits, bne, NULL)) {
        error("run RSA_generate_key, and create \'rsa\'");
    }
    *rsa_private = RSAPrivateKey_dup(rsa);
    *rsa_public = RSAPublicKey_dup(rsa);
    BN_free(bne);
    RSA_free(rsa);
}

// 
void envelope_seal(const EVP_CIPHER *cipher, byte **enc_key, int *enc_key_length, byte *iv, EVP_PKEY **pkeys, int pkeys_length, byte *message, int message_length, byte **enc, int *enc_length) {
    int len = 0;
    EVP_CIPHER_CTX *ctx;
    if (!(ctx = EVP_CIPHER_CTX_new())) {
        error("create and initialise the cipher context \'ctx\'");
    }
    if (pkeys_length != EVP_SealInit(ctx, cipher, enc_key, enc_key_length, iv, pkeys, pkeys_length)) {
        error("init the seal operation");
    }
    if (1 != EVP_SealUpdate(ctx, *enc, enc_length, message, message_length)) {
        error("provide the \'message\' to be encrypted");
    }
    if (1 != EVP_SealFinal(ctx, *enc + *enc_length, &len)) {
        error("finalize the encryption");
    }
    *enc_length += len;
    EVP_CIPHER_CTX_free(ctx);
}

void envelope_open(const EVP_CIPHER *cipher, byte *enc_key, int enc_key_length, byte *iv, EVP_PKEY *pkey_private, byte *enc, int enc_length, byte **dec, int *dec_length) {
    int len = 0;
    EVP_CIPHER_CTX *ctx;
    if (!(ctx = EVP_CIPHER_CTX_new())) {
        error("create and initialise the cipher context \'ctx\'");
    }
    if (1 != EVP_OpenInit(ctx, cipher, enc_key, enc_key_length, iv, pkey_private)) {
        error("init the open operation");
    }
    if (1 != EVP_OpenUpdate(ctx, *dec, dec_length, enc, enc_length)) {
        error("provide the \'message\' to be decrypted");
    }
    if (1 != EVP_OpenFinal(ctx, *dec + *dec_length, &len)) {
        error("finalize the decryption");
    }
    *dec_length += len;
    EVP_CIPHER_CTX_free(ctx);
}

int main(int argc, char *argv[]) {
    // RSA seeding
    int seed[] = {0, 1, 2, 3, 4, 5, 6, 7};
    RAND_seed(seed, 8);

    // simple message to encrypt.
    byte *message = "The quick brown fox jumps over the lazy dog.";
    size_t message_length = strlen(message);
    // algorithm aes cbc, because we do not want to handle iv
    const EVP_CIPHER *cipher = EVP_aes_256_cbc();

    // user 1
    RSA *rsa_private0 = NULL, *rsa_public0;
    generate_rsa_keys(2048, &rsa_private0, &rsa_public0);
    EVP_PKEY *pkey_private0 = EVP_PKEY_new(), *pkey_public0 = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pkey_private0, RSAPrivateKey_dup(rsa_private0));
    EVP_PKEY_assign_RSA(pkey_public0, RSAPublicKey_dup(rsa_public0));

    // user 2
    RSA *rsa_private1 = NULL, *rsa_public1;
    generate_rsa_keys(3072, &rsa_private1, &rsa_public1);
    EVP_PKEY *pkey_private1 = EVP_PKEY_new(), *pkey_public1 = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pkey_private1, RSAPrivateKey_dup(rsa_private1));
    EVP_PKEY_assign_RSA(pkey_public1, RSAPublicKey_dup(rsa_public1));

    // user 3
    RSA *rsa_private2 = NULL, *rsa_public2;
    generate_rsa_keys(4096, &rsa_private2, &rsa_public2);
    EVP_PKEY *pkey_private2 = EVP_PKEY_new(), *pkey_public2 = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pkey_private2, RSAPrivateKey_dup(rsa_private2));
    EVP_PKEY_assign_RSA(pkey_public2, RSAPublicKey_dup(rsa_public2));

    // allocating space for data
    int pkeys_length = 3;
    EVP_PKEY **pkeys = (EVP_PKEY **)calloc(sizeof(EVP_PKEY *), pkeys_length);
    pkeys[0] = pkey_public0;
    pkeys[1] = pkey_public1;
    pkeys[2] = pkey_public2;
    byte **enc_keys = (byte **)calloc(sizeof(byte *), pkeys_length);
    enc_keys[0] = (byte *)OPENSSL_malloc(RSA_size(rsa_public0));
    enc_keys[1] = (byte *)OPENSSL_malloc(RSA_size(rsa_public1));
    enc_keys[2] = (byte *)OPENSSL_malloc(RSA_size(rsa_public2));
    int *enc_key_lengths = (int *)calloc(sizeof(int), pkeys_length);
    enc_key_lengths[0] = RSA_size(rsa_public0);
    enc_key_lengths[1] = RSA_size(rsa_public1);
    enc_key_lengths[2] = RSA_size(rsa_public2);
    int iv_length = EVP_CIPHER_iv_length(cipher);
    byte *iv = (byte *)OPENSSL_malloc(iv_length);

    // encrypting message
    int enc_length = 0;
    byte *enc = (byte *)OPENSSL_malloc(1024);
    envelope_seal(cipher, enc_keys, enc_key_lengths, iv, pkeys, pkeys_length, message, message_length, &enc, &enc_length);

    // each user decrypt his key
    int dec_key_length0 = EVP_CIPHER_key_length(cipher);
    byte *dec_key0 = (byte *)OPENSSL_malloc(dec_key_length0);
    RSA_private_decrypt(enc_key_lengths[0], enc_keys[0], dec_key0, rsa_private0, RSA_PKCS1_OAEP_PADDING);
    printf("The 1 user:\n");
    BIO_dump_fp(stdout, enc_keys[0], enc_key_lengths[0]);
    printf("key:\n");
    BIO_dump_fp(stdout, dec_key0, dec_key_length0);

    int dec_key_length1 = EVP_CIPHER_key_length(cipher);
    byte *dec_key1 = (byte *)OPENSSL_malloc(dec_key_length1);
    RSA_private_decrypt(enc_key_lengths[1], enc_keys[1], dec_key1, rsa_private1, RSA_PKCS1_OAEP_PADDING);
    printf("The 2 user:\n");
    BIO_dump_fp(stdout, enc_keys[1], enc_key_lengths[1]);
    printf("key:\n");
    BIO_dump_fp(stdout, dec_key1, dec_key_length1);

    int dec_key_length2 = EVP_CIPHER_key_length(cipher);
    byte *dec_key2 = (byte *)OPENSSL_malloc(dec_key_length2);
    RSA_private_decrypt(enc_key_lengths[2], enc_keys[2], dec_key2, rsa_private2, RSA_PKCS1_OAEP_PADDING);
    printf("The 3 user:\n");
    BIO_dump_fp(stdout, enc_keys[2], enc_key_lengths[2]);
    printf("key:\n");
    BIO_dump_fp(stdout, dec_key2, dec_key_length2);

    // each user decrypt message with his private key and provided symm. enc key.
    printf("Dec message:\n");
    int dec_length0 = 0;
    byte *dec0 = (byte *)OPENSSL_malloc(1024);
    envelope_open(cipher, enc_keys[0], enc_key_lengths[0], iv, pkey_private0, enc, enc_length, &dec0, &dec_length0);
    printf("The 1 user:\n");
    BIO_dump_fp(stdout, enc, enc_length);
    BIO_dump_fp(stdout, dec0, dec_length0);

    int dec_length1 = 0;
    byte *dec1 = (byte *)OPENSSL_malloc(1024);
    envelope_open(cipher, enc_keys[1], enc_key_lengths[1], iv, pkey_private1, enc, enc_length, &dec1, &dec_length1);
    printf("The 2 user:\n");
    BIO_dump_fp(stdout, enc, enc_length);
    BIO_dump_fp(stdout, dec1, dec_length1);

    int dec_length2 = 0;
    byte *dec2 = (byte *)OPENSSL_malloc(1024);
    envelope_open(cipher, enc_keys[2], enc_key_lengths[2], iv, pkey_private2, enc, enc_length, &dec2, &dec_length2);
    printf("The 3 user:\n");
    BIO_dump_fp(stdout, enc, enc_length);
    BIO_dump_fp(stdout, dec2, dec_length2);
    return 0;
}

Симметричный ключ для пользователя 1:

0000 - 70 12 3e a1 a3 55 00 00-00 00 00 00 00 00 00 00   p.>..U..........
0010 - 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

Симметричный ключ дляпользователь 2:

0000 - 20 37 3e a1 a3 55 00 00-00 00 00 00 00 00 00 00    7>..U..........
0010 - 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

Симметричный ключ для пользователя 3:

0000 - 10 ef 3d a1 a3 55 00 00-00 00 00 00 00 00 00 00   ..=..U..........
0010 - 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

Один и тот же симметричный ключ ожидался для каждого пользователя.Первые байты ключей отличаются, и большинство байтов - нули.Как правильно выполнить это действие?Я правильно получаю ключ RSA, не так ли?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...