Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ac:laboratoare:11 [2025/11/05 23:13]
marios.choudary
ac:laboratoare:11 [2025/11/06 10:36] (current)
marios.choudary
Line 31: Line 31:
 We will use the ''​%%pyasn1%%''​ library to parse the ''​%%.pem%%''​ file's binarized DER format more conveniently. We will use the ''​%%pyasn1%%''​ library to parse the ''​%%.pem%%''​ file's binarized DER format more conveniently.
  
-==== 1. Implement DH + RSA signature ====+==== 1. Implement DH + RSA signature ​(3p) ==== 
  
 Starting from {{:​ac:​laboratoare:​lab_tofu.zip |these files}}, solve the TODO 1 series in ''​%%dhe_server.py%%''​ and ''​%%dhe_client.py%%''​. ​ Starting from {{:​ac:​laboratoare:​lab_tofu.zip |these files}}, solve the TODO 1 series in ''​%%dhe_server.py%%''​ and ''​%%dhe_client.py%%''​. ​
Line 60: Line 60:
 </​code>​ </​code>​
  
-==== 2. Do you like TOFU? ====+==== 2. Do you like TOFU? (3p) ==== 
  
 Now start solving the TODO 2 series by implementing Trust On First Use in ''​%%dhe_client.py%%''​. Do it as follows: Now start solving the TODO 2 series by implementing Trust On First Use in ''​%%dhe_client.py%%''​. Do it as follows:
Line 77: Line 77:
  
 This is very similar to what SSH does when connecting to a server using a pair of public/​private keys and is known as Trust On First Use (TOFU) authentication. This is very similar to what SSH does when connecting to a server using a pair of public/​private keys and is known as Trust On First Use (TOFU) authentication.
 +
 +==== 3. PQC ready? (4p) ====
 +
 +Now let's update the key exchange to use post-quantum cryptography.
 +
 +For this you can either modify the work you did above to use a post-quantum key exchange method such as ML-KEM in Python.
 +To do this in Python you can use a library such as [[https://​pypi.org/​project/​mlkem/​|ml-kem]].
 +You can install this as follows:
 +<​code>​
 +pip install ml-kem
 +</​code>​
 +
 +Below is an example of how to use this library in a simple client-server scenario. Note: this example is provided by Gemini AI, so use it with caution and double-check it:
 +<​code>​
 +# Install the library first: pip install ml-kem
 +
 +from mlkem.ml_kem import ML_KEM
 +from mlkem.parameter_set import ML_KEM_768 # Recommended security level
 +import secrets
 +
 +# --- Server (Alice) Side ---
 +
 +def server_keygen():​
 +    """​Alice generates her ML-KEM key pair."""​
 +    # Initialize ML-KEM with the desired security level
 +    ml_kem = ML_KEM(parameters=ML_KEM_768,​ randomness=secrets.token_bytes)
 +    ​
 +    # Generate the encapsulation key (ek, public) and decapsulation key (dk, private)
 +    ek, dk = ml_kem.key_gen()
 +    ​
 +    print("​Alice:​ Generated Public Key (ek) and Private Key (dk)."​)
 +    return ek, dk, ml_kem
 +
 +def server_decapsulate(dk,​ c, ml_kem):
 +    """​Alice decapsulates the ciphertext to get the shared secret."""​
 +    try:
 +        K_prime = ml_kem.decaps(dk,​ c)
 +        print("​Alice:​ Successfully decapsulated the Shared Secret (K'​)."​)
 +        return K_prime
 +    except ValueError as e:
 +        print(f"​Alice:​ Decapsulation failed! {e}")
 +        return None
 +
 +# --- Client (Bob) Side ---
 +
 +def client_encapsulate(ek):​
 +    """​Bob encapsulates a shared secret using Alice'​s public key."""​
 +    ml_kem = ML_KEM(parameters=ML_KEM_768,​ randomness=secrets.token_bytes)
 +    ​
 +    # Encapsulate to get the shared secret (K) and the ciphertext (c)
 +    K, c = ml_kem.encaps(ek)
 +    ​
 +    print("​Bob:​ Encapsulated a Shared Secret (K) and created Ciphertext (c).")
 +    return K, c
 +
 +# --- Communication Flow Simulation ---
 +
 +# 1. Server (Alice) Key Generation
 +ek_server, dk_server, ml_kem_instance = server_keygen()
 +
 +# 2. Public Key Transmission (ek_server is sent to the client)
 +print("​\n--- Network Transmission:​ ek sent to Bob ---")
 +
 +# 3. Client (Bob) Encapsulation
 +K_client, c_client = client_encapsulate(ek_server)
 +
 +# 4. Ciphertext Transmission (c_client is sent back to the server)
 +print("​\n--- Network Transmission:​ c sent to Alice ---")
 +
 +# 5. Server (Alice) Decapsulation
 +K_server = server_decapsulate(dk_server,​ c_client, ml_kem_instance)
 +
 +# 6. Verification
 +print("​\n--- Verification ---")
 +if K_client is not None and K_server is not None:
 +    if K_client == K_server:
 +        print("​Success! Alice'​s and Bob's shared secrets match."​)
 +        # The shared secret can now be used as an AES key, e.g., K_client
 +        # The shared secret is bytes:
 +        # print(f"​Shared Secret: {K_client.hex()}"​)
 +    else:
 +        print("​Failure! Shared secrets do not match."​)
 +else:
 +    print("​Failure in key exchange process."​)
 +</​code>​
 +
 +
 +Otherwise, you can start from the Diffie-Hellman key exchange lab we did in OpenSSL/C. You may start from {{:​ac:​laboratoare:​lab_dhe_solved.zip|this}} code, that provides a working solution for the Diffie-Hellman lab in OpenSSL.
 +
 +If you go for the C implementation in OpenSSL, one option to include post-quantum encryption is using [[https://​github.com/​open-quantum-safe/​liboqs |liboqs]]. To install it on Ubuntu, use the command below:
 +
 +<​code>​
 +sudo apt install astyle cmake gcc ninja-build libssl-dev python3-pytest python3-pytest-xdist unzip xsltproc doxygen graphviz python3-yaml valgrind
 +</​code>​
 +
 +If using this library, you may use [[https://​github.com/​open-quantum-safe/​liboqs/​blob/​main/​tests/​example_kem.c |this example]] to implement your own version of key exchange and test it in the scenarios above (key exchange and key exchange + TOFU). You may use any resources or available KEMs.
 +
 +Alternatively,​ you can also use OpenSSL directly (starting with version 3.5). You can find some documentation for ML-KEM [[https://​docs.openssl.org/​master/​man7/​EVP_KEM-ML-KEM/​ |here]] and [[https://​docs.openssl.org/​3.5/​man7/​EVP_PKEY-ML-KEM/​ |here]].
 +
 +Below is an example code obtained through Gemini AI (not fully tested, but perhaps a good starting point):
 +<​code>​
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +#include <​string.h>​
 +#include <​openssl/​evp.h>​
 +#include <​openssl/​err.h>​
 +#include <​openssl/​provider.h>​
 +
 +// --- HARDCODED ML-KEM-768 Public Key (Replace with a real key) ---
 +// A real ML-KEM-768 public key is 608 bytes long.
 +// This is a placeholder for demonstration.
 +unsigned char server_public_key_bytes[] = {
 +    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
 +    // ... 592 more bytes of a real ML-KEM-768 public key would go here ...
 +    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
 +    // Note: This placeholder is NOT a valid ML-KEM-768 key and will likely fail.
 +    // Replace with a 608-byte key generated via '​openssl genpkey'​ for real use.
 +};
 +size_t public_key_len = 608; // ML-KEM-768 Public Key size
 +
 +// Error handling macro
 +#define HANDLE_ERROR(msg) \
 +    { \
 +        fprintf(stderr,​ "%s failed.\n",​ msg); \
 +        ERR_print_errors_fp(stderr);​ \
 +        goto cleanup; \
 +    }
 +
 +int main(void) {
 +    EVP_PKEY_CTX *kctx = NULL;
 +    EVP_PKEY *peer_pub_key = NULL;
 +    OSSL_PARAM params[2];
 +    unsigned char *shared_secret = NULL;
 +    unsigned char *ciphertext = NULL;
 +    size_t shared_secret_len = 0;
 +    size_t ciphertext_len = 0;
 +    int ret = 0;
 +
 +    printf("​Starting ML-KEM Client Key Encapsulation (ML-KEM-768).\n"​);​
 +
 +    // 1. Load the OpenSSL default provider (ML-KEM is in the default provider since 3.5)
 +    if (!OSSL_PROVIDER_load(NULL,​ "​default"​)) {
 +        HANDLE_ERROR("​Failed to load default provider"​);​
 +    }
 +
 +    // 2. Import the raw public key bytes into an EVP_PKEY structure
 +    printf("​2. Importing ML-KEM-768 Public Key...\n"​);​
 +
 +    // a. Create parameter array to describe the key components
 +    params[0] = OSSL_PARAM_construct_octet_string("​pub",​ server_public_key_bytes,​ public_key_len);​
 +    params[1] = OSSL_PARAM_construct_end();​
 +
 +    // b. Import the key. ML-KEM-768 is named "​ML-KEM-768"​
 +    peer_pub_key = EVP_PKEY_new_from_params(NULL,​ params, "​ML-KEM-768"​);​
 +    if (!peer_pub_key) {
 +        // NOTE: This will fail if the hardcoded bytes are not a valid key.
 +        HANDLE_ERROR("​EVP_PKEY_new_from_params failed (Public Key Import)"​);​
 +    }
 +
 +    // 3. Initialize the Key Encapsulation Context
 +    kctx = EVP_PKEY_CTX_new_from_pkey(NULL,​ peer_pub_key,​ NULL);
 +    if (!kctx) {
 +        HANDLE_ERROR("​EVP_PKEY_CTX_new_from_pkey failed"​);​
 +    }
 +
 +    if (EVP_PKEY_encapsulate_init(kctx) <= 0) {
 +        HANDLE_ERROR("​EVP_PKEY_encapsulate_init failed"​);​
 +    }
 +
 +    // 4. Determine buffer sizes
 +    printf("​4. Determining buffer sizes...\n"​);​
 +    if (EVP_PKEY_encapsulate(kctx,​ NULL, &​shared_secret_len,​ NULL, &​ciphertext_len) <= 0) {
 +        HANDLE_ERROR("​EVP_PKEY_encapsulate (size determination) failed"​);​
 +    }
 +    ​
 +    printf(" ​  - Shared Secret Length: %zu bytes\n",​ shared_secret_len);​
 +    printf(" ​  - Ciphertext Length: %zu bytes\n",​ ciphertext_len);​
 +
 +    // 5. Allocate buffers
 +    shared_secret = OPENSSL_malloc(shared_secret_len);​
 +    ciphertext = OPENSSL_malloc(ciphertext_len);​
 +
 +    if (!shared_secret || !ciphertext) {
 +        HANDLE_ERROR("​Memory allocation failed"​);​
 +    }
 +
 +    // 6. Perform the Encapsulation (Client'​s Key Exchange Step)
 +    printf("​6. Performing Key Encapsulation...\n"​);​
 +    if (EVP_PKEY_encapsulate(kctx,​ shared_secret,​ &​shared_secret_len,​ ciphertext, &​ciphertext_len) <= 0) {
 +        HANDLE_ERROR("​EVP_PKEY_encapsulate failed"​);​
 +    }
 +
 +    printf("​✅ Encapsulation successful!\n"​);​
 +    printf(" ​  The client has generated a **Shared Secret** and the **Ciphertext**.\n"​);​
 +    ​
 +    printf(" ​  - Shared Secret (First 16 bytes): ");
 +    for (size_t i = 0; i < (shared_secret_len > 16 ? 16 : shared_secret_len);​ i++) {
 +        printf("​%02x",​ shared_secret[i]);​
 +    }
 +    printf("​...\n"​);​
 +
 +    printf(" ​  - Ciphertext (First 16 bytes, to be sent to Server): ");
 +    for (size_t i = 0; i < (ciphertext_len > 16 ? 16 : ciphertext_len);​ i++) {
 +        printf("​%02x",​ ciphertext[i]);​
 +    }
 +    printf("​...\n"​);​
 +
 +    ret = 0; // Success
 +    ​
 +cleanup:
 +    // Free all allocated resources
 +    EVP_PKEY_CTX_free(kctx);​
 +    EVP_PKEY_free(peer_pub_key);​
 +    OPENSSL_free(shared_secret);​
 +    OPENSSL_free(ciphertext);​
 +    OSSL_PROVIDER_unload(OSSL_PROVIDER_load(NULL,​ "​default"​));​ // Unload provider
 +
 +    if (ret != 0) {
 +        return EXIT_FAILURE;​
 +    }
 +    return EXIT_SUCCESS;​
 +}
 +</​code>​
 +
 +Some instructions to use this code (also from Gemini AI):
 +  * Save the code as mlkem_client.c.
 +  * Generate a real ML-KEM-768 public key (if you didn't do this in the previous step) by running the following commands:
 +<​code>​
 +openssl genpkey -algorithm ML-KEM-768 -out server_private.pem
 +openssl pkey -in server_private.pem -pubout -out server_public.pem
 +</​code>​
 +  * Extract the raw public key bytes to replace the placeholder in the C code. A common way to get the raw bytes is to convert the PEM file to a DER format and extract the key component. For ML-KEM, the raw key is often found within the ASN.1 structure.
 +<​note>​
 +See the DH lab for information about this process. But see also below more details for this process, as provided by Gemini AI.
 +</​note>​
 +  * Compile the code (adjusting paths to your OpenSSL 3.5 installation),​ using a command like this (check again also the DH lab for more details):
 +<​code>​
 +gcc -o mlkem_client mlkem_client.c -I/​path/​to/​openssl/​include -L/​path/​to/​openssl/​lib -lssl -lcrypto
 +</​code>​
 +
 +The following GeminiAI-generated scripts (might have some bugs, please double-check,​ they are only given as reference/​helper tools) generate an ML-KEM-768 key pair and, importantly,​ forces OpenSSL to save the private key in the FIPS 203 '​dk'​ format (the one the C code expects for decapsulation) rather than the default '​seed'​ format, which is not what the raw C code imports:
 +<​code>​
 +#!/bin/bash
 +KEY_ALG="​ML-KEM-768"​
 +PRIV_FILE="​server_private_dk.pem"​
 +PUB_FILE="​server_public_ek.pem"​
 +RAW_PRIV_FILE="​server_private_raw.bin"​
 +RAW_PUB_FILE="​server_public_raw.bin"​
 +
 +echo "--- 1. Generating $KEY_ALG Key Pair (forcing dk-only private key) ---"
 +
 +# Generate the private key, using '​-provparam ml-kem.retain_seed=no'​
 +# to ensure it saves the full FIPS 203 '​dk'​ decapsulation key,
 +# NOT just the seed.
 +openssl genpkey -algorithm "​$KEY_ALG"​ \
 +    -provparam ml-kem.retain_seed=no \
 +    -out "​$PRIV_FILE"​
 +
 +# Extract the public key from the private key file
 +openssl pkey -in "​$PRIV_FILE"​ -pubout -out "​$PUB_FILE"​
 +
 +echo "Keys generated: $PRIV_FILE and $PUB_FILE"​
 +echo "​----------------------------------------------------------------"​
 +</​code>​
 +
 +The ML-KEM public key is in the SubjectPublicKeyInfo structure in the PEM file. We use openssl pkey to output the key in DER format and then remove the ASN.1 header/​wrapper to get the raw bytes:
 +<​code>​
 +echo "--- 2. Extracting RAW Public Key (608 bytes) ---"
 +
 +# The ML-KEM public key is 608 bytes long.
 +# The '​pubout'​ option converts to DER, and '​tail'​ removes the ASN.1 wrapper.
 +# NOTE: The ASN.1 wrapper size may vary by OpenSSL version/​config. We must
 +# determine the exact offset to trim off the SubjectPublicKeyInfo header.
 +# For standard ML-KEM-768 PKCS#8 output, the header is typically 24 bytes.
 +HEADER_BYTES=24 # Common offset for ML-KEM-768 PKCS#8 SubjectPublicKeyInfo header
 +
 +openssl pkey -in "​$PUB_FILE"​ -pubin -outform DER -out "​$RAW_PUB_FILE"​
 +# Trim the ASN.1 header to get the raw 608-byte key
 +# (Skip first $HEADER_BYTES,​ save the next 608 bytes)
 +dd if="​$RAW_PUB_FILE"​ of="​client_public_key_raw_final.bin"​ bs=1 skip=$HEADER_BYTES count=608 status=none
 +
 +echo "Raw public key saved to client_public_key_raw_final.bin"​
 +# Print the hex array for C code
 +echo "​Public Key Hex Array:"​
 +xxd -p "​client_public_key_raw_final.bin"​ | tr -d '​\n'​ | sed '​s/​../&,​ 0x/g' | sed 's/^, 0x/​0x/'​ | sed 's/, $//'
 +echo
 +echo "​----------------------------------------------------------------"​
 +</​code>​
 +
 +Similarly, the private key (the FIPS 203 '​dk'​ component) is inside the PKCS#8 private key structure. We again convert to DER and trim the ASN.1 wrappers:
 +<​code>​
 +echo "--- 3. Extracting RAW Private Key (1184 bytes) ---"
 +
 +# The ML-KEM-768 private key (dk) is 1184 bytes long.
 +# We convert to DER and again skip the ASN.1 header bytes.
 +# For PKCS#8 '​dk'​ private key, the header is typically 50 bytes.
 +HEADER_BYTES=50 # Common offset for ML-KEM-768 PKCS#8 PrivateKeyInfo header
 +
 +openssl pkey -in "​$PRIV_FILE"​ -outform DER -out "​$RAW_PRIV_FILE"​
 +# Trim the ASN.1 header to get the raw 1184-byte key
 +# (Skip first $HEADER_BYTES,​ save the next 1184 bytes)
 +dd if="​$RAW_PRIV_FILE"​ of="​server_private_key_raw_final.bin"​ bs=1 skip=$HEADER_BYTES count=1184 status=none
 +
 +echo "Raw private key saved to server_private_key_raw_final.bin"​
 +# Print the hex array for C code
 +echo "​Private Key Hex Array:"​
 +xxd -p "​server_private_key_raw_final.bin"​ | tr -d '​\n'​ | sed '​s/​../&,​ 0x/g' | sed 's/^, 0x/​0x/'​ | sed 's/, $//'
 +echo
 +echo "​----------------------------------------------------------------"​
 +</​code>​
 +
 +You can now use the hex output from these scripts to reliably replace the placeholder arrays in your C client and server code.
 +See also [[https://​www.youtube.com/​watch?​v=FzLzH5W-mi8|this]] video about Post-Quantum Cryptography support in OpenSSL.
 +
 +
 +Below is also an example code from Gemini AI as starting point for the server, to pair with the code above for the client.
 +Note that these examples use hardcoded values for keys and do not imply any communication. Therefore, make sure you use them for a proper key exchange that uses communication between parties to exchange the public keys and ciphertexts,​ in a similar manner to what you did for the DH lab.
 +
 +<​code>​
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +#include <​string.h>​
 +#include <​openssl/​evp.h>​
 +#include <​openssl/​err.h>​
 +#include <​openssl/​provider.h>​
 +
 +// --- HARDCODED ML-KEM-768 Private Key (Replace with a real key) ---
 +// A real ML-KEM-768 private key is 1184 bytes long.
 +unsigned char server_private_key_bytes[] = {
 +    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
 +    // ... 1168 more bytes of a real ML-KEM-768 private key would go here ...
 +    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
 +};
 +size_t private_key_len = 1184; // ML-KEM-768 Private Key size
 +
 +// --- HARDCODED Ciphertext (Generated by the Client - Replace with real data) ---
 +// A real ML-KEM-768 ciphertext is 1088 bytes long.
 +unsigned char client_ciphertext_bytes[] = {
 +    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
 +    // ... 1072 more bytes of a real ML-KEM-768 ciphertext would go here ...
 +    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
 +};
 +size_t ciphertext_len = 1088; // ML-KEM-768 Ciphertext size
 +
 +// --- Hardcoded Shared Secret Size (32 bytes for ML-KEM-768) ---
 +size_t shared_secret_len = 32;
 +
 +// Error handling macro
 +#define HANDLE_ERROR(msg) \
 +    { \
 +        fprintf(stderr,​ "%s failed.\n",​ msg); \
 +        ERR_print_errors_fp(stderr);​ \
 +        goto cleanup; \
 +    }
 +
 +int main(void) {
 +    EVP_PKEY_CTX *kctx = NULL;
 +    EVP_PKEY *server_priv_key = NULL;
 +    OSSL_PARAM params[2];
 +    unsigned char *recovered_secret = NULL;
 +    int ret = 0;
 +
 +    printf("​Starting ML-KEM Server Key Decapsulation (ML-KEM-768).\n"​);​
 +
 +    // 1. Load the OpenSSL default provider
 +    if (!OSSL_PROVIDER_load(NULL,​ "​default"​)) {
 +        HANDLE_ERROR("​Failed to load default provider"​);​
 +    }
 +
 +    // 2. Import the raw private key bytes into an EVP_PKEY structure
 +    printf("​2. Importing ML-KEM-768 Private Key...\n"​);​
 +
 +    // a. Create parameter array to describe the key components
 +    // The ML-KEM private key is referred to as "​priv"​ (or '​dk'​ in FIPS 203 terms)
 +    params[0] = OSSL_PARAM_construct_octet_string("​priv",​ server_private_key_bytes,​ private_key_len);​
 +    params[1] = OSSL_PARAM_construct_end();​
 +
 +    // b. Import the key.
 +    server_priv_key = EVP_PKEY_new_from_params(NULL,​ params, "​ML-KEM-768"​);​
 +    if (!server_priv_key) {
 +        HANDLE_ERROR("​EVP_PKEY_new_from_params failed (Private Key Import)"​);​
 +    }
 +
 +    // 3. Initialize the Key Decapsulation Context
 +    kctx = EVP_PKEY_CTX_new_from_pkey(NULL,​ server_priv_key,​ NULL);
 +    if (!kctx) {
 +        HANDLE_ERROR("​EVP_PKEY_CTX_new_from_pkey failed"​);​
 +    }
 +
 +    if (EVP_PKEY_decapsulate_init(kctx) <= 0) {
 +        HANDLE_ERROR("​EVP_PKEY_decapsulate_init failed"​);​
 +    }
 +
 +    // 4. Allocate buffer for the shared secret
 +    recovered_secret = OPENSSL_malloc(shared_secret_len);​
 +    if (!recovered_secret) {
 +        HANDLE_ERROR("​Memory allocation failed"​);​
 +    }
 +
 +    // 5. Perform the Decapsulation (Server'​s Key Exchange Step)
 +    printf("​5. Performing Key Decapsulation...\n"​);​
 +
 +    // The ciphertext is passed as the input buffer (client_ciphertext_bytes).
 +    // The recovered shared secret is written to the output buffer (recovered_secret).
 +    if (EVP_PKEY_decapsulate(kctx,​ recovered_secret,​ &​shared_secret_len,​ client_ciphertext_bytes,​ ciphertext_len) <= 0) {
 +        HANDLE_ERROR("​EVP_PKEY_decapsulate failed"​);​
 +    }
 +
 +    printf("​✅ Decapsulation successful!\n"​);​
 +    printf(" ​  The server has recovered the **Shared Secret**.\n"​);​
 +    ​
 +    printf(" ​  - Recovered Shared Secret (First 16 bytes): ");
 +    for (size_t i = 0; i < (shared_secret_len > 16 ? 16 : shared_secret_len);​ i++) {
 +        printf("​%02x",​ recovered_secret[i]);​
 +    }
 +    printf("​...\n"​);​
 +
 +    printf("​\n**NOTE:​ For a successful key exchange, the hash of this secret must match the hash of the client'​s secret.**\n"​);​
 +
 +    ret = 0; // Success
 +    ​
 +cleanup:
 +    // Free all allocated resources
 +    EVP_PKEY_CTX_free(kctx);​
 +    EVP_PKEY_free(server_priv_key);​
 +    OPENSSL_free(recovered_secret);​
 +    OSSL_PROVIDER_unload(OSSL_PROVIDER_load(NULL,​ "​default"​));​ // Unload provider
 +
 +    if (ret != 0) {
 +        return EXIT_FAILURE;​
 +    }
 +    return EXIT_SUCCESS;​
 +}
 +</​code>​
 +
  
ac/laboratoare/11.1762377195.txt.gz · Last modified: 2025/11/05 23:13 by marios.choudary
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0