Fichiers texte (CSV) en python

1 – Introduction

Un fichier « CSV » est un fichier texte qui respecte un certain format. En effet, comme son nom l’indique (comma seperated values) : valeurs séparées par des virgules. Le format CSV est très utilisé comme format par les tableurs (comme excel) et les logiciels de base de données pour les opérations d’import et d’export.

Dans cet article, on va découvrir le format « CSV », puis étudier la manière de manipuler ce genre de fichiers en Python.

2 – Fichiers CSV

Le contenu d’un fichier est un ensemble de lignes, où chaque ligne est composée de plusieurs valeurs séparées par des virgules (la virgule est le séparateur par défaut).

Exemple de fichier CSV : 

Sexe,Prénom,Année de naissance
M,Bob,1990
F,Alice,1980
F,Eve,2000

Le séparateur par défaut est la virgule « , ». Toutefois, on peut définir d’autres séparateurs comme : le point-virgule « ; », l’espace  » « , les deux points « : », … etc.

3 – Python et fichiers CSV

Comme les fichiers CSV sont des fichiers texte, il faut d’abord les ouvrir en mode lecture texte « r ». Pour cela, on utilise la fonction « open »

file = open("fichier.csv", "r")

Ensuite, on peut commencer à lire le contenu. Il existe différentes méthodes pour lire un fichier CSV selon ce qu’on veut récupérer : quelques caractères, une lignes, la listes des lignes, ou tout simplement tout. Soit « file » notre variable python qui est obtenue après ouverture du fichier :

  • file.read(n) : lire les « n » (au max) premiers caractères du fichier et les renvoie dans une chaîne de caratères.
  • file.readline() : lire la première ligne, c’est-à-dire, lire des caractère jusqu’à arriver au caractère « \n ».
  • file.readlines() : lire tout le fichier et le retourner sous forme de liste de lignes.
  • file.read() : lire tout le contenu du fichier et le retourner dans une chaîne de caractères.

Pour écrire dans un fichier texte, on utilise la méthode « write ».

  • file.write(texte) : écrire « texte » dans le fichier.

Enfin, pour fermer le fichier, on utilise la méthode « close ». C’est toujours important de fermer un fichier surtout après une écriture.

  • file.close()

Par exemple, pour remplacer le séparateur d’un fichier CSV de virgule « , » à dière « # », on a deux manières de faire :

3.1 – Sans le module csv

Pour lire le contenu d’un fichier CSV sans utiliser le module Python « csv », il faudra lire le fichier ligne par ligne et parser les lignes en python :

f = open("fichier.csv", "r+")     # mode lecture/écriture
lignes = f.readlines()
f.seek(0) # retour au début du fichier
for l in lignes:
# découper les lignes en plusieurs éléments
s = l.split(",")
# regrouper les éléments
ss = "#".join(s)
# écrire la ligne dans le fichier
f.write(ss)
f.close()

3.2 – Avec le module csv

Avec le module CSV, on utilise une la fonction « reader » qui génère un itérateur et qui itère sur les ligne du fichier. Cette fonction s’occupe également de parser les lignes. Ensuite, on utilise « writer » pour l’écriture.

import csv
f = open("fichier.csv", "r+")
r = csv.reader(f, delimiter=",")
lignes = list(r)
f.seek(0) # retour au début du fichier
w = csv.writer(f, delimiter="#")
w.writerows(lignes)
f.close() # fermeture du fichier

3 – Quelques Exercices

D’autres exercices sont disponibles sur ma playlist youtube.

3.1 – Récupérer les commentaires d’un programme python

Hypothèse : Les chaînes de caractère dans le programme python ne contiennent pas le caractère « # ».

Les étapes à suivre sont :

  1. Ouverture du fichier en mode lecture « r »
  2. Pour chaque ligne :
    1. Vérifier si la ligne contient le caractère « # » et récupérer son indice.
    2. Extraire la sous chaîne de caractère à partir du « # » jusqu’à la fin de la ligne.
    3. mettre cette sous chaîne dans une liste.
  3. Fermeture du fichier et renvoi de la liste.

Le code de la fonction python ressemble à ça :

def getComments(file):
f = open(file) # ouverture du fichier en mode lecture
ligne = f.readline()
res = []
while ligne != "": # parcours du contenu du fichier
pos = ligne.find("#") # recherche l'indice de '#'
if pos != -1:
res.append(ligne[pos:])
ligne = f.readline()
f.close() # fermeture du fichier
return res # renvoi du résultat

3.2 – Récupérer une ligne d’un fichier CSV

On dispose d’un fichier CSV qui contient un certain nombre de lignes et de colonnes. On voudrait récupérer une ligne particulière. Le programme doit accepter les indices positifs et négatifs. Si l’indice de la ligne se trouve en dehors de l’intervalle des lignes du fichier, le programme renvoie une liste vide.

Les étapes à suivre sont :

  1. Ouverture du fichier en mode lecture.
  2. Lecture du contenu du fichier dans un reader CSV.
  3. Vérification que l’indice de ligne appartient bien à l’intervalle.
  4. Fermeture du fichier et renvoie de la ligne

Le programme ressemble à :

def getLigne(file, n, sep=","):
f = open(file, 'r')
# lire le contenu du fichier
r = csv.reader(f, delimiter=sep, quoting=csv.QUOTE_NONNUMERIC)
liste = list(r)
f.close()
if (n < len(liste)) and (n >= -len(liste)):
res = liste[n]
else:
res = []
return res

3.3 – Récupérer une colonne d’un fichier CSV

Cet exercice ressemble beaucoup à l’exercice précédent. Il suffit juste d’inverser les lignes et les colonnes du fichier pour retrouver exactement la même situation.

Les étapes à suivre sont :

  1. Ouverture du fichier et récupération du contenu dans un reader CSV.
  2. Inversement des lignes et des colonnes
  3. Suite comme l’exercice précédent.

Le programme ressemble à ça :

def getColonne(file, n, sep=","):
f = open(file, 'r')
r = csv.reader(f, delimiter=sep, quoting=csv.QUOTE_NONNUMERIC)
lr = list(zip(*r)) # inverser les lignes et les colonnes

# vérifier que "n" est dans le bon intervalle
if (n < len(lr)) and (n >= -len(lr)):
r = list(lr[n])
else:
r = []
f.close()
return r

Il existe une autre manière de faire : L’idée est de lire le contenu du fichier, de parcourir le contenu ligne par ligne et extraire l’élément en question de chaque ligne. Le code ressemble à :

def getColonne(file, n, sep=","):
f = open(file, 'r')
r = csv.reader(f, delimiter=sep, quoting=csv.QUOTE_NONNUMERIC)
liste = list(r)
f.close()
res = []
if (n < len(liste[0])) and (n >= -len(liste[0])):
for ligne in liste:
res.append(ligne[n])
return res

4 – Conclusion

Dans cet artcile, on a vu comment manipuler (ouverture/lecture/écriture) d’un fichier texte en Python, et particulièrement un fichier CSV.

L’article a traité également quelques exercices liés aux fichiers CSV. Vous pouvez trouvez plus d’exercices sur les fichiers CSV en Python sur ma playlist youtube

Tutoriel : Utilisation de base de OpenSSL

1 – Introduction

OpenSSL est une boite à outils qui comporte deux bibliothèques « libcrypto » et « libssl ». Elles implémentent respectivement une variété d’algorithmes de la cryptographie (Chiffrement symétrique/asymétrique, hachage, signature numérique, certificats, …) et le protocole de communication SSL/TLS. Elle offre également une interface ligne de commande qui s’appelle « openssl ».

Elle est développée en langage C, et est sortie en 1998 pour la première fois.

2 – Qu’est ce que OpenSSL

La bibliothèque OpenSSL est une implémentation libre des protocoles SSL et TSL. Elle donne accès à :

  • Une bibliothèque de fonctionnalité écrite en C permettant de réaliser des applications client/serveur sécurisées s’appuyant sur SSL/TSL,
  • Un ensemble d’exécutables en ligne de commande permettant :
    • La création de clés RSA, DSA (pour les signatures)
    • La création de certificat X509 (identification)
    • Le calcul d’empreinte (MD5, SHA, RIPEMD160, …)
    • Le chiffrement et le déchiffrement (RSA, DES, IDEA, RC2, RC4, Blowfish, …)
    • La réalisation de de tests de clients et serveurs SSL/TSL
    • La signature et le chiffrement de courriers (S/MIME).

Généralement, OpenSSL est installée par défaut sur les système d’exploitation Linux. Pour avoir l’aide sur les fonctionnalités et l’utilisation en général de la bibliothèque OpenSSL, il faut taper la commande :

$ man openssl

La syntaxe générale pour l’utilisation en mode shell des fonctionnalités OpenSSL est la suivante :

$ openssl <commande> <options>

3 – Utilisation

3.1 – Chiffrement symétrique

Le chiffrement symétrique ou crypto-système à clé privée, utilise la même clé pour le chiffrement et le déchiffrement. Ceci nécessite que l’émetteur et le récepteur du message partagent la même clé privée. La figure suivante illustre bien le principe du chiffrement symétrique :

Parmi les crypto-systèmes à clé privée, on trouve AES, BlowFish, … etc. 
Dans la suite, on va considérer le crypto-système AES. Pour utiliser AES, on a besoin d’un mot de passe avec lequel on génère une clé de chiffrement/déchiffrement. Pour cela, on peut choisir n’importe quel chaîne de caractères, ou on peut également générer aléatoirement une chaîne en utilisant la commande « rand » d’OpenSSL :

$ openssl rand 32 > aes.key 

Cette commande va générer aléatoirement une chaîne de « 32 » caractères et la stocke dans un fichier qui s’appelle « aes.key ».

Pour chiffrer un fichier « file.txt » par exemple avec le chiffrement AES et la clé « aes.key », on va utiliser la commande « enc » de « OpenSSL » :

$ openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -salt -in file.txt -out file.aes - kfile aes.key

Quelques remarques :

  • -aes-256-cbc : Cette option indique que AES 256 avec le mode CDC qui est utilisé pour le chiffrement.
  • -pbkdf2 : Cette option d’indique l’utilisation de l’algorithme PBKDF2 avec un nombre d’itération (par défaut ou précisé par « -iter »), dans le but d’augmenter la résistance aux attaques par force brute.
  • -iter 100000 : Cette option sert à indiquer un nombre d’itérations différent de celui par défaut.
  • -salt : Cette option indique l’utilisation d’un salt lors du chiffrement.

Pour déchiffrer le message on utilise la même commande précédente à qui on ajoute l’option « -d » :

$ openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -salt -in file.aes -out dec_file.txt - kfile aes.key

Cette commande va déchiffrer le fichier « file.aes » et mettre le résultat dans le fichier « dec_file.txt ».

3.2 – Chiffrement asymétrique

Les crypto-systèmes asymétriques utilisent une paire de clés (publique et privée). La clé publique est connue par tout le monde, et est utilisée pour chiffrer les messages destinés au propriétaire de la clé. La clé privée est utilisée, quant-à-elle, pour déchiffrer les messages reçus. La figure suivante illustre le principe de ce crypto-système :

3.2.1 – Génération de clés RSA

Avant de pouvoir chiffrer et déchiffrer des messages en utilisant RSA, il faudra d’abord créer une paire de clés. Pour cela, on utilise la commande « genrsa » de « OpenSSL » :

$ openssl genrsa -out key.pem 512

A la fin, on aura une clé privée RSA de 512 bits dans un fichier « key.pem ». 
Il est souvent recommander de protéger cette clé (fichier) par un mot de passe. Pour cela, l’algorithme DES3 est utilisé pour chiffrer ce fichier :

$ openssl rsa -in key.pem -des3 -out key.pem

A ce stade, on a un fichier « key.pem » qui contient une clé privée RSA chiffrer en utilisant un mot de passe et l’algorithme DES3. Ce fichier tel qu’il est ne sert pas à grand chose. En effet, on a besoin d’en extraire la clé publique et la partager avec les autres. Ceci va leur permettre de nous envoyer des messages chiffrés. Pour cela, il faut taper la commande suivante :

$ openssl rsa -in key.pem -pubout -out key.pub

Puisque, la clé privée « key.pem » est protéger par mot de passe, cette commande demande de taper le mot de passe, puis extrait la clé publique et la met dans un fichier « key.pub ». Ce dernier, peut être partagé avec les personnes qui veulent nous envoyer un message de manière confidentielle.

3.2.2 – Chiffrement avec RSA

Pour chiffrer un message avec RSA, on utilise la commande « rsault » avec l’option « -encrypt ». On lui donne la clé publique du destinataire « key.pub ». La commande pour faire le chiffrement est la suivante :

$ openssl rsautl -encrypt -pubin -inkey key.pub -in file.txt -out file.enc  

3.2.3 – Déchiffrement avec RSA

Pour déchiffrer un message avec RSA, on utilise la commande « rsault » avec l’option « -decrypt ». Il faut lui donner la clé privée comme paramètre :

$ openssl rsautl -decrypt -inkey key.pem -in file.enc -out file.dec

3.3 – Chiffrement hybride

Généralement le chiffrement asymétrique n’est pas utilisé tout seul, même s’il a des avantages. En effet, il est très souvent combiné avec le chiffrement symétrique Pour les raisons suivantes :

  •  Le chiffrement asymétrique (exemple RSA) ne permet pas de chiffrer de gros volumes de données. La taille des données qu’on peut chiffrer est limitée à quelques centaines d’octets.
  • Le chiffrement asymétrique est très gourmand en puissance de calcul contrairement au chiffrement symétrique.

Le chiffrement hybride profite des avantages des deux types de chiffrement (symétrique et asymétrique). En effet, le principe consiste à chiffrer les données avec une clé symétrique (AES par exemple) puis chiffrer la clé symétrique avec l’algortihme asymétrique. Ensuite il faudra envoyer les deux résultats (données chiffrées et clé chiffrée) au destinataire.

La figure suivante illustre ce principe :

3.4 – Signature numérique

La signature numérique sert à prouver qu’un message à été bel et bien envoyé par l’émetteur et que personne d’autre ne s’est fait passer pour lui. Pour cela, l’émetteur signe numériquement le message avant de l’envoyer. Et à la réception du message, le destinataire vérifie la signature numérique pour confirmer l’authenticité de l’émetteur. La figure suivante illustre ce principe :

Les crypto-systèmes à clé publique offrent le mécanisme de signature numérique contrairement aux crypto-systèmes à clé privée.

La signature numérique ne peut pas s’appliquer sur un gros volume de données (messages longs, fichiers volumineux, …), c’est pour cela qu’on signe le hash du message ou du fichier à envoyer. Les étapes à suivre sont :

  1. Calculer l’empreinte (ou le hash) du message :
    $ openssl dgst -sha256 file.aes > file.aes.hash
  2. Signer ce hash en utilisant le crypto-système à clé publique
    $ openssl rsautl -sign -inkey key.pem -in file.aes.hash -out file.signature
  3. Vérification de la signature : retrouver le hash à partir de la signature
    $ openssl rsautl -verify -pubin -inkey key.pub -in file.signature -out hash

4 – Conclusion

Dans cet article, on a présenté une introduction à la boite à outils OpenSSL et son utilisation pour faire du chiffrement symétrique et asymétrique. On a vu également la signature numérique avec un crypto-système à clé publique.

Les crypto-systèmes choisis sont RSA pour le chiffrement asymétrique et la signature numérique, et AES pour le chiffrement symétrique.

On a vu également un exemple d’utilisation de fonction de hashage : SHA256 pour la réalisation de la signature numérique.