C语言 使用OpenSSL加密/解密

2lpgd968  于 2023-06-21  发布在  其他
关注(0)|答案(2)|浏览(162)

我正在研究密钥协商协议。在一个点上卡住了,我想加密和发送消息从服务器和接收和解密在客户端。以下是服务器的代码片段。

// Generate an initialization vector (IV) for CBC mode
    const EVP_CIPHER* cipher = EVP_aes_256_cbc(); // Use the desired cipher algorithm
    EVP_CIPHER_CTX* ctx_encrypt = EVP_CIPHER_CTX_new();
    const unsigned char* plaintext = sessionKey;
    size_t plaintext_len = sessionKeyLen;
    const int MAX_TEXT_LENGTH = 256;
    unsigned char iv[EVP_MAX_IV_LENGTH];
    
    // Initialize the encryption/decryption context
    if (EVP_CipherInit_ex(ctx_encrypt, cipher, NULL, NULL, NULL, 1) != 1) {
    fprintf(stderr, "Error initializing the cipher context\n");
    EVP_CIPHER_CTX_free(ctx_encrypt);
    return;
    }

    // Set the session key
    if (EVP_CIPHER_CTX_set_key_length(ctx_encrypt, skeylen) != 1) {
    fprintf(stderr, "Error setting the key length\n");
    EVP_CIPHER_CTX_free(ctx_encrypt);
    return;
    }

    if (EVP_CipherInit_ex(ctx_encrypt, NULL, NULL, skey, NULL, -1) != 1) {
    fprintf(stderr, "Error setting the session key\n");
    EVP_CIPHER_CTX_free(ctx_encrypt);
    return;
    }
    
    if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) != 1) {
        fprintf(stderr, "Error generating IV\n");
        exit(1);
    }

    // Set the IV for the encryption operation
    if (EVP_EncryptInit_ex(ctx_encrypt, EVP_aes_256_cbc(), NULL, skey, iv) != 1) {
        fprintf(stderr, "Error setting encryption IV\n");
        exit(1);
    }

    // Encrypt the plaintext (session key)
    unsigned char ciphertext[MAX_TEXT_LENGTH + EVP_MAX_BLOCK_LENGTH];
    int ciphertext_len;

    if (EVP_EncryptUpdate(ctx_encrypt, ciphertext, &ciphertext_len, plaintext, plaintext_len) != 1) {
        fprintf(stderr, "Error encrypting data\n");
        exit(1);
    }

    // Finalize the encryption
    int final_len;
    if (EVP_EncryptFinal_ex(ctx_encrypt, ciphertext + ciphertext_len, &final_len) != 1) {
        fprintf(stderr, "Error finalizing encryption\n");
        exit(1);
    }
    ciphertext_len += final_len;

    const size_t ivLength = EVP_CIPHER_iv_length(EVP_aes_256_cbc()); // Get the length of the IV
    const size_t concatenatedMessageLength = ivLength + ciphertext_len;
    unsigned char concatenatedMessage[concatenatedMessageLength];

    memcpy(concatenatedMessage, iv, ivLength);
    memcpy(concatenatedMessage + ivLength, ciphertext, ciphertext_len);

    printf("Concatenated Message 1:\n");
    for (size_t i = 0; i < concatenatedMessageLength; i++) {
        printf("%02x", concatenatedMessage[i]);
    }
    printf("\n");

    EVP_CIPHER_CTX_free(ctx_encrypt);

    // Preparing for Bob's share

    // Generate an initialization vector (IV) for CBC mode
    plaintext = (const unsigned char*)"Verification Message SessionKey";
    plaintext_len = strlen((const char*)plaintext);
    EVP_CIPHER_CTX* ctx_encrypt2 = EVP_CIPHER_CTX_new();

    // Initialize the encryption/decryption context
    if (EVP_CipherInit_ex(ctx_encrypt2, cipher, NULL, NULL, NULL, 1) != 1) {
    fprintf(stderr, "Error initializing the cipher context\n");
    EVP_CIPHER_CTX_free(ctx_encrypt2);
    return;
    }

    // Set the session key
    if (EVP_CIPHER_CTX_set_key_length(ctx_encrypt2, sessionKeyLen) != 1) {
    fprintf(stderr, "Error setting the key length\n");
    EVP_CIPHER_CTX_free(ctx_encrypt2);
    return;
    }

    if (EVP_CipherInit_ex(ctx_encrypt2, NULL, NULL, sessionKey, NULL, -1) != 1) {
    fprintf(stderr, "Error setting the session key\n");
    EVP_CIPHER_CTX_free(ctx_encrypt2);
    return;
    }

    if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) != 1) {
        fprintf(stderr, "Error generating IV\n");
        exit(1);
    }

    // Set the IV for the encryption operation
    if (EVP_EncryptInit_ex(ctx_encrypt2, EVP_aes_256_cbc(), NULL, sessionKey, iv) != 1) {
        fprintf(stderr, "Error setting encryption IV\n");
        exit(1);
    }

    // Encrypt the plaintext (Bob's share)
    if (EVP_EncryptUpdate(ctx_encrypt2, ciphertext, &ciphertext_len, plaintext, plaintext_len) != 1) {
        fprintf(stderr, "Error encrypting data\n");
        exit(1);
    }

    // Finalize the encryption
    if (EVP_EncryptFinal_ex(ctx_encrypt2, ciphertext + ciphertext_len, &final_len) != 1) {
        fprintf(stderr, "Error finalizing encryption\n");
        exit(1);
    }
    ciphertext_len += final_len;
    const size_t concatenatedMessageLength2 = ivLength + ciphertext_len;
    unsigned char concatenatedMessage2[concatenatedMessageLength2];

    memcpy(concatenatedMessage2, iv, ivLength);
    memcpy(concatenatedMessage2 + ivLength, ciphertext, ciphertext_len);

    printf("Concatenated Message 2:\n");
    for (size_t i = 0; i < concatenatedMessageLength2; i++) {
        printf("%02x", concatenatedMessage2[i]);
    }
    printf("\n");

    EVP_CIPHER_CTX_free(ctx_encrypt2);

    // Sending Server Share and Verification Message
    if (concatenatedMessageLength > 0) {
        send(client_sock_Bob, concatenatedMessage, concatenatedMessageLength, 0);
        // Send the encrypted hash to the server
        usleep(100);
        if (concatenatedMessageLength2 > 0) {
            send(client_sock_Bob, concatenatedMessage2, concatenatedMessageLength2, 0);
        } else {
            printf("Server Verification message is Null: %s\n");
        }
    } else {
        printf("Session key is Null : %s\n");
    }`

在此代码中,要加密的第一条消息是一个sessionkey,由密钥'skey'(一个数组)加密。下一条消息由会话密钥加密。在客户端,客户端只有skey(一个数组),它将首先解密并获得会话密钥,然后使用该会话密钥解密下一条消息。下面是代码

`const EVP_CIPHER* cipher = EVP_aes_256_cbc(); // Use the desired cipher algorithm
    EVP_CIPHER_CTX* ctx_decrypt = EVP_CIPHER_CTX_new();
    char decryptedText1[1024] = {0};
    char decryptedText2[1024] = {0};
    int decryptedText1_len = 0;
    int decryptedText2_len = 0;
    memset(decryptedText1, 0, sizeof(decryptedText1));

    // Initialize the encryption/decryption context
    if (EVP_CipherInit_ex(ctx_decrypt, cipher, NULL, NULL, NULL, 1) != 1) {
    fprintf(stderr, "Error initializing the cipher context\n");
    EVP_CIPHER_CTX_free(ctx_decrypt);
    return;
    }

    // Set the session key
    if (EVP_CIPHER_CTX_set_key_length(ctx_decrypt, skeylen) != 1) {
    fprintf(stderr, "Error setting the key length\n");
    EVP_CIPHER_CTX_free(ctx_decrypt);
    return;
    }

    if (EVP_CipherInit_ex(ctx_decrypt, NULL, NULL, skey, NULL, -1) != 1) {
    fprintf(stderr, "Error setting the session key\n");
    EVP_CIPHER_CTX_free(ctx_decrypt);
    return;
    }
    
    // Extract the IV from the concatenated message 2
    memcpy(iv, concatenatedMessage2, EVP_MAX_IV_LENGTH);

    // Set the IV for the decryption operation
    if (EVP_DecryptInit_ex(ctx_decrypt, EVP_aes_256_cbc(), NULL, skey, iv) != 1) {
    fprintf(stderr, "Error setting decryption IV\n");
    exit(1);
    }

    // Decrypt the ciphertext
    if (EVP_DecryptUpdate(ctx_decrypt, decryptedText1, &decryptedText1_len, concatenatedMessage2 + EVP_MAX_IV_LENGTH, concatenatedMessageLength2 - EVP_MAX_IV_LENGTH) != 1) {
    fprintf(stderr, "Error decrypting data\n");
    exit(1);
    }

    // Finalize the decryption
    int final_len;
    if (EVP_DecryptFinal_ex(ctx_decrypt, decryptedText1 + decryptedText1_len, &final_len) != 1) {
    fprintf(stderr, "Error finalizing decryption\n");
    exit(1);
    }
    decryptedText1_len += final_len;
    
    // Print the decrypted plaintext
    printf("Decrypted Text: %.*s\n", decryptedText1_len, decryptedText1);
    EVP_CIPHER_CTX_free(ctx_decrypt);


    EVP_CIPHER_CTX* ctx_decrypt2 = EVP_CIPHER_CTX_new();
    // Initialize the encryption/decryption context
    if (EVP_CipherInit_ex(ctx_decrypt2, cipher, NULL, NULL, NULL, 1) != 1) {
    fprintf(stderr, "Error initializing the cipher context\n");
    EVP_CIPHER_CTX_free(ctx_decrypt2);
    return;
    }

    // Set the session key
    if (EVP_CIPHER_CTX_set_key_length(ctx_decrypt2, decryptedText1_len) != 1) {
    fprintf(stderr, "Error setting the key length\n");
    EVP_CIPHER_CTX_free(ctx_decrypt2);
    return;
    }

    if (EVP_CipherInit_ex(ctx_decrypt2, NULL, NULL, decryptedText1, NULL, -1) != 1) {
    fprintf(stderr, "Error setting the session key\n");
    EVP_CIPHER_CTX_free(ctx_decrypt2);
    return;
    }
    // Extract the IV from the concatenated message 1
    memcpy(iv, concatenatedMessage1, EVP_MAX_IV_LENGTH);

    // Set the IV for the decryption operation
    if (EVP_DecryptInit_ex(ctx_decrypt2, EVP_aes_256_cbc(), NULL, decryptedText1, iv) != 1) {
    fprintf(stderr, "Error setting decryption IV\n");
    exit(1);
    }

    // Decrypt the ciphertext
    if (EVP_DecryptUpdate(ctx_decrypt2, decryptedText2, &decryptedText2_len, concatenatedMessage1 + EVP_MAX_IV_LENGTH, concatenatedMessageLength1 - EVP_MAX_IV_LENGTH) != 1) {
    fprintf(stderr, "Error decrypting data\n");
    exit(1);
    }

    // Finalize the decryption
    if (EVP_DecryptFinal_ex(ctx_decrypt2, decryptedText2 + decryptedText2_len, &final_len) != 1) {
    fprintf(stderr, "Error finalizing decryption\n");
    exit(1);
    }
    decryptedText2_len += final_len;

    // Print the decrypted plaintext
    printf("Decrypted Text: %.*s\n", decryptedText2_len, decryptedText2);

我面临的问题是在解密。它在解密第一消息时卡住,给出“错误解密数据”作为输出。我已经在两端验证了skey和iv。我会很感激你的帮助

2nbm6dog

2nbm6dog1#

正如评论所指出的,你有:

...
    // Extract the IV from the concatenated message 2
    memcpy(iv, concatenatedMessage2, EVP_MAX_IV_LENGTH);
...
    // Extract the IV from the concatenated message 1
    memcpy(iv, concatenatedMessage1, EVP_MAX_IV_LENGTH);
...

当它应该是:

...
    // Extract the IV from the concatenated message 1
    memcpy(iv, concatenatedMessage1, EVP_MAX_IV_LENGTH);
...
    // Extract the IV from the concatenated message 2
    memcpy(iv, concatenatedMessage2, EVP_MAX_IV_LENGTH);
...

例如,您使用concatenatedMessage2 iv来解密concatenatedMessage1,使用concatenatedMessage1 iv来解密concatenatedMessage2。

sdnqo3pr

sdnqo3pr2#

我做了一些调试,得到了这个错误。concatenatedmessagelength1在另一个函数中被更新时,它正在向您发送。(虽然是全球性的)。然而,现在我被卡在下一个错误
if (EVP_DecryptFinal_ex(ctx_decrypt, decryptedText1 + decryptedText1_len, &final_len) != 1) { fprintf(stderr, "Error finalizing decryption\n"); exit(1); }
在调试时,我发现decryptedText1_len是32,这是正确的(我们的会话密钥是32字节),但是,在检查变量decryptedText1时,它有48个字节。

相关问题