Vous êtes sur la page 1sur 26

La cryptographie en VB.

NET

Par J-M Rabilloud

Date de publication : 13 décembre 2005

Cet article traitera des manipulations cryptographiques avec VB.NET.


La cryptographie en VB.NET par J-M Rabilloud

I - Introduction..............................................................................................................................................................3
II - Concepts................................................................................................................................................................ 4
II-A - Chiffrement.................................................................................................................................................... 4
II-A-1 - Algorithme secret..................................................................................................................................4
II-A-2 - Chiffrement à clé.................................................................................................................................. 4
II-A-2-a - Chiffrement à clé symétrique.......................................................................................................4
II-A-2-b - Chiffrement à clé asymétrique..................................................................................................... 4
II-A-2-c - Chiffrement à sens unique...........................................................................................................5
II-A-2-d - Techniques dérivées.................................................................................................................... 5
II-B - Identification.................................................................................................................................................. 5
II-B-1 - Hachage................................................................................................................................................5
II-B-2 - Limites du hachage.............................................................................................................................. 5
II-B-3 - Hachage avec une clé......................................................................................................................... 5
II-C - Génération de clé......................................................................................................................................... 5
II-C-1 - Aléatoire................................................................................................................................................6
II-C-2 - Dérivée................................................................................................................................................. 6
II-C-2-a - Mot de passe...............................................................................................................................6
II-C-3 - Composite.............................................................................................................................................6
II-D - Evaluation des risques et des besoins.........................................................................................................6
II-D-1 - Boucher les failles................................................................................................................................ 6
II-D-2 - Comprendre l'attaquant........................................................................................................................ 7
II-D-3 - Limitations.............................................................................................................................................7
III - L'espace de nom Security.Cryptography.............................................................................................................. 9
IV - Exemples............................................................................................................................................................ 11
IV-A - Chiffrement symétrique de fichier..............................................................................................................11
IV-B - Chiffrement Asymétrique de clé................................................................................................................ 14
IV-C - Le hachage................................................................................................................................................17
IV-C-1 - Salage............................................................................................................................................... 18
IV-C-2 - Contrôle d'intégrité............................................................................................................................ 19
IV-C-3 - Signature numérique.........................................................................................................................20
IV-D - Clé dérivée................................................................................................................................................ 22
IV-E - Clé composite............................................................................................................................................ 23
V - Conclusion........................................................................................................................................................... 26

-2-
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

I - Introduction

Dans cet article nous allons nous pencher sur la sécurisation des données privées au sens large du terme.

De tout temps la manipulation des données afin d'en préserver le secret ou l'intégrité fut un enjeu majeur de
l'information. Que ce soit la permutation de Jules César, l'encre invisible ou le sceau royal, il fut et demeure nécessaire
de pouvoir identifier ou chiffrer des données. Le Framework .NET met à notre disposition un certain nombre de
classes pour simplifier le travail, encore faut-il avoir les idées claires quant aux concepts mis en œuvre.

Cet article sera écrit en VB.NET 2003.

Bonne lecture.

-3-
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

II - Concepts

En informatique, il est toujours assez complexe de déterminer ce qui relève de quoi. En l'occurrence, la meilleure
façon de sécuriser des données consiste évidemment à ne pas les divulguer. Certes, ce n'est pas toujours très
commode mais cet aspect n'est pas à perdre de vue. Pourquoi ?

La protection des données repose généralement sur plusieurs couches, la première devant être la sécurisation
du poste de travail. En effet il ne sert à rien de chiffrer 140 fois un fichier si les clés sont facilement accessibles.
Nous verrons cela plus en détail lors de l'étude de la sécurisation des clés, mais si vous n'avez aucune notion
d'administration du poste de travail, je vous encourage vivement à vous pencher sur le sujet.

II-A - Chiffrement

Souvent jargonné sous le terme "Cryptage", le chiffrement est le principe le plus connu même si ce n'est pas toujours
le mieux compris. Le principe consiste à transformer les données avec des méthodes plus ou moins complexes afin
d'obtenir des données "protégées". Cette opération doit pouvoir être accomplie en sens inverse, le déchiffrement,
pour pouvoir récupérer les données d'origines.

Il existe de très nombreuses techniques car le principe est vieux comme le monde.

II-A-1 - Algorithme secret

Bien qu'ils aient presque complètement disparus, je vous en parle car il s'agit d'une tentation fréquente lorsqu'on
commence à se pencher sur les joies de la cryptographie. A la base, même une compression est un encodage et
on peut facilement croire qu'un encodage par un algorithme qu'on est le seul à connaître est particulièrement sûr.
Malheureusement, le Reverse Engineering étant ce qu'il est, cette approche est erronée. Il est toujours assez simple
de retrouver les opérations d'un algorithme et dès lors de casser la sécurité. Ne vous lancez pas dans ce genre
d'aventure, il n'y a pas de plus mauvaise sécurité qu'une sécurité illusoire.

II-A-2 - Chiffrement à clé

Tous les algorithmes modernes utilisent maintenant des chiffrements à clés. Il en existe de plusieurs sortes, regroupés
en trois grandes familles.

II-A-2-a - Chiffrement à clé symétrique

Dans ce type de chiffrement, la même clé sert au codage et au décodage des données. Il en existe plusieurs (Rijndael,
RC2, DES, Triple DES, etc…) mais tous reposent sur le même principe. Pour donner un exemple trivial, un chiffrement
à clé symétrique peut être la multiplication par deux de chaque code ASCII. Deux est alors la clé.

II-A-2-b - Chiffrement à clé asymétrique

Beaucoup plus complexe, ce chiffrement utilise une paire de clé publique/privée. La clé publique sert au chiffrement
et la clé privée au déchiffrement. Le plus connu d'entre eux est l'algorithme RSA (RIVEST, SHAMIR, ADLEMAN).

Les chiffrements à clé symétrique ou asymétrique ne sont pas plus sûrs selon la nature de la clé. Cette différence
est due aux problèmes de communication de clé. En effet, dans une approche du chiffrement à des fins de
communication, je dois à un moment ou un autre fournir la clé de déchiffrement dans le cas d'une clé symétrique.
La clé est alors vulnérable. Dans le cas d'un chiffrement asymétrique, il suffit de communiquer la clé publique aux
personnes souhaitant m'envoyer des données, pour qu'ils puissent chiffrer les données avec cette clé. Je pourrais
les déchiffrer à l'aide de ma clé privée qui, elle, n'est pas transmise.

-4-
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

Gardez à l'esprit que les chiffrements asymétriques sont plus lourds et donc beaucoup plus long, on les réserve
généralement pour le traitement de petit volume de données.

II-A-2-c - Chiffrement à sens unique

Cette famille un peu particulière nommée "hachage" ne permet pas le déchiffrement. Comme on l'utilise à des fins
d'identification, nous la verrons un peu plus loin.

II-A-2-d - Techniques dérivées

Dans la longue lutte entre chiffreurs et casseurs, il apparaît bien régulièrement de nouvelles techniques de dérivation
pour brouiller les pistes. On utilise par exemple le salage pour contrer les attaques par dictionnaire, les clés
composites ou les clés dérivées pour protéger la clé, etc…

II-B - Identification

Bien que l'identification soit un vaste domaine, elle fait partie intégrante du monde de la cryptographie informatique.
En effet, l'identification permet de pouvoir reconnaître une source de données chiffrées ou non comme sûre sans
avoir à la déchiffrer au préalable. Par ailleurs l'identification doit servir à diminuer les attaques par leurre. Bien que
généralement non suffisant, la base de l'identification repose généralement sur le hachage.

II-B-1 - Hachage

Le hachage (de l'anglais hash) est un chiffrement à sens unique, c'est-à-dire qu'il n'est pas théoriquement possible
de remonter à la valeur d'origine en connaissant la valeur hachée. Il existe de nombreux algorithmes (MD5, SHA1,
SHA256,…). Dans tous les cas, le hachage donne une chaîne résultante de longueur connue que l'on appelle taille de
hachage. L'intérêt du hachage est donc évidemment de faire de l'identification ou du contrôle d'intégrité de données.
On peut aussi l'utiliser à des fins de comparaison. Ainsi, il est beaucoup plus sûr de faire une comparaison de valeurs
hachées que de leurs homologues en clair.

II-B-2 - Limites du hachage

Quoique très fiable, le hachage a des limites. La première de ces limites est une utilisation correcte, car il est assez
facile de reconnaître une valeur hachée et il peut être assez facile de deviner ce qui a été haché. Dès lors, le leurre
redevient possible.

Le deuxième danger consiste à stocker des valeurs critiques hachées trop facilement accessible. Ainsi, si vous
hachez des mots de passe et que vous laissez les valeurs obtenues accessibles, vous rendez vos mots de passe
vulnérables à une attaque par dictionnaire, voire par force brute.

II-B-3 - Hachage avec une clé

Pour contourner la possibilité de corruption du hachage, on utilise généralement un hachage avec une clé, c'est-à-
dire qu'on ajoute une valeur secrète à la valeur à hacher ce qui rend théoriquement impossible une mystification.

II-C - Génération de clé

Il s'agit là du pivot de la cryptographie, sans de bonnes clés pas de cryptographie valable. Là encore, il existe plusieurs
techniques de génération de clé.

-5-
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

II-C-1 - Aléatoire

Les précurseurs de clé sont générés de façon aléatoire. Il faut s'assurer que la fonction aléatoire le soit bien, ce qui
exclu Rand par exemple, et privilégier les appels à des fonctions ad hoc. L'avantage de la génération aléatoire est
qu'elle permet de générer des clés très robustes quand elle est bien utilisée.

II-C-2 - Dérivée

Très populaire puisqu'elle permet de ne pas stocker la clé, la génération de clé dérivée est cependant périlleuse car
elle n'est fiable que si les précurseurs (généralement des mots de passe) sont bien choisis, ce qui va nous permettre
de gloser quelque peu sur les mots de passe.

II-C-2-a - Mot de passe

L'éternel problème du mot de passe repose sur la continuelle lutte entre mémorisation et robustesse. Un mot de
passe fiable fait généralement une vingtaine de caractère utilisant des lettres sensibles à la casse, des chiffres
et des caractères de ponctuation, de plus il est de bon ton qu'il ne contienne aucun mot ou suite de caractères
susceptible de le rendre vulnérable à une attaque par dictionnaire. Autant dire tout de suite que pour mémoriser
"dAT9{j*c3-{p5KvADyX(rb" il faut un peu d'entraînement. Cependant une clé dérivée de "médor" présente assez peu
de résistance aussi faut il trouver un compromis selon la sensibilité des données protégées et leur durée de vie.

II-C-3 - Composite

Il existe un grand nombre de techniques de génération de clé. On les nomme clés composites car leurs précurseurs
viennent de sources différentes. Les plus utilisées sont des clés dérivées où le précurseur est un mot de passe
prétraité avec une autre donnée. Attention cependant, il existe des générateurs un peu exotiques. J'ai vu ainsi
un programme utiliser des paramètres hardware dans les précurseurs d'une clé de chiffrement de données. C'est
uniquement le jour du changement de poste de travail que l'utilisateur c'est rendu compte qu'il ne pouvait plus
déchiffrer ses données (ce qui prouve au moins qu'elles étaient bien sécurisées).

II-D - Evaluation des risques et des besoins

La première étape lorsqu'on se lance dans la sécurisation des données consiste à évaluer ce dont on a besoin, et
donc, d'avoir une idée des techniques d'attaques.

II-D-1 - Boucher les failles

Avant toute attaque assez volumineuse, les attaquants vont toujours commencer par chercher les failles éventuelles.
Bien qu'elles soient connues, on les retrouve très fréquemment.

Ne stocker jamais un mot de passe ou une clé en clair dans le code.

De manière générale éviter de stocker quoi que ce soit dans le code car il s'agit d'un endroit particulièrement
vulnérable. Lorsque des valeurs sensibles doivent y être, elles doivent être hachées. Méfiez vous aussi des chaînes
de connexions qui peuvent contenir des informations sensibles en clair.

Ne hacher jamais le seul contenu d'un fichier si vous mettez la valeur hachée dans le fichier

Une des plus redoutables fausses bonnes idées consiste à hacher le contenu du fichier, puis à ajouter la valeur
obtenue en fin de fichier. La première chose que va essayer un pirate qui trouve une valeur hachée en fin de fichier, est
une combinaison courante (nom de fichier + contenu, contenu seul, etc…) pour savoir à quoi correspond le hachage.

-6-
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

N'écrivez jamais des données déchiffrées sur le disque

Même temporairement. Votre chiffre sera d'autant plus vulnérable que le pirate pourra accéder à la fois aux
représentations claire et chiffrée. Il y aura de toute façon une faille grave puisqu'il suffirait de faire planter l'application
au moment ou le fichier en clair existe. Par ailleurs des données même temporairement déchiffrées sur un disque
peuvent rester accessibles alors que le fichier est détruit.

N'utilisez jamais de méthode de cryptage cassée

Il ne sert à rien d'implémenter une méthode utilisant le chiffre de beaufort par exemple car certains logiciels de
décryptage le casseront en quelques minutes. Partez du principe que l'attaquant sait ce qu'il fait. Toutes les méthodes
de chiffrement vulnérables aux attaques par "mot probable" par exemple doivent être bannies.

N'utilisez pas de clé faible

Lorsqu'une clé est générée aléatoirement, il peut exister un risque de créer une clé faible. Une clé faible est une clé
présentant un élément de symétrie. Par exemple, si pour une clé 128 bits, les 64 premiers bits ont la même valeur
que les 64 derniers, vous avez une clé faible.

II-D-2 - Comprendre l'attaquant

Pour vous défendre correctement, vous devez appréhender les techniques de l'attaquant. La cryptographie est
une chaîne dont la sécurité est régie par le maillon le plus faible. A part quelques boutonneux généralement peu
dangereux, les attaquants qui cherchent à casser un chiffre sont des gens expérimentés qui vont toujours chercher
le point de vulnérabilité de votre défense.

La lutte peut revêtir deux aspects, la bataille des clés ou l'attaque du chiffre.

Attaquer un chiffre donné par les algorithmes standards de chiffrement, pour peu qu'il soit correctement utilisé, est une
entreprise colossale, demandant du temps, des ressources importantes et une solide connaissance des mécanismes
de chiffrement. C'est donc généralement autour de la clé que se joue la sécurité.

Une chose est sûre pour le défenseur, vous devez mettre les clés le plus à l'abri possible. Une chose est certaine
pour l'attaquant, si votre code sait déchiffrer, la clé sera à un moment ou à un autre relativement accessible.

Comme vous l'avez compris, la clé ne doit pas être présente dans le code. Ou elle doit être dérivée d'une donnée
secrète, ou elle doit exister dans une ressource externe. Si l'application n'est pas censée être installée sur n'importe
quel poste, vous pouvez utiliser des fichiers ou le registre (avec des ACL correctes), sinon, seule la dérivation est
véritablement fiable.

Dans le pire des cas, l'attaquant peut installer une version fonctionnelle de l'application sur un poste où il possède
les droits administrateurs.

II-D-3 - Limitations

• Utiliser le hachage, les signatures numériques ou des certificats à des fins d'identification. Une identification
réussie ne doit pas vous dispenser d'un contrôle de validité des données entrantes, ceci vous permettra
d'éviter qu'une faille se transforme en désastre.
• Le chiffrement est une opération lourde, veillez à ne pas l'utiliser pour protéger des données non sensibles.
• La mise en place d'une cryptographie nécessitant des ressources externes à l'application demande d'utiliser
une stratégie de déploiement spécifique. Celle-ci doit alors tenir compte des règles d'administration définies
par le client.
• Dans le cadre des applications censées chiffrer / déchiffrer, on utilise généralement des clés dérivées puisqu'il
n'est pas nécessaire de les stocker. Cependant si votre application utilise une gestion d'accès spécifique (à

-7-
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

chaque utilisateur un mot de passe) les données chiffrées par un utilisateur ne pourront être lue par un autre
ce qui n'est pas forcément bienvenu. Les applications à mot de passe commun contournent cela mais au prix
d'une plus grande vulnérabilité puisque le mot de passe doit être communiqué.

Utiliser le hachage, les signatures numériques ou des certificats à des fins d'identification. Une identification réussie
ne doit pas vous dispenser d'un contrôle de validité des données entrantes, ceci vous permettra d'éviter qu'une faille
se transforme en désastre.

-8-
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

III - L'espace de nom Security.Cryptography

Cet espace de nom contient l'ensemble des classes nécessaires à la gestion de la cryptographie. On retrouve
généralement toujours la même construction hiérarchique, à savoir :

<Famille Algorithmes>

<Algorithmes>

<Fournisseur ou Classe>

Une représentation incomplète peut être exprimée par l'arborescence suivante :

-9-
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

Dans la suite de cet article, nous allons voir quelques exemples des pratiques les plus courantes de manipulation
des classes de cet Espace de nom.

- 10 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

IV - Exemples

IV-A - Chiffrement symétrique de fichier

Cette première application (WinForms) permet de crypter des fichiers avec l'algorithme symétrique Triple DES (Data
Encryption Standard). Celui-ci utilise une clé de 168 bits (ou 192 bits), qui sont en fait trois clés de 56 bits et un vecteur
d'initialisation. Ce vecteur à pour but d'empêcher l'identification de blocs chiffrés similaires pour un texte clair similaire.

Généralement on utilise le service cryptographique le plus proche possible des données à chiffrer afin de diminuer
les vulnérabilités de la clé.

Il est nécessaire d'avoir la clé et le vecteur pour déchiffrer, ils seront donc créés une fois puis stockés dans le registre.

Nous allons aussi utiliser des évènements personnalisés pour suivre la progression de l'opération. Je vais donc créer
une bibliothèque de classe (crypto.vb) :

Tout d'abord je dérive une classe pour mon argument d'évènement :

Public Class ChiffreEventArgs

Inherits System.EventArgs
Private m_Realize, m_Total As Long

Public Sub New(ByVal ValRealise As Long, ByVal ValTotal As Long)


Me.m_Realize = ValRealise
Me.m_Total = ValTotal
End Sub

Public ReadOnly Property Total() As Long


Get
Return Me.m_Total
End Get
End Property

Public ReadOnly Property Realise() As Long


Get
Return Me.m_Realize
End Get
End Property

End Class

Cet argument renverra le nombre d'octets à convertir et le nombre d'octets convertis. Maintenant nous allons créer
une classe de chiffrement / déchiffrement de fichier selon l'algorithme Triple DES. Mon entête de classe sera :

Imports Microsoft.Win32
Imports System.IO
Imports System.Security
Imports System.Security.Permissions
Imports System.Security.Cryptography

<Assembly: RegistryPermission(SecurityAction.RequestMinimum, All:="HKEY_CURRENT_USER\SOFTWARE


\Secure")>
<Assembly: FileIOPermission(SecurityAction.RequestMinimum, Unrestricted:=True)>

Comme nous l'avons vu dans la sécurité d'accès au code, je peux demander la vérification des autorisations au
niveau assembly afin d'interdire l'appel à ma bibliothèque en cas d'autorisations insuffisantes.

Le code de la classe sera :

Public Class CryptFile

- 11 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

'Déclaration des délégués pour le suivi de l'opération asynchrone


Delegate Sub StartChiffreEventHandler(ByVal sender As Object, ByVal e As ChiffreEventArgs)
Delegate Sub EndChiffreEventHandler(ByVal sender As Object, ByVal e As ChiffreEventArgs)
Delegate Sub ProgressChiffreEventHandler(ByVal sender As Object, ByVal e As ChiffreEventArgs)
'Déclaration des évènements pour le suivi de l'opération asynchrone
Public Event StartChiffreEvent As StartChiffreEventHandler
Public Event EndChiffreEvent As EndChiffreEventHandler
Public Event ProgressChiffreEvent As ProgressChiffreEventHandler

Private RegApp As RegistryKey


Private STDES As TripleDESCryptoServiceProvider
Public Sub New()

'vérification du registre
RegApp = Registry.CurrentUser.OpenSubKey("Software\\Secure\\chPers", True)
STDES = New TripleDESCryptoServiceProvider
If RegApp Is Nothing Then 'les clés de registre n'existent pas
With STDES 'je génére une clé de chiffrement et un vecteur
.GenerateIV()
.GenerateKey()
End With
'je les mets dans le registre
RegApp = Registry.CurrentUser.CreateSubKey("Software\\Secure\\chPers")
RegApp.SetValue("cle", Convert.ToBase64String(STDES.Key))
RegApp.SetValue("vecteur", Convert.ToBase64String(STDES.IV))
Else 'les clés de registre existent
With STDES 'je récupère les valeurs du registre
.Key = Convert.FromBase64String(CType(RegApp.GetValue("cle"), String))
.IV = Convert.FromBase64String(CType(RegApp.GetValue("vecteur"), String))
End With
End If

End Sub

Public Sub chiffrement(ByVal Fichier As String)

If File.Exists(Fichier) Then
Dim FichierSource As New FileStream(Fichier, FileMode.Open, FileAccess.Read)
Dim FichierCible As New FileStream(Path.ChangeExtension(Fichier, "cry"), _
FileMode.Create, FileAccess.Write)
Dim ChiffreFlux As New CryptoStream(FichierCible, STDES.CreateEncryptor,
CryptoStreamMode.Write)
FichierCible.SetLength(0)
Dim bin(100) As Byte
Dim LongTotale As Long = FichierSource.Length
RaiseEvent StartChiffreEvent(Me, New ChiffreEventArgs(0, LongTotale))
Dim LongEffectue As Long = 0
Dim BlocLen As Integer
'traitement
While LongEffectue < LongTotale
BlocLen = FichierSource.Read(bin, 0, 100)
ChiffreFlux.Write(bin, 0, BlocLen)
LongEffectue += BlocLen
RaiseEvent ProgressChiffreEvent(Me, New ChiffreEventArgs(LongEffectue,
LongTotale))
End While
RaiseEvent EndChiffreEvent(Me, New ChiffreEventArgs(LongEffectue, LongTotale))
ChiffreFlux.Close()
FichierSource.Close()
FichierCible.Close()
Else
Throw New FileNotFoundException("Le fichier n'as pas été trouvé", Fichier)
End If

End Sub

Public Sub Dechiffrement(ByVal Fichier As String, ByVal ExtensionCible As String)

If File.Exists(Fichier) Then
Dim FichierSource As New FileStream(Fichier, FileMode.Open, FileAccess.Read)
Dim FichierCible As New FileStream(Path.ChangeExtension(Fichier, ExtensionCible), _

- 12 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

FileMode.Create, FileAccess.Write)
Dim ChiffreFlux As New CryptoStream(FichierCible, STDES.CreateDecryptor,
CryptoStreamMode.Write)
FichierCible.SetLength(0)
Dim bin(100) As Byte
Dim LongTotale As Long = FichierSource.Length
RaiseEvent StartChiffreEvent(Me, New ChiffreEventArgs(0, LongTotale))
Dim LongEffectue As Long = 0
Dim BlocLen As Integer
'traitement
While LongEffectue < LongTotale
BlocLen = FichierSource.Read(bin, 0, 100)
ChiffreFlux.Write(bin, 0, BlocLen)
LongEffectue += BlocLen
RaiseEvent ProgressChiffreEvent(Me, New ChiffreEventArgs(LongEffectue,
LongTotale))
End While
RaiseEvent EndChiffreEvent(Me, New ChiffreEventArgs(LongEffectue, LongTotale))
ChiffreFlux.Close()
FichierSource.Close()
FichierCible.Close()
Else
Throw New FileNotFoundException("Le fichier n'as pas été trouvé", Fichier)
End If

End Sub

End Class

Pour exécuter un chiffrement symétrique Triple DES je crée une instance du fournisseur
TripleDESCryptoServiceProvider. Si les valeurs n'existent pas déjà dans le registre, je crée une clé de 192 bits et un
vecteur. Notez que le générateur de nombre aléatoire utilisé pour générer la clé interdit la création d'une clé faible.

Une fois que mon fournisseur possède une clé et un vecteur, il peut fournir ces mécanismes de chiffrement /
déchiffrement. Pour sécuriser l'opération, on chiffre généralement un flux. Pour cela, on utilise une instance de
CryptoStream qui attend une référence au flux sortant, un appel au service de chiffrement et le mode d'action. Ensuite
l'opération elle-même est très simple.

Ce code chiffre donc le fichier spécifié. Ce chiffrement est robuste, le seul point faible de l'application étant la capacité
d'accéder à la clé de registre pour un attaquant. Si les ACL sont correctement définies, il est quasiment impossible
de briser ce chiffrement, surtout si je régénère une clé et un vecteur périodiquement.

Le déchiffrement prendrait exactement la même forme si ce n'est que je devrais créer CryptoStream avec le code :

Dim ChiffreFlux As New CryptoStream(FichierClair, STDES.CreateDecryptor, CryptoStreamMode.Write)

Et que je dois passer l'extension du fichier de sorti.

Un code de consommation de ma classe pourrait être :

Private Sub cmdCryptFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _


Handles cmdCryptFile.Click
Dim MonFichier As String
With Me.OpenFileDialog1
.CheckFileExists = True
.DefaultExt = "doc"
.Filter = "Documents Word (*.doc)|*.doc|Fichiers texte (*.txt)|*.txt|
Tous les fichiers (*.*)|*.*"
.FilterIndex = 1
.Multiselect = False
.Title = "Selection du fichier à chiffrer"
If .ShowDialog(Me) = DialogResult.OK Then
MonFichier = .FileName
End If

- 13 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

End With
Try
Dim objChiffre As New Crypto.CryptFile
AddHandler objChiffre.StartChiffreEvent, AddressOf Operation_StartChiffreEvent
AddHandler objChiffre.ProgressChiffreEvent, AddressOf Operation_ProgressChiffreEvent
AddHandler objChiffre.EndChiffreEvent, AddressOf Operation_EndChiffreEvent
objChiffre.chiffrement(MonFichier)
Catch ex As Exception
MsgBox("Erreur lors de l'opération", MsgBoxStyle.Critical And
MsgBoxStyle.OKOnly, "ERREUR")
End Try

End Sub

Private Sub Operation_StartChiffreEvent(ByVal sender As Object, ByVal e As


Crypto.ChiffreEventArgs)
With Me.lblChiffrement
.Text = "Opération en cours..."
.Visible = True
End With
Me.pgbChiffrement.Visible = True
End Sub

Private Sub Operation_ProgressChiffreEvent(ByVal sender As Object, ByVal e As


Crypto.ChiffreEventArgs)
Me.pgbChiffrement.Value = CInt(e.Realise / e.Total * 100)
End Sub

Private Sub Operation_EndChiffreEvent(ByVal sender As Object, ByVal e As Crypto.ChiffreEventArgs)


Me.lblChiffrement.Visible = False
Me.pgbChiffrement.Visible = False
End Sub

IV-B - Chiffrement Asymétrique de clé

En l'état je peux donc chiffrer et déchiffrer des fichiers sur mon poste. Par contre je ne peux pas fournir ces fichiers
à l'extérieur sans fournir la clé, qui du coup devient plus vulnérable.

Supposons que nous voulions communiquer ces fichiers à neo.51 par mail. Je dois trouver un moyen sécurisé de lui
transmettre la clé. Pour cela, nous allons utiliser un cryptage asymétrique.

Il est assez facile de créer des clés asymétriques dans .NET mais il faut se méfier. Si la clé publique est faite pour être
communiquée, la clé privée, elle, ne doit jamais l'être. Or le fournisseur RSA permet d'exporter assez simplement
des informations de clé pouvant contenir la clé privée. Ces méthodes, parfois appelées « clés mobiles » doivent être
utilisées en toute connaissance de cause. En effet, les clés mobiles sont extrêmement vulnérables si elles sont trop
facilement accessibles. Généralement, on ne les utilise que pour garder les valeurs de clés en cas d'incident sur le
poste de travail. Les clés mobiles ne devraient jamais être utilisées au sein d'une application.

Lorsqu'on crée une paire de clé, on utilise généralement un « magasin » (KeyContainer) qui gère le stockage et la
protection des clés sur le poste de travail.

Je vais simuler tout cela au sein d'un même exemple. Tout d'abord, je vais ajouter un constructeur à la classe CryptFile
que nous avons vu précédemment, afin de pouvoir l'utiliser avec un couple clé, vecteur importé.

Public Sub New(ByVal Cle() As Byte, ByVal Vecteur() As Byte)


'création d'un service avec des valeurs externes
STDES = New TripleDESCryptoServiceProvider
With STDES
.Key = Cle
.IV = Vecteur
End With
End Sub

- 14 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

Ensuite, nous allons créer une classe gérant le chiffrement asymétrique.

Public Class RSAPaire


Private m_Magasin As String
Private m_RSA As RSACryptoServiceProvider

Public Sub New(ByVal NomMagasin As String, ByVal CreerMagasin As Boolean)

m_Magasin = NomMagasin
If CreerMagasin Then CreateMagasin() Else RecupMagasin()

End Sub

Public Sub New(ByVal ImportString As String)


m_RSA = New System.Security.Cryptography.RSACryptoServiceProvider
m_RSA.FromXmlString(ImportString)
End Sub

Private Sub CreateMagasin()


Dim cspParam As CspParameters = New CspParameters
cspParam.KeyContainerName = m_Magasin
m_RSA = New System.Security.Cryptography.RSACryptoServiceProvider(cspParam)
m_RSA.PersistKeyInCsp = True

End Sub

Private Sub RecupMagasin()


Dim cspParam As CspParameters = New CspParameters
cspParam.KeyContainerName = m_Magasin
m_RSA = New System.Security.Cryptography.RSACryptoServiceProvider(cspParam)
End Sub

Public Function ExportPublicKey() As String


Return m_RSA.ToXmlString(False)
End Function

Public Function CryptData(ByVal DonneeClaire() As Byte) As Byte()


Return m_RSA.Encrypt(DonneeClaire, False)
End Function

Public Function DecryptData(ByVal DonneeChiffree() As Byte) As Byte()


Return m_RSA.Decrypt(DonneeChiffree, False)
End Function

End Class

Ce constructeur est particulier dans le sens qu'il permet au fournisseur RSACryptoServiceProvider de chiffrer mais
pas de déchiffrer.

Reprenons donc, je veux échanger la recette de la garbure avec Neo.51 afin qu'il ne se nourrisse pas uniquement
de hamburger ce qui n'est pas bon pour lui. Cette recette sera cryptée afin que Maïté ne nous tombe pas dessus
quand elle verra que je ne mets pas de confit.

Pour que Neo.51 puisse déchiffrer le fichier je dois lui faire parvenir la clé et le vecteur Triple DES. Il doit donc créer
un magasin et en exporter la clé publique. En effet, j'ai besoin de sa clé publique pour chiffrer les informations. Si je
chiffre avec la mienne il ne pourra pas déchiffrer puisqu'il n'a pas ma clé privée.

On peut simuler cela avec le code suivant :

Private Sub cmdExportPubKey_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


_
Handles cmdExportPubKey.Click
Dim objRsa As New Crypto.RSAPaire("neo", True)
Me.txtPublicKey.Text = objRsa.ExportPublicKey
End Sub

- 15 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

Il lui suffit alors de m'envoyer la chaîne obtenue dans un mail.

Je vais donc utiliser cette chaîne pour chiffrer mes informations de clé symétrique :

Private Sub cmdRSACrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _


Handles cmdRSACrypt.Click

Dim objRsa As New Crypto.RSAPaire(Me.txtPublicKey.Text)


Dim RegApp As RegistryKey = Registry.CurrentUser.OpenSubKey("Software\\Secure\\chPers", True)
Dim CryptCleSym() As Byte
Dim CryptVecSym() As Byte
CryptCleSym =
objRsa.CryptData(Convert.FromBase64String(CType(RegApp.GetValue("cle"), String)))
CryptVecSym =
objRsa.CryptData(Convert.FromBase64String(CType(RegApp.GetValue("vecteur"), String)))
Me.txtCleSymCry.Text = Convert.ToBase64String(CryptCleSym)
Me.txtVecSymCry.Text = Convert.ToBase64String(CryptVecSym)

End Sub

Je possède donc maintenant deux chaînes chiffrées correspondant respectivement à la clé et au vecteur Triple DES.
Je peux les mettre à mon tour dans un mail avec le fichier word précédemment chiffré. Pour déchiffrer le fichier,
Neo.51 devra seulement déchiffrer les informations de clé avec sa clé privé, puis le fichier. Par exemple :

Private Sub cmdDecryptKeyAndFile_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) _
Handles cmdDecryptKeyAndFile.Click
Dim objRsa As New Crypto.RSAPaire("neo", False)
Dim DecryptCleSym() As Byte
Dim DecryptVecSym() As Byte
DecryptCleSym = objRsa.DecryptData(Convert.FromBase64String(Me.txtCleSymCry.Text))
DecryptVecSym = objRsa.DecryptData(Convert.FromBase64String(Me.txtVecSymCry.Text))
Dim MonFichier As String
With Me.OpenFileDialog1
.CheckFileExists = True
.DefaultExt = "cry"
.Filter = "Fichiers chiffrés (*.cry)|*.cry"
.FilterIndex = 1
.Multiselect = False
.Title = "Selection du fichier à déchiffrer"
If .ShowDialog(Me) = DialogResult.OK Then
MonFichier = .FileName
End If
End With
Try
Dim objChiffre As New Crypto.CryptFile(DecryptCleSym, DecryptVecSym)
AddHandler objChiffre.StartChiffreEvent, AddressOf Operation_StartChiffreEvent
AddHandler objChiffre.ProgressChiffreEvent, AddressOf Operation_ProgressChiffreEvent
AddHandler objChiffre.EndChiffreEvent, AddressOf Operation_EndChiffreEvent
objChiffre.Dechiffrement(MonFichier, "doc")
Catch ex As Exception
MsgBox("Erreur lors de l'opération", MsgBoxStyle.Critical And
MsgBoxStyle.OKOnly, "ERREUR")
End Try

End Sub

Cette technique est correctement sécurisée puisqu'à aucun moment la clé privée n'a été communiquée. Cependant,
il ne faut pas perdre de vue quelques considérations annexes. Une des nombreuses légendes du Web veut que les
chiffrements asymétriques soient la panacée universelle, toujours bien plus sûrs que leurs homologues symétriques.
Non seulement il n'en est rien, mais cela peut être fallacieux. Les clés asymétriques telle que la paire RSA de l'exemple
peuvent toujours être attaquées par reconstruction. Ces attaques sont d'autant plus efficaces que l'on peut récupérer
des informations de la clé publique pour conduire l'attaque. Ainsi dans mon exemple, la clé RSA est plus vulnérable
que le fichier crypté car elle n'est pas assez longue. Rassurez vous quand même, l'attaque d'une clé RSA de 1024
bits ne se fait pas en dix minutes.

- 16 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

Je vous ai montré ici un exemple d'implémentation particulier, mais sachez que le Framework expose des
classes RSAOAEPKeyExchangeFormatter et RSAOAEPKeyExchangeDeformatter qui gèrent parfaitement ce type
de fonctionnement.

IV-C - Le hachage

Comme nous l'avons vu dans la partie théorique, le hachage est un chiffrement en sens unique utilisé principalement
à des fins d'authentification. Le premier exemple est le simple hachage de mot de passe.

Dans le plus simple des cas, imaginons une boite de dialogue pour entrer dans mon application, avec un mot de
passe commun pour tous les utilisateurs :

Private Sub cmdOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


cmdOK.Click
Dim SHA As New SHA256Managed
Dim UniEnc As New System.Text.UnicodeEncoding
Dim bitPass() As Byte = UniEnc.GetBytes(Me.txtPassword.Text)
If
Convert.ToBase64String(SHA.ComputeHash(bitPass)) = "ew9LkdvpuYaurqPCDV3rWGZ1vTaD3GfN6b441cA0TNQ=" Then
Me.DialogResult = DialogResult.OK
Else
Me.DialogResult = DialogResult.Cancel
End If
End Sub

Notez que je laisse sous forme de chaîne dans le code source la valeur hachée de comparaison. Cela est sans
importance puisqu'on ne peut pas remonter de la valeur hachée vers la valeur claire. Cependant la sécurité ne repose
que sur la robustesse du mot de passe. Ce genre d'application est assez rare pour des raisons évidentes, on trouve
plus souvent des applications multi utilisateur, chacun gérant son mot de passe.

Le stockage de ces mots de passe est généralement une base de données ou un fichier, comme c'est le cas pour
l'authentification par formulaire ASP.NET.

Prenons un exemple comme celui-ci. Les données de connexion se trouvent rangée sous la forme :


<credentials>
<User Name="Jean-Marc" Password="ew9LkdvpuYaurqPCDV3rWGZ1vTaD3GfN6b441cA0TNQ=" />
<User Name="Morpheus" Password="ew9LkdvpuYaurqPCDV3rWGZ1vTaD3GfN6b441cA0TNQ=" />
<User Name="Neo.51" Password="ew9LkdvpuYaurqPCDV3rWGZ1vTaD3GfN6b441cA0TNQ=" />

</ credentials >

Autant le dire clairement, si vous hachez simplement les mots de passe tel que nous venons de le faire et s'il y
a de nombreux utilisateurs enregistrés, vous êtes probablement loin de la sécurité. L'efficacité des attaques par
dictionnaire n'est plus à démontrer, pas plus que la faiblesse des mots de passe usuellement choisis. Une méthode
pour résoudre cela consiste à forcer le choix d'un mot de passe robuste.

Par exemple, le code suivant force la saisie d'un mot de passe robuste :

<Flags()> Private Enum Conforme


HasLower = 1
HasUpper = 2
HasNumber = 4
HasOther = 8
End Enum

Private Sub txtNewPass_Validating(ByVal sender As Object, ByVal e As


System.ComponentModel.CancelEventArgs) _
Handles txtNewPass.Validating
If Me.txtNewPass.Text.Length < 12 Then

- 17 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

e.Cancel = True

Me.ErrorProvider1.SetError(Me.txtNewPass, "Le mot de passe doit contenir au moins 12 caractères")


End If
Dim Verif As New Conforme
Dim tabChar() As Char = Me.txtNewPass.Text.ToCharArray
For cmpt As Integer = tabChar.GetLowerBound(0) To tabChar.GetUpperBound(0)
Select Case True

Case Char.IsPunctuation(tabChar(cmpt)) OrElse Char.IsSymbol(tabChar(cmpt))


Verif = Verif Or Conforme.HasOther

Case Char.IsLower(tabChar(cmpt))
Verif = Verif Or Conforme.HasLower

Case Char.IsUpper(tabChar(cmpt))
Verif = Verif Or Conforme.HasUpper

Case Char.IsNumber(tabChar(cmpt))
Verif = Verif Or Conforme.HasNumber

End Select
Next
If Verif < 15 Then
e.Cancel = True
Me.ErrorProvider1.SetError(Me.txtNewPass, _
"Le mot de passe doit contenir au moins une majuscule, une minuscule un chiffre et un symbole")
End If
End Sub

Dans ce type de contrainte, veillez à ne pas forcer le changement de mot de passe trop fréquemment ; la sécurité
doit être présente et non pesante.

IV-C-1 - Salage

Une autre technique pour se protéger contre les attaques par dictionnaire consiste à utiliser le salage (parfois nommé
"hachage avec clé"). Le salage est l'adjonction d'un terme au terme à hacher pour obtenir un hachage résistant. Selon
les cas, le sel (c'est-à-dire le terme ajouté) doit être secret ou non. Dans le cas de notre fichier, il doit être original
puisqu'il ne peut être secret stricto sensu.

Pour la suite de notre exemple, imaginons le fichier App.config suivant :

<?xml version="1.0" encoding="utf-8" ?>


<configuration>
<configSections>
<sectionGroup name="SecurityGroup">
<section name="AccessSection"
type="System.Configuration.NameValueSectionHandler" />
<section name="IntegriteSection"
type="System.Configuration.SingleTagSectionHandler" />
<section name="SaltSection"
type="System.Configuration.SingleTagSectionHandler" />
</sectionGroup>
</configSections>
<SecurityGroup>
<AccessSection>
<add key="bidou" value="pua2jaEGDfiz/1Co3uDWSigjl/jzwMVtU9LJzYED+O4=" />
<add key="neo.51" value="1pxvek/zYndThdRUtZDtWtta9qIZzf1ELgsLb6qE+k8=" />
<add key="morpheus" value="lHUgdYfqWnThea9P3uBkaE8q7TuQ1MC1g4rJH/fHRLQ=" />
</AccessSection>
<IntegriteSection Setting1 ="V+HG0hhMdCIctvSFD5kqfE1vCZX6FjprtHuoxoTEppo=" />
<SaltSection Setting1 ="VV0+*àBD" Setting2 ="c)4Dé}yB" Setting3 ="w5jnpFgP" />
</SecurityGroup>
</configuration>

Un exemple de vérification de mot de passe pourrait être par exemple :

- 18 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

Private Sub cmdOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


cmdOK.Click
Dim Salage As IDictionary
Dim collSec As NameValueCollection
Dim SHA As New SHA256Managed
Dim UniEnc As New System.Text.UnicodeEncoding

collSec = CType(Configuration.ConfigurationSettings.GetConfig("SecurityGroup/AccessSection"),
NameValueCollection)
Salage = CType(Configuration.ConfigurationSettings.GetConfig("SecurityGroup/SaltSection"),
IDictionary)
For Elem As Integer = 0 To collSec.Count - 1
If collSec.GetKey(Elem).CompareTo(Me.txtUserName.Text) = 0 Then
Dim bitPass() As Byte = _
UniEnc.GetBytes(Me.txtPassword.Text.Insert(3, Salage.Item("Setting" & (1 +
Elem).ToString).ToString))
If
Convert.ToBase64String(SHA.ComputeHash(bitPass)).CompareTo(collSec.Get(Elem)) = 0 Then
Me.DialogResult = DialogResult.OK
Exit Sub
End If
End If
Next
Me.DialogResult = DialogResult.Cancel

End Sub

Dans ce cas, j'ai placé mes termes de sel dans le fichier de configuration. Cependant j'ai un peu complexifié l'opération
en insérant le sel dans le mot de passe. Ne sous estimez pas l'efficacité du salage. Beaucoup de pirates en herbe se
livrent à des attaques par dictionnaire sans même étudier le fonctionnement, le salage rendra le dictionnaire inopérant.

Même si dans mon exemple cela reste très simple, le salage permet d'augmenter fortement la sécurité. Par exemple
je pourrais multiplier les leurres en ajoutant dans le fichier des valeurs de salage que je n'utilise pas ; je pourrais
également utiliser une composition de valeurs pour saler, etc…

En l'état, les hachages ne sont pas spécialement vulnérables, si ce n'est que rien n'empêche de mettre une autre
valeur hachée à la place d'un hachage de mot de passe existant ce qui permettrait alors de franchir la sécurité (à
condition de saler correctement).

IV-C-2 - Contrôle d'intégrité

La problématique du contrôle d'intégrité des fichiers est toujours bien plus complexe qu'il y parait à première vue.
D'abord parce que si les données hachées sont susceptibles d'être modifiées, le hachage doit être relativement facile
d'accès, ensuite parce qu'un des pièges les plus classique consiste à hacher des données prévisibles ce qui permet
à un hacker de retrouver la logique du contrôle et donc de pouvoir modifier le fichier à sa guise.

Ne vous lancez pas non plus dans une surenchère du chiffrement, chiffrer le hachage ne change généralement rien
dans une optique d'application installable partout car la clé de chiffrement sera aussi accessible que le hachage.

Continuons avec mon fichier de configuration précédent. Je veux donc lui donner une identification afin qu'il ne soit
pas possible de faire fonctionner l'application avec une version du fichier modifiée par ailleurs.

Le principe est toujours le même. On récupère un certain nombre de données que l'on mixe ensemble avant de
procéder au hachage. On obtient alors une valeur, appelée parfois "empreinte de sécurité" ou "signature numérique"
que l'on compare avec une même valeur précédemment stockée. Il existe deux écoles pour le stockage de
l'empreinte.

• Le stockage interne : C'est-à-dire dans le fichier marqué.


• Le stockage externe : C'est-à-dire dans le registre ou dans un autre fichier.

- 19 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

Le stockage interne : C'est-à-dire dans le fichier marqué.

Les deux méthodes sont sensiblement équivalentes, elles permettent l'utilisation de leurre (par exemple stocker
plusieurs valeurs dans le registre alors qu'une seule est utilisée). Regardons un exemple de contrôle en stockage
interne, valeur que vous voyez dans le fichier de configuration dans la section "IntegriteSection".

Private Sub frmPass_Activated(ByVal sender As Object, ByVal e As


System.EventArgs) Handles MyBase.Activated
Dim Salage As IDictionary
Dim collSec As NameValueCollection
Dim SHA As New SHA256Managed
Dim UniEnc As New System.Text.UnicodeEncoding
Dim TabString() As String
Dim Integrite As String

collSec = CType(Configuration.ConfigurationSettings.GetConfig("SecurityGroup/AccessSection"),
NameValueCollection)
Salage = CType(Configuration.ConfigurationSettings.GetConfig("SecurityGroup/SaltSection"),
IDictionary)
ReDim TabString(collSec.Count * 3)
For cmpt As Integer = 0 To collSec.Count - 1
TabString(cmpt * 3) = Salage.Item("Setting" & (1 + cmpt).ToString).ToString
TabString(cmpt * 3 + 1) = collSec.GetValues(cmpt).GetValue(0).ToString
TabString(cmpt * 3 + 2) = collSec.GetKey(cmpt)
Next
TabString(TabString.GetUpperBound(0)) =
System.Reflection.Assembly.GetExecutingAssembly.ImageRuntimeVersion
Integrite = CType(Configuration.ConfigurationSettings.GetConfig("SecurityGroup/
IntegriteSection"), _
IDictionary).Item("Setting1").ToString
Dim bitPass() As Byte = UniEnc.GetBytes(String.Join(Me.Height.ToString, TabString))
If Convert.ToBase64String(SHA.ComputeHash(bitPass)).CompareTo(Integrite) <> 0 Then
MsgBox("Echec du controle d'intégrité", MsgBoxStyle.Critical And MsgBoxStyle.OKOnly)
Me.DialogResult = DialogResult.Cancel
End If
End Sub

J'ai utilisé ici une empreinte assez simple, il demeure évidemment possible de faire beaucoup plus complexe.

Attention toutefois à ce que vous utilisez, car selon les cas vous pouvez vous piéger vous-même. Par exemple, j'ai
une fois intégré dans l'empreinte la date de dernière modification du fichier. Comme je faisais un stockage interne,
j'enregistrais le fichier par la suite ce qui fait que mon contrôle d'intégrité plantait systématiquement.

IV-C-3 - Signature numérique

La signature numérique consiste à identifier des données et leur provenance. Fondamentalement, cela consiste à
hacher des données puis à signer ce hachage avec une clé privé asymétrique. On peut identifier ces données grâce
à la valeur du hachage, et vérifier leur authenticité par contrôle de la signature à l'aide de la clé publique.

Par exemple, nous allons ajouter deux propriétés et deux fonctions à notre classe RSAPaire comme suit :

Public ReadOnly Property ValeurHachage() As Byte()


Get
Return Me.m_ValHash
End Get
End Property

Public ReadOnly Property Signature() As Byte()


Get
Return Me.m_ValSign
End Get
End Property

Public Sub CreeSignature(ByVal Fichier As String)

- 20 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

Dim RSASignature As New RSAPKCS1SignatureFormatter(m_RSA)


Dim Flux As New FileStream(Fichier, FileMode.Open, FileAccess.Read)
Dim SHA As New SHA1CryptoServiceProvider
Me.m_ValHash = SHA.ComputeHash(Flux)
With RSASignature
.SetHashAlgorithm("SHA1")
Me.m_ValSign = .CreateSignature(Me.m_ValHash)
End With
End Sub

Public Function VerifSignature(ByVal ValeurHachee As String, ByVal


LaSignature As String) As Boolean
Dim RSASignature As New RSAPKCS1SignatureDeformatter(m_RSA)
RSASignature.SetHashAlgorithm("SHA1")
Return RSASignature.VerifySignature(Convert.FromBase64String(ValeurHachee), _
Convert.FromBase64String(LaSignature))
End Function

Les deux propriétés ont peu d'intérêt, penchons nous sur les fonctions.

Dans mon exemple, j'attends un nom de fichier que je vais pouvoir hacher. C'est ce hachage que je vais signer à
l'aide de l'objet RSAPKCS1SignatureFormatter.

La fonction VerifSignature est quand à elle le simple pendant de la fonction VerifySignature de l'objet
RSAPKCS1SignatureDeformatter.

Maintenant je vais appeler ma méthode de chiffrement afin de crypter le fichier et de récupérer une signature.

'creation de la signature
Dim objRsa1 As New Crypto.RSAPaire("neo", True)
objRsa1.CreeSignature(FichierCrypte)
Me.txtHashFile.Text = Convert.ToBase64String(objRsa1.ValeurHachage)
Me.txtNumSign.Text = Convert.ToBase64String(objRsa1.Signature)
'verification de la signature
Dim PubKey As String = objRsa1.ExportPublicKey
Dim objrsa2 As New Crypto.RSAPaire(PubKey)
If objrsa2.VerifSignature(Me.txtHashFile.Text, Me.txtNumSign.Text) Then
MsgBox("Signature valide")
Else
MsgBox("Signature non valide")
End If

Dans la première partie, je crée un objet RSA en récupérant les clés de mon magasin comme nous l'avons vu
précédemment, je transmets alors le nom du fichier chiffré et je récupère les deux valeurs obtenues, c'est-à-dire le
hachage et le hachage signé. La vérification quant à elle a lieu grâce à un objet RSAPaire qui ne contient que la
clé publique.

In fine j'obtiens donc un fichier chiffré, une valeur de hachage, une signature numérique. Le fait que le fichier soit
chiffré n'a aucune importance sur l'authentification. Celui qui réceptionne ces trois éléments et qui connaît ma clé
publique peut vérifier que :

• Le hachage est bien correspondant à la signature


• Le hachage est bien correspondant au fichier

Le hachage est bien correspondant à la signature

Donc le fichier est bien authentique.

Cette technique est extrêmement efficace, car tant que la clé privée est bien protégée, l'intégrité et l'authentification
ne font aucun doute. Cette technique d'identification peut être utilisée dans de nombreux scénarios.

- 21 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

IV-D - Clé dérivée

Le principe de la clé dérivée repose donc sur la génération d'une clé à partir d'un précurseur qui lui est censé être
secret. Prenons l'exemple le plus courant où le précurseur est un mot de passe. Dans mon exemple, l'application
utilise des Datasets chiffrés (sous forme XML) et nécessite donc un mot de passe pour pouvoir les lire. On manipule
les clés dérivées dans le Framework à l'aide de la classe PasswordDeriveBytes.

Pour dériver la clé, c'est-à-dire pour fournir une clé en partant d'un mot de passe, cette classe attend :

• Un nombre d'itération
• Un algorithme de hachage
• Une valeur de salage
• Le mot de passe

Un nombre d'itération

Le principe est assez simple, le mot de passe est ajouté au sel, et l'ensemble est haché le nombre de fois précisé
selon l'algorithme défini.

Trois remarques cependant.

Il faut que la valeur de hachage soit suffisamment longue pour pouvoir alimenter une clé de la bonne dimension (dans
notre cas 192 bits soit 24 caractères).

Par ailleurs il faut un mot de passe robuste afin de se garantir contre les attaques par dictionnaire puisque le sel
est fourni par l'application.

On pourrait durcir la protection en allongeant la taille du sel et/ou en demandant un deuxième mot de passe comme
valeur de salage.

En l'état mon code serait :

Private Sub cmdAccCryptData_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _


Handles cmdAccCryptData.Click

Dim CryptXML As New FileStream(Application.StartupPath & "\biblio.cry", FileMode.Open)


Dim pdb As New Security.Cryptography.PasswordDeriveBytes(Me.txtPass.Text, _
New Byte(7) {21, 10, 16, 21, 32, 2, 78, 9})
With pdb
.HashName = "SHA256"
.IterationCount = 722
End With
Dim Prov3DES As New TripleDESCryptoServiceProvider
With Prov3DES
.Key = pdb.GetBytes(24)
.IV = pdb.GetBytes(8)
End With
Dim CryptFlux As New CryptoStream(CryptXML, Prov3DES.CreateDecryptor, CryptoStreamMode.Read)
Dim MonDs As New DataSet
MonDs.ReadXml(CryptFlux, XmlReadMode.ReadSchema)
Me.DataGrid1.DataSource = MonDs

End Sub

L'avantage évident de cette méthode est que la clé n'est stockée nulle part.

- 22 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

IV-E - Clé composite

Pour finir, nous allons voir une technique chère aux auteurs de shareware, la clé composite. Ce type de clé utilise
des précurseurs de deux sources, généralement l'éditeur et la machine. Il existe de nombreux schémas possibles, je
vais prendre un grand classique comme exemple. Cependant il faut généralement faire preuve de plus d'imagination
pour créer un système résistant.

Dans cette implémentation, le Shareware possède un bouton "enregistrer"qui génère une clé à envoyer à l'éditeur,
celui-ci renvoyant une clé à donner au logiciel pour activer les fonctionnalités manquantes. Le programme contient
donc une clé publique dont l'éditeur possède la clé privée pour sécuriser le transfert.

La clé publique peut être stockée n'importe où car sa découverte n'a pas grande importance.

Pour extraire des informations de la machine, on utilise l'interop avec WMI, c'est-à-dire les classes de l'espace de
nom Management.

Créons une classe qui va nous permettre de manipuler la clé composite.

Public Class ExtractInfo


Private m_info1, m_info2, m_info3 As String

Public Sub New()

m_info1 = GetMacAddress()
m_info2 = GetDiskSerial()
m_info3 = GetProcessorRef()

End Sub

Private Function GetMacAddress() As String

Dim NetClass As New


System.Management.ManagementClass("Win32_NetworkAdapterConfiguration")
Dim Nets As ManagementObjectCollection = NetClass.GetInstances
Dim Net As ManagementObject
For Each Net In Nets
GetMacAddress = Net("MacAddress").ToString
Exit For
Next Net

End Function

Private Function GetDiskSerial() As String

Dim diskClass As New System.Management.ManagementClass("Win32_LogicalDisk")


Dim disks As System.Management.ManagementObjectCollection = diskClass.GetInstances()
Dim disk As System.Management.ManagementObject
For Each disk In disks
If CStr(disk("Name")) = "C:" Then
GetDiskSerial = disk("VolumeSerialNumber").ToString
End If
Next disk

End Function

Private Function GetProcessorRef() As String

Dim ProcClass As New System.Management.ManagementClass("Win32_Processor")


Dim Procs As ManagementObjectCollection = ProcClass.GetInstances
Dim Proc As ManagementObject
For Each Proc In Procs
GetProcessorRef = Proc("ProcessorId").ToString
Exit For
Next Proc

- 23 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

End Function

Public Function EmissionCle(ByVal Pbk As String) As Byte()


Dim mRSA As New RSACryptoServiceProvider
mRSA.FromXmlString(Pbk)
Dim UEnc As New System.Text.UnicodeEncoding
Dim strTest As String = Me.m_info1 & "|" & Me.m_info2 & "|" & Me.m_info3
Dim TabByte() As Byte = UEnc.GetBytes(strTest)
Return mRSA.Encrypt(TabByte, False)
End Function

Public Function VerifyKey(ByVal Test As String) As Boolean

Dim cmpt As Integer


Dim TabByte(23), rndByte() As Byte, Verif() As Byte
Dim dEnc As New System.Text.ASCIIEncoding
dEnc.GetBytes(m_info1.Substring(4, 2)).CopyTo(TabByte, 0)
ReDim Verif(1)
dEnc.GetBytes(m_info1.Substring(6, 2)).CopyTo(Verif, 0)
dEnc.GetBytes(m_info2.Substring(0, 5)).CopyTo(TabByte, 2)
cmpt = 1 + m_info2.Length - 6
ReDim Preserve Verif(cmpt)
dEnc.GetBytes(m_info2.Substring(6)).CopyTo(Verif, 2)
dEnc.GetBytes(m_info3.Substring(0, 5)).CopyTo(TabByte, 8)
ReDim Preserve Verif(cmpt + m_info3.Length - 6)
dEnc.GetBytes(m_info3.Substring(6)).CopyTo(Verif, cmpt + 1)
rndByte = Convert.FromBase64String( _
Registry.CurrentUser.OpenSubKey("Software\\Secure\\Share").GetValue("part").ToString)
rndByte.CopyTo(TabByte, 14)
dEnc.GetBytes(m_info1.Substring(8, 2)).CopyTo(TabByte, 22)
Dim m3DES As New TripleDESCryptoServiceProvider
m3DES.Key = TabByte
m3DES.IV = New Byte(7)
{Verif(0), Verif(1), Verif(2), Verif(3), Verif(4), Verif(5), Verif(6), Verif(7)}
Dim ms As New IO.MemoryStream
Dim CryptFlux As New CryptoStream(ms, m3DES.CreateEncryptor, CryptoStreamMode.Write)
CryptFlux.Write(System.Text.UnicodeEncoding.Unicode.GetBytes(Test), 0, Test.Length)
Dim PassByte As Byte() = ms.ToArray
If String.Compare(Registry.CurrentUser.OpenSubKey("Software\\Secure\\Share") _
.GetValue("ver").ToString, Convert.ToBase64String(PassByte)) <> 0 Then
Return False
Else
Return True
End If

End Function

End Class

Dans cet exemple, je récupère l'adresse MAC, le numéro de série du disque C et la référence du processeur. J'ai
implémenté par ailleurs deux fonctions, une qui génère une chaîne cryptée avec les informations et une autre qui
vérifie la clé finale, autrement dit qui vérifie que le logiciel est bien enregistré.

La création de la chaîne cryptée pour l'envoie vers l'éditeur n'est pas bien complexe, elle reprend ce que nous avons
vu pour le chiffrement asymétrique.

Une fois cette chaîne arrivée, l'éditeur va donc à son tour retourner une chaîne à l'utilisateur. Que contient elle ?

Elle contient en fait deux choses :

• Le mot de vérification codé


• Le complément de la clé Triple DES

Le mot de vérification codé

- 24 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

Ces deux valeurs seront stockées dans le registre lors de l'enregistrement.

En regardant maintenant le code de vérification, on comprend mieux comment est composée une clé composite.
Dans cet exemple, la clé TripleDES est composé d'un tableau de 24 byte définit par :

• 2 octets donnés par l'adresse MAC


• 10 octets donnés par l'éditeur
• 5 octets donnés par la référence processeur
• 5 octets donnés par le numéro de série du disque C
• 2 octets donnés par l'adresse MAC

2 octets donnés par l'adresse MAC

Le vecteur quand à lui est uniquement composé par des paramètres de la machine.

Dans cet exemple, la solution est assez vulnérable, mais je pourrais très facilement la durcir en :

- 25 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/
La cryptographie en VB.NET par J-M Rabilloud

V - Conclusion

Voila, nous avons vu les grandes familles de gestion des données secrètes. N'oubliez pas que votre plus grand
ennemi demeure dans les chaînes de caractères, et qu'une bonne défense doit être rigoureuse. Ne vous alarmez
pas trop, la plupart des attaquants sont assez mauvais et utilisent des logiciels d'attaque qu'ils n'ont pas écrit. Ceux-
là n'ont aucune chance de percer vos défenses si vous ne commettez pas d'erreur.

- 26 -
Copyright ® 2005 J-M Rabilloud. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://bidou.developpez.com/tutoriels/dotnet/securite/crypto/

Vous aimerez peut-être aussi