Skip to content

Instantly share code, notes, and snippets.

@jiep
Last active October 6, 2021 18:21
Show Gist options
  • Save jiep/cc5659abc5bd578e496efffc1ab6cfa2 to your computer and use it in GitHub Desktop.
Save jiep/cc5659abc5bd578e496efffc1ab6cfa2 to your computer and use it in GitHub Desktop.
Solución al ejercicio de liboqs

Enunciado

Dado el siguiente protocolo de intercambio de clave, que emplea un KEM, definido en [1], se pide:

enunciado

  1. Implementar el protocolo anterior usando un KEM disponible en liboqs.
  2. (Opcional) Compilar el protocolo con una versión de liboqs que incluya sólo el KEM elegido.
  3. (Opcional) Usar la compilación cruzada para compilar el protocolo en Windows.

Referencias

[1] Joppe W. Bos et al. "CRYSTALS - Kyber: A CCA-Secure Module-Lattice-Based KEM". In:EuroS&P. IEEE, 2018,pp. 353–367.

/* Compilar con
gcc -Ibuild/include -Lbuild/lib ejercicio.c -o ejercicio -loqs -lcrypto
*/
#include <stdio.h>
#include <string.h>
#include <oqs/oqs.h>
#define MAX 16
void print_hex(const uint8_t *bytes, size_t length) {
for(size_t i = 0; i < length; i++){
printf("%02x", bytes[i]);
}
printf("\n");
}
void print_hex_short(const uint8_t *bytes, size_t length) {
for(size_t i = 0; i < MAX; i++){
printf("%02x", bytes[i]);
}
printf("...");
for(size_t i = length - MAX; i < length; i++){
printf("%02x", bytes[i]);
}
printf("\n");
}
void concat_keys(const uint8_t *key1, const uint8_t *key2, const uint8_t *key3,
size_t length, uint8_t *out) {
memcpy(out, key1, length);
memcpy(out + length, key2, length);
memcpy(out + 2*length, key3, length);
}
int main(void) {
OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_kyber_1024);
printf("[--] Setting kyber1024...\n");
// Claves estáticas de P1
uint8_t *pk1 = malloc(kem->length_public_key);
uint8_t *sk1 = malloc(kem->length_secret_key);
OQS_KEM_keypair(kem, pk1, sk1);
printf("\n[P1] Generating static keys...\n");
printf("[P1] pk1: ");
print_hex_short(pk1, kem->length_public_key);
printf("[P1] sk1: ");
print_hex_short(sk1, kem->length_secret_key);
// Claves estáticas de P2
uint8_t *pk2 = malloc(kem->length_public_key);
uint8_t *sk2 = malloc(kem->length_secret_key);
OQS_KEM_keypair(kem, pk2, sk2);
printf("\n[P2] Generating static keys...\n");
printf("[P2] pk2: ");
print_hex_short(pk2, kem->length_public_key);
printf("[P2] sk2: ");
print_hex_short(sk2, kem->length_secret_key);
// -----------------------------------------------
uint8_t *pk = malloc(kem->length_public_key);
uint8_t *sk = malloc(kem->length_secret_key);
OQS_KEM_keypair(kem, pk, sk);
printf("\n[P1] Generating pk and sk...\n");
printf("[P1] pk: ");
print_hex_short(pk, kem->length_public_key);
printf("[P1] sk: ");
print_hex_short(sk, kem->length_secret_key);
uint8_t *c2 = malloc(kem->length_ciphertext);
uint8_t *k2 = malloc(kem->length_shared_secret);
OQS_KEM_encaps(kem, c2, k2, pk2);
printf("[P1] Generating c2 and k2...\n");
printf("[P1] c2: ");
print_hex_short(c2, kem->length_ciphertext);
printf("[P1] k2: ");
print_hex(k2, kem->length_shared_secret);
printf("[P1] Sending pk and c2 to P2...\n");
// P1 envía pk y c2 a P2
uint8_t *c = malloc(kem->length_ciphertext);
uint8_t *k = malloc(kem->length_shared_secret);
OQS_KEM_encaps(kem, c, k, pk);
printf("\n[P2] Generating c and k...\n");
printf("[P2] c: ");
print_hex_short(c, kem->length_ciphertext);
printf("[P2] k: ");
print_hex(k, kem->length_shared_secret);
uint8_t *c1 = malloc(kem->length_ciphertext);
uint8_t *k1 = malloc(kem->length_shared_secret);
OQS_KEM_encaps(kem, c1, k1, pk1);
printf("[P2] Generating c1 and k1...\n");
printf("[P2] c1: ");
print_hex_short(c1, kem->length_ciphertext);
printf("[P2] k1: ");
print_hex(k1, kem->length_shared_secret);
uint8_t *k2_prime = malloc(kem->length_shared_secret);
OQS_KEM_decaps(kem, k2_prime, c2, sk2);
printf("[P2] Generating k2_prime...\n");
printf("[P2] k2_prime: ");
print_hex(k2_prime, kem->length_shared_secret);
printf("[P2] Sending c and c1 to P1...\n");
// P2 envía c y c1 a P1
uint8_t *k_prime = malloc(kem->length_shared_secret);
OQS_KEM_decaps(kem, k_prime, c, sk);
printf("\n[P1] Generating k_prime...\n");
printf("[P1] k_prime: ");
print_hex(k_prime, kem->length_shared_secret);
uint8_t *k1_prime = malloc(kem->length_shared_secret);
OQS_KEM_decaps(kem, k1_prime, c1, sk1);
printf("[P1] Generating k1_prime...\n");
printf("[P1] k1_prime: ");
print_hex(k1_prime, kem->length_shared_secret);
// P1 genera clave secreta a partir de k_prime, k1_prime y k2
uint8_t *concat_keys1 = malloc(3*kem->length_shared_secret);
uint8_t *key1 = malloc(kem->length_shared_secret);
concat_keys(k_prime, k1_prime, k2, kem->length_shared_secret, concat_keys1);
OQS_SHA3_sha3_256(key1, concat_keys1, 3*kem->length_shared_secret);
// P2 genera clave secreta a partir de k, k1 y k2_prime
uint8_t *concat_keys2 = malloc(3*kem->length_shared_secret);
uint8_t *key2 = malloc(kem->length_shared_secret);
concat_keys(k, k1, k2_prime, kem->length_shared_secret, concat_keys2);
OQS_SHA3_sha3_256(key2, concat_keys2, 3*kem->length_shared_secret);
printf("\n[P1] key1: ");
print_hex(key1, kem->length_shared_secret);
printf("[P2] key2: ");
print_hex(key2, kem->length_shared_secret);
if(memcmp(key1, key2, kem->length_shared_secret) != 0){
printf("[--] Key exchange error!\n");
return OQS_ERROR;
}
printf("[--] Key exchange successful!\n");
// Escribimos ceros y liberamos memoria
OQS_MEM_secure_free(sk1, kem->length_secret_key);
OQS_MEM_secure_free(sk2, kem->length_secret_key);
OQS_MEM_secure_free(sk, kem->length_secret_key);
OQS_MEM_secure_free(k2, kem->length_shared_secret);
OQS_MEM_secure_free(k, kem->length_shared_secret);
OQS_MEM_secure_free(k1, kem->length_shared_secret);
OQS_MEM_secure_free(k2_prime, kem->length_shared_secret);
OQS_MEM_secure_free(k_prime, kem->length_shared_secret);
OQS_MEM_secure_free(k1_prime, kem->length_shared_secret);
OQS_MEM_secure_free(concat_keys1, 3*kem->length_shared_secret);
OQS_MEM_secure_free(key1, kem->length_shared_secret);
OQS_MEM_secure_free(concat_keys2, 3*kem->length_shared_secret);
OQS_MEM_secure_free(key2, kem->length_shared_secret);
// Liberamos memoria
OQS_MEM_insecure_free(pk1);
OQS_MEM_insecure_free(pk2);
OQS_MEM_insecure_free(pk);
OQS_MEM_insecure_free(c2);
OQS_MEM_insecure_free(c);
OQS_MEM_insecure_free(c1);
OQS_KEM_free(kem);
return OQS_SUCCESS;
}
// [--] Setting kyber1024...
//
// [P1] Generating static keys...
// [P1] pk1: 138a87d4e44ceb295aee077765472ac0...579480901c8c89b118bc4228d0f67648
// [P1] sk1: 3b562b08f7906f0491c97130e1cbaf83...93ab6869cb49209aecb6702838166bad
//
// [P2] Generating static keys...
// [P2] pk2: 284492a2f210dc5a9d24a01a38009a40...d1b60b525d74752d50b9f32d3c7500e3
// [P2] sk2: 13ccb67671ceb4e785d8b4994b970d0e...05f9025dd7e22997a993a01d2a84bc15
//
// [P1] Generating pk and sk...
// [P1] pk: 2e5a0ba61657f022a9fcc1022a9251ac...28e4605bc0059ae90bd7919b9761d7f6
// [P1] sk: 7b8a27334b4f942288f695611d0cb8a0...da375693c1e43f8d6a0bae8443ff4663
// [P1] Generating c2 and k2...
// [P1] c2: 11a7e16af581cd3c7b01a32a6c9b3363...fef17291404c124f9c2efdf0a53b3014
// [P1] k2: 0a8f48e3ee9220a1629a91f7dcafce34068489fa886048628c604ff7effab539
// [P1] Sending pk and c2 to P2...
//
// [P2] Generating c and k...
// [P2] c: 4377cfeb21ba39de87b4405cefe15e43...f19779e3f73f60240bb6c7a7d857a43e
// [P2] k: 784201510c9cee69430844c4faa1d1d3320af2a6c08add723d5993ab6d35656d
// [P2] Generating c1 and k1...
// [P2] c1: e990da93a8e98f7b91eaf33b9c80043e...e1b6f7913e6c7c9a7041188a686e098b
// [P2] k1: 224e0f9493c3ec3b11434eea84dabfb191a8ce2c716e95ed708e3b4651ea09c0
// [P2] Generating k2_prime...
// [P2] k2_prime: 0a8f48e3ee9220a1629a91f7dcafce34068489fa886048628c604ff7effab539
// [P2] Sending c and c1 to P1...
//
// [P1] Generating k_prime...
// [P1] k_prime: 784201510c9cee69430844c4faa1d1d3320af2a6c08add723d5993ab6d35656d
// [P1] Generating k1_prime...
// [P1] k1_prime: 224e0f9493c3ec3b11434eea84dabfb191a8ce2c716e95ed708e3b4651ea09c0
//
// [P1] key1: 09857e5b30073ae455264e9f4c21b177134fa3eb639bc1f38a2ef4dd6a1d6a89
// [P2] key2: 09857e5b30073ae455264e9f4c21b177134fa3eb639bc1f38a2ef4dd6a1d6a89
// [--] Key exchange successful!
  1. Personalizar librería de liboqs con sólo kyber_1024 y compilar.

    cmake -GNinja -DOQS_MINIMAL_BUILD="OQS_ENABLE_KEM_kyber_1024" ..
    ninja
  2. Compilar ejercicio.c con gcc.

    gcc -Ibuild/include -Lbuild/lib ejercicio.c -o ejercicio-kyber1024 -loqs -lcrypto

    Esto permite reducir el tamaño del binario de forma significativa.

    ls -lah ejercicio*
    -rwxrwxr-x 1 vm vm 7,1M ago 24 12:32 ejercicio             <- Ejercicio con la librería completa (7.1 MB)
    -rwxrwxr-x 1 vm vm  82K ago 24 12:23 ejercicio-kyber1024   <- Ejercicio con la librería personalizada (82 KB)
  1. Compilación cruzada de liboqs usando el toolchain de Windows y añadiendo sólo kyber_1024.

    cmake -GNinja -DCMAKE_TOOLCHAIN_FILE=../.CMake/toolchain_windows-amd64.cmake -DOQS_USE_OPENSSL=OFF -DOQS_MINIMAL_BUILD="OQS_ENABLE_KEM_kyber_1024" ..
    ninja
  2. Compilación cruzada de ejercicio.c con x86_64-w64-mingw32-gcc.

    Si no se dispone de x86_64-w64-mingw32-gcc, hay que instalarlo junto con wine.

    sudo apt install wine gcc-mingw-w64
    x86_64-w64-mingw32-gcc -Ibuild/include -Lbuild/lib ejercicio.c -o ejercicio-kyber1024 -loqs

    De nuevo, se reduce el tamaño del binario de forma significativa.

    -rwxrwxr-x 1 vm vm 497K ago 24 12:46 ../ejercicio-kyber1024.exe   <- Ejercicio con la librería personalizada (497 KB)
    -rwxrwxr-x 1 vm vm 6,5M ago 24 12:44 ../ejercicio.exe             <- Ejercicio con la librería completa (6.5 MB)
    
  3. Ejecutar el binario en Windows.

    ejercicio-win ejercicio1024-win

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment