Cryptographie : Signature numérique et Chiffrement


OpenSSL

OpenSSL est une implémentation libre des algorithmes de chiffrement SSL basée sur un ensemble composé d'un outil en ligne de commande et de deux bibliothèques sous formes de librairies indépendantes : Les bibliothèques, écrites en langage C, implémentent les fonctions basiques de cryptographie et fournissent un certain nombre de fonctions utiles.
Grâce aux wrappers, il est possible d'utiliser les bibliothèques OpenSSL dans une grande variété de langages de programmation.

Les paramètres de la commande en ligne OpenSSL sont très nombreux ; ils permettent d'indiquer entre autres l'un des nombreux types de chiffrement (exemple : blowfish, DES ou Triple DES, DSA, RC4, RC5, RSA...), d'encodage (base64 ou autres) et de hachage (MD5, SHA-1...). L'outil peut fonctionner en mode client et en mode génération de contenu.

Cet utilitaire et les bibliothèques associées sont disponibles pour la plupart des environnements et sont sous une licence de type Apache.

Les structures SSL BIO

La couche BIO est une couche d'abstraction d'entrée/sortie, grâce à celle-ci on peut lire dans un fichier classique, comme communiquer via un socket protégé par SSL.

Les chaînes

Cette couche contient deux types d'éléments, les sources (socket, fichier, ...) et les filtres (chiffrement, buffer, ...).
Ces éléments sont reliés ensemble selon les besoins de l'utilisateur, en une double liste chaînée. Un exemple classique est la chaîne BIO utilisée par un client SSL :

BIO_buffer => BIO_ssl => BIO_socket

Le premier élément de la chaîne est le premier à être appelé lors de toute opération de lecture/écriture. Par exemple, si l'on fait une opération read sur buffer, celui si va faire une opération read sur SSL, qui fera lui-même une opération read sur socket. Le dernier élément doit donc être une source, et les autres des filtres.
Tout BIO est un maillon d'une chaîne, lors de sa création, il est seul, c'est à nous de le lier grâce à BIO_push qui permet d'ajouter un élément à la fin BIO_pop permet de retirer l'élément courant de la chaîne, et renvoi l'élément suivant connecté à toute la chaîne résultante.

La structure des éléments

Un BIO_METHOD est un type, qui contient les opérations nécessaire au BIO :

typedef struct bio_method_st
{
	int type;
	const char *name;

	int (*bwrite)(BIO *, const char *, int);
	int (*bread)(BIO *, char *, int);
	int (*bputs)(BIO *, const char *);
	int (*bgets)(BIO *, char *, int);
	long (*ctrl)(BIO *, int, long, void *);

	int (*create)(BIO *);
	int (*destroy)(BIO *);

	long (*callback_ctrl)(BIO *, int, bio_info_cb *);
} BIO_METHOD;

Pour créer un nouvel élément, il nous faut récupérer le BIO_METHOD de notre élément.
Pour chaque type de maillon BIO, il existe une fonction permettant de récupérer ce BIO_METHOD, son nom est formé comme suit :

// sources
BIO_METHOD *BIO_s_accept(void);
BIO_METHOD *BIO_s_connect(void);
BIO_METHOD *BIO_s_socket(void);
BIO_METHOD *BIO_s_fd(void);

// filtres
BIO_METHOD *BIO_f_ssl(void);
BIO_METHOD *BIO_f_buffer(void);

// sources et filtres divers en vrac
BIO_METHOD *BIO_s_mem(void);
BIO_METHOD *BIO_s_log(void);
BIO_METHOD *BIO_s_datagram(void);
BIO_METHOD *BIO_s_bio(void);
BIO_METHOD *BIO_s_null(void);
BIO_METHOD *BIO_f_null(void);
BIO_METHOD *BIO_f_linebuffer(void);
BIO_METHOD *BIO_f_nbio_test(void);

La structure d'un maillon est complexe, mais il y a peu à gérer pour créer un nouveau type de maillon :

typedef struct bio_st
{
	BIO_METHOD *method;
 
	long (*callback)(struct bio_st *,int,const char *,int, long,long);
	char *cb_arg;

/* partie importante si on crée un nouveau type de maillon */
	int init;
	int shutdown;
	int flags;
	int retry_reason;
	int num;
	void *ptr; // on stocke nos données liées

	struct bio_st *next_bio;
	struct bio_st *prev_bio;

	int references;
	unsigned long num_read;
	unsigned long num_write;

	CRYPTO_EX_DATA ex_data;
} BIO;