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 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.
Si bien no entrare en algunos de los detalles de libgcrypt eso queda a tarea del lector.
La funcion anterior solo genera una cadena en formato S-expresion con instrucciones para posteriormente generar un par de claves:
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:
Veamos informamos de cuanta memoria se uso para el buffer y acontinuacion vemos una cadena similar a la que le pasamos al programa:
por ejemplo:
6:genkey <-6 bytes
3:rsa <- 3bytes
5:nbits <- 5 bytes
4:4096 <- 4 bytes
etc...
Generamos la clave:
La guardamos en un buffer con memoria previamente reservada:
La imprimimos en pantalla
pero bien la salida al parecer esta trunca:
Para esto guardamos el buffer completo en un archivo:
Y si revisan el contenido del archivo veran el formato completo de las claves en el formato descrito en la documentacion de libgcrypt
https://gnupg.org/documentation/manuals/gcrypt/RSA-key-parameters.html#RSA-key-parameters
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 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.
Código (c) [Seleccionar]
/*
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.
Código (c) [Seleccionar]
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:
Código (c) [Seleccionar]
"(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:
Código [Seleccionar]
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:
Código (c) [Seleccionar]
gcry_pk_genkey(&rsa_keypair, rsa_parms);
La guardamos en un buffer con memoria previamente reservada:
Código (c) [Seleccionar]
offset = gcry_sexp_sprint(rsa_keypair,GCRYSEXP_FMT_CANON,buffer,length);
La imprimimos en pantalla
Código (c) [Seleccionar]
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:
Código [Seleccionar]
fwrite(buffer,sizeof(char),offset,f);
Y si revisan el contenido del archivo veran 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