Libgcrypt paso a paso

Iniciado por AlbertoBSD, 29 Marzo 2016, 17:44 PM

0 Miembros y 1 Visitante están viendo este tema.

AlbertoBSD

Muy buen dia, este sera un pequeño taller para entender un poco mas sobre criptografía paso a paso usando lenguaje C y la libreria Libgcrypt.

Nota para el moderador Lo pongo en Cryptografia  y no en C/C++ por ver el detalle de los conceptos criptograficos.

Asi podremos observar paso paso el contenido de la memoria  :silbar: y como esta cambia.

Antes de programar con libgcrypt yo solo sabia los conceptos básicos de Criptografia pero en general desconocía a grandes rasgos la forma interna de trabajar de programas como GnuPG entre otros.

Los códigos que pondré aqui estan a su disposición para practicar con la librería y los conceptos criptográficos y estan disponibles en github

https://github.com/albertobsd/libgcrypt-examples

Creacion de par de Claves RSA

Bien el primer tema sera crear una clave RSA de cierta cantidad de bits y ver como esta esta clave en la memoria.

El primer ejemplo esta bajo el nombre RSA_2048.c aunque en realidad el ejmplo crea un par claves de 4096 bits
https://github.com/albertobsd/libgcrypt-examples/blob/master/RSA_2048.c

El programa genera un nuevo par de claves RSA de 4096 bits y los guarda en formato S-Expresion en un archivo llamado clave.txt por si tienen ese archivo ya existente con datos seria sobreescrito.

El codigo y luego explicare las partes interesantes por serparado.

/*
Twitter @albertobsd
cc -o RSA_2048 RSA_2048.c `libgcrypt-config --cflags --libs`
Prueba de generacion de claves RSA 2048 y 4096 bits.
*/

#include<stdio.h>
#include<gcrypt.h>

int main() {
FILE *f = NULL;
gcry_sexp_t rsa_parms = NULL;
gcry_sexp_t rsa_keypair = NULL;
gcry_error_t err = 0;
char *buffer;
size_t length = 4;
size_t offset = 0;
err = gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
err |= gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
err |= gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
err |= gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if(err) {
fprintf(stderr,"gcrypt: failed initialization");
exit(0);
}
err = gcry_sexp_build(&rsa_parms, NULL, "(genkey (rsa (nbits 4:4096)(rsa-use-e 1:1)))");
if (err) {
fprintf(stderr,"gcrypt: failed initialization");
exit(0);
}
length = gcry_sexp_sprint(rsa_parms,GCRYSEXP_FMT_CANON,NULL,0);
buffer = calloc(length,sizeof( char));
offset = gcry_sexp_sprint(rsa_parms,GCRYSEXP_FMT_CANON,buffer,length);
printf("Buffer size %i\n",length);
printf("Buffer offset %i\n",offset);
printf("%s\n",buffer);
memset(buffer,0,length);
err = gcry_pk_genkey(&rsa_keypair, rsa_parms);
if (err) {
fprintf(stderr,"gcrypt: failed initialization");
exit(0);
}
length = gcry_sexp_sprint(rsa_keypair,GCRYSEXP_FMT_CANON,NULL,0);
buffer = realloc(buffer,length*sizeof(char));
offset = gcry_sexp_sprint(rsa_keypair,GCRYSEXP_FMT_CANON,buffer,length);

printf("Buffer size %i\n",length);
printf("Buffer offset %i\n",offset);
printf("%s\n",buffer);
f = fopen("clave.txt","w");
if(f) {
fwrite(buffer,sizeof(char),offset,f);
fclose(f);
}
memset(buffer,0,length);
free(buffer);
gcry_sexp_release(rsa_keypair);
gcry_sexp_release(rsa_parms);
}


Si bien no entrare en algunos de los detalles de libgcrypt eso queda a tarea del lector.

gcry_sexp_build(&rsa_parms, NULL, "(genkey (rsa (nbits 4:4096)(rsa-use-e 1:1)))");

La funcion anterior solo genera una cadena en formato S-expresion con instrucciones para posteriormente generar un par de claves:

"(genkey (rsa (nbits 4:4096)(rsa-use-e 1:1)))"

Si queremos crear un par de clave de 1024 bits solo cambiaremos el 4096 por 1024 y asi susesivamente.

Si ejecutamos el programa veremos un salida similar a la siguiente:


Buffer size 49
Buffer offset 48
(6:genkey(3:rsa(5:nbits4:4096)(9:rsa-use-e1:1)))
Buffer size 2441
Buffer offset 2440
(8:key-data(10:public-key(3:rsa(1:n513:


Veamos informamos de cuanta memoria se uso para el buffer y acontinuacion vemos una cadena similar a la que le pasamos al programa:

Citar
(6:genkey(3:rsa(5:nbits4:4096)(9:rsa-use-e1:1)))

por ejemplo:
6:genkey <-6 bytes
3:rsa <- 3bytes
5:nbits <- 5 bytes
4:4096 <- 4 bytes
etc...

Generamos la clave:

gcry_pk_genkey(&rsa_keypair, rsa_parms);

La guardamos en un buffer con memoria previamente reservada:

offset = gcry_sexp_sprint(rsa_keypair,GCRYSEXP_FMT_CANON,buffer,length);


La imprimimos en pantalla

printf("%s\n",buffer);

pero bien la salida al parecer esta trunca:

Citar
Buffer size 2441
Buffer offset 2440
(8:key-data(10:public-key(3:rsa(1:n513:

Para esto guardamos el buffer completo en un archivo:

fwrite(buffer,sizeof(char),offset,f);

Y si revisan el contenido del archivo veran  :o :o :o el formato completo de las claves en el formato descrito en la documentacion de libgcrypt

Citar

(private-key
  (rsa
    (n n-mpi)
    (e e-mpi)
    (d d-mpi)
    (p p-mpi)
    (q q-mpi)
    (u u-mpi)))

(public-key
  (rsa
    (n n-mpi)
    (e e-mpi)))

+ Otros  datos

https://gnupg.org/documentation/manuals/gcrypt/RSA-key-parameters.html#RSA-key-parameters
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW