IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Apprendre la programmation en VBA pour EXCEL par la pratique - Quatrième partie

Tome 4 - Un algorithme de chiffrement/déchiffrement des cellules pour une meilleure confidentialité

Ce cours est une suite de la série sur « apprendre la programmation en VBA pour Excel par la pratique ». Dans ce tome 4, vous allez apprendre la cryptologie en VBA pour chiffrer des cellules Excel.

Merci pour vos avis.
52 commentaires Donner une note à l´article (5)

Article lu   fois.

L'auteur

Profil Pro

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

« Ils sont invisibles, mais ils sont là, partout. Ils lisent nos messages, piratent nos ordinateurs, volent nos fichiers. Ils nous espionnent… »

Si comme Alice vous êtes un brin paranoïaque, ou plus simplement si vous avez besoin de communiquer des informations confidentielles, vous utilisez certainement des logiciels permettant de chiffrer vos données pour les protéger des espions.

Mais comment faire dans EXCEL pour garder secret le contenu d'une cellule, qui plus est, dans un fichier partagé ?
D'autant que les solutions proposées par EXCEL pour protéger une feuille ou un projet VBA n'apportent qu'une sûreté symbolique, car il circule sur Internet des méthodes très simples et rapides pour faire sauter ces protections.

Pour répondre à ce besoin de confidentialité, nous allons étudier un algorithme de chiffrement et de déchiffrement, on parle de cryptosystème, qui permet de rendre des cellules illisibles pour un utilisateur n'étant pas dans la confidence.

La cryptologie regroupe deux disciplines : la cryptographie qui rend un message inintelligible pour le diffuser en toute sécurité à un destinataire qui sait comment le déchiffrer, et la cryptanalyse qui inversement vise à déchiffrer un message dont on n'est pas le destinataire légitime.
Ces deux disciplines vont de pair. En effet, il est difficile d'imaginer une méthode de chiffrement sans penser aux failles qui pourraient permettre de la casser.

Alors avant de rentrer dans le vif du sujet, nous allons nous initier à la cryptologie au travers une brève étude des méthodes anciennes, puis modernes, afin de mieux comprendre comment fonctionne le cryptosystème que je vous présente dans ce mémento, qui est à la frontière entre ces deux approches, et quelles sont ses failles.

II. Les bases de la cryptologie - Les cryptosystèmes symétriques

La cryptographie existe depuis l'antiquité. Et certains considèrent l'écriture comme une subtile invention permettant de transmettre un message dans un langage codé réservé aux érudits.

L'alphabétisation se développant, il a fallu inventer d'autres méthodes pour échanger ses secrets.
Ce sujet étant très documenté, vous trouverez sur Internet de nombreuses façons de chiffrer un message, par exemple sur « http://www.bibmath.net/crypto/ ».

Nous n'étudierons ici que trois méthodes pour chiffrer un message constitué des 26 lettres de notre alphabet. Des cas d'école qui résument l'évolution de la cryptologie.

1re méthode : remplacer une lettre par un signe. Cela nécessite d'avoir une table de correspondance sous la main, ou une bonne mémoire. Pour déchiffrer, il faut remplacer le signe par la lettre correspondante, avec la table préalablement communiquée. Comme dans les jeux qu'on trouve sur les paquets de céréales du petit déjeuner.
Une variante, connue sous le nom de « code César » permet de se passer de l'encombrante table de correspondance en remplaçant une lettre par une autre avec un décalage, par exemple de 3 lettres, dans l'alphabet. « A » devient « D », « B » devient « E », etc., « X » devient « A ». Remarquez qu'avec un décalage de 13 lettres il suffit de chiffrer le message une deuxième fois pour obtenir le déchiffrement.
Cette méthode comporte un gros défaut : même sans connaître le décalage appliqué ou sans avoir la table de correspondance, l'analyse de la fréquence d'apparition des lettres, ou des signes, permet de déchiffrer facilement un message.
Par exemple, si « MESSAGE CODE » est chiffré en « PHVVDJH FRGH », sachant que le « E » est la lettre la plus utilisée en français, suivi du « A » et du « S », qu'une série de deux lettres identiques représente souvent « EE », « SS », « LL », ou « NN », qu'après deux consonnes on trouve une voyelle, ce message peut être déchiffré instantanément en « PessaJe FRGe ». Avec un peu de patience et un zeste d'intuition, les autres lettres se déchiffrent rapidement. Et plus le message est long, plus les indices sont nombreux, ce qui facilite l'exercice.

La 2e méthode, dite « code de Vigenère », vise à brouiller la fréquence d'apparition des lettres en faisant en sorte qu'une lettre ne soit pas toujours chiffrée de la même manière. Pour cela on introduit un « mot de passe », par exemple « SECRET », qui sert de clé pour le chiffrage, et on attribue une valeur pour chaque lettre. Espace vaut 0, « A » vaut 1, jusqu'à « Z » qui vaut 26.
Pour chiffrer, on additionne la lettre de la clé et la lettre du message. Si cette valeur est supérieure à 26, on retranche 26. Soit en mathématique, le reste de la division par 26, appelé modulo.
Quand on arrive à la fin de la clé on repart de sa première lettre.
Inversement pour déchiffrer on soustrait du message chiffré (ou cryptogramme) la valeur de la clé, en ajoutant 26 sur les valeurs inférieures à 1.

Un mécanisme permettant de chiffrer et de déchiffrer avec la même clé est dit symétrique et repose sur deux principes :

  • la clé est connue de l'expéditeur et du destinataire ;
  • la clé doit rester secrète.

Voici un exemple de chiffrement avec le code de Vigenère :

Image non disponible

Si le cryptogramme « VJCEJMLFJWEYLYCUTXX » est intercepté, il semble impossible à déchiffrer sans connaître la clé. Cependant, malgré les apparences, le code de Vigenère peut être cassé, si l'assaillant à une idée du contenu du message.

Reprenons cet exemple. Votre intuition est que le mot « MESSAGE » se trouve dans le cryptogramme.
En soustrayant au cryptogramme le mot « MESSAGE », en partant de la première lettre, vous obtenez un message déchiffré :

Image non disponible

« IEJLIFGF », ça ne donne pas plus d'information. Vous continuez votre test en partant cette fois de la deuxième lettre. Ce qui donne « JPZQTKYEW ». Vous continuez sur la lettre suivante…
Voici le résultat :

Image non disponible

« CRETSECRE », ça saute aux yeux, c'est la répétition de « SECRET ». Vous venez de trouver la clé pour déchiffrer ce cryptogramme.

C'est d'autant plus facile que la clé est courte et a une signification.
Donc pour une plus grande sécurité, il faut une clé longue, idéalement de la taille du message, et complètement aléatoire.

C'est le principe du chiffre de Vernam, la 3e méthode que nous étudions, une variante du chiffre de Vigenère qui sous certaines conditions est considérée comme indéchiffrable.

Voici une démonstration :
Alice chiffre « CE MESSAGE EST CODE AVEC LE CHIFFRE DE VERNAM » avec la clé aléatoire
« ABXRCTEFGJIOPLEDGVTUHGFDEVHADXSQGHTHKKHYVV », et obtient le cryptogramme
« DGXEHMXGNOITIFEGVZYUICKGEHMAGFBWMZYHGPZMWI ». Qui est théoriquement impossible à déchiffrer (si vous en doutez, essayez donc).
Sûre d'elle, Alice envoie un deuxième message, avec la même clé, ce qui donne « WGLVHTEZVEC ».

Bob intercepte ces deux cryptogrammes. Il sait juste qu'Alice à la fâcheuse habitude de commencer ses rédactions confidentielles par « le message suivant devra être détruit… », ou « ce message est confidentiel… », etc.
Il part donc du principe que le premier cryptogramme commence par « LE MESSAGE », et soustrait ces lettres au cryptogramme comme vu précédemment pour casser le code de Vigenère. Ce qui lui donne la clé « RBXRCTEFGJI ».
Certes incompréhensible, mais qui va lui servir. Car maintenant, Bob soustrait cette clé au second message. Et voit en clair « EENDEZ TOUT ». En modifiant sa première intuition « LE MESSAGE » par « CE MESSAGE », il obtient « VENDEZ TOUT ».

Image non disponible

Moralité, pour garder secrets ses messages, Alice doit utiliser une clé :

  • connue uniquement d'elle et du destinataire ;
  • de la taille du message à chiffrer, voire plus grande ;
  • complètement aléatoire ;
  • à usage unique.

III. La cryptologie moderne - Les cryptosystèmes asymétriques

La principale faille des cryptosystèmes symétriques est que la clé utilisée doit rester secrète. Et donc plus vous avez de destinataires dans la confidence, plus vous augmentez le risque de « fuite ».

Les cryptosystèmes asymétriques règlent ce problème en utilisant deux clés :

  • une pour chiffrer, qui peut être connue de tous, on parle alors de clé publique ;
  • une pour déchiffrer, qui elle seule est secrète, c'est la clé privée.

Mais par quel miracle la clé privée peut-elle déchiffrer un message chiffré avec une autre clé connue de tous, tout en restant secrète ?
C'est parce que les clés utilisées sont des nombres liés mathématiquement entre eux. Et si l'on retrouve facilement la clé publique à partir de la clé privée, l'inverse est quasi impossible en temps raisonnable, on parle de fonction mathématique à sens unique… à condition que la clé publique soit un nombre très grand. Nous allons voir pourquoi ci-dessous.

Voici un exemple avec de petits nombres pour mieux comprendre le principe d'un algorithme asymétrique.
Pour définir les clés, on prend deux nombres premiers au hasard. Par exemple p = 17 et q = 11.
On calcule leur produit, n = 17 x 11 = 187.
Puis la valeur de l'indicatrice d'Euler en n, Ø(n) = (p-1) x (q-1) = (17-1) x (11-1) = 160.
On choisit un entier inférieur à Ø(n) et qui est premier avec Ø(n), e = 7.
Enfin on calcule l'inverse de e modulo Ø(n), d = (Ø(n)+1) / e = (160+1) / 7 = 23.
Cela donne la clé publique constituée de n et e (187,7) et la clé privée constituée de n et d (187,23).

Soit un alphabet où A=1, B=2, C=3, etc.
Pour chiffrer « C » nous utilisons la clé publique dans la formule suivante : Code = reste de (3e/n).
Soit le reste de 37/187 = 2187 - (Entier(2187/187) x 187) = 130.
Pour déchiffrer 130 nous utilisons la clé privée dans la formule suivante : Lettre = reste de (130d/n).
Soit le reste de 13023/187 = 3, qui correspond à « C ».

Dans cet exemple, retrouver la clé privée semble facile si la clé publique est connue. En effet, la clé publique donne le premier nombre de la clé privée, n=187. Il ne reste plus qu'à trouver le second nombre (d=23) qui est Ø(n) + 1 / 7. Cela revient à trouver Ø(n) qui n'est autre que (p-1) x (q-1), c'est-à-dire, trouver deux nombres premiers p et q sachant que p x q = 187.
Après quelques calculs, 187 peut être factorisé en deux nombres premiers p=11 et q=17.

Voici un code très simple permettant de trouver la décomposition d'un nombre :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Sub Décomposition(n)

For i = 2 To n - 1
    While n / i = Int(n / i)
        Debug.Print i
        n = n / i
    Wend
Next i

End Sub

On retrouve alors Ø(n) = (11-1) x (17-1) = 160.
e est connu, c'est le 7 de la clé publique divulguée.
Et on peut alors calculer d = (160+1) / 7 = 23.

Si la clé privée a été retrouvée, c'est parce qu'il est facile de factoriser un petit nombre, mais les temps de traitement explosent avec de très grands nombres. Ici un très grand nombre est un nombre qui comporte plus d'une centaine de chiffres. Il faut alors des années de calculs pour trouver le résultat.

C'est donc uniquement la difficulté, actuelle, à factoriser un grand nombre en deux nombres premiers qui assure la confidentialité de la clé privée d'un cryptosystème asymétrique.

Malheureusement, il est impossible de manipuler des nombres à 100 chiffres en VBA. Au mieux nous pouvons traiter des entiers sur 29 chiffres (soit 14 octets), en utilisant le type de données « Decimal », qu'on obtient indirectement en déclarant les variables au format « Variant » puis en les convertissant avec la fonction « CDec ».

Mais un nombre si « petit » peut être décomposé en moins d'une seconde sur les sites Internet : « http://www.dcode.fr/decomposition-nombres-premiers ».
Si nous utilisons un cryptosystème asymétrique en VBA, nous devrons donc garder secrète la clé publique, ce qui lui fait perdre son intérêt. En attendant une version d'EXCEL qui permettra de calculer des nombres sur 256 octets.

Autre problème rencontré avec le VBA : aucune fonction intégrée n'est capable d'effectuer un calcul du type 12345 puissance 12345, ou de retourner le reste de 357 puissance 177 divisé par 55 (pourtant nécessaires dans un cryptosystème asymétrique), car cela dépasse les capacités de calcul d'EXCEL.
C'est sur Internet que j'ai trouvé les fonctions mathématiques en VBA qui permettent de réaliser ces calculs, reprises en annexe 2Annexe 2. Les fonctions mathématiques de calcul de modulo.

Et un cryptosystème asymétrique comme celui présenté ici ne règle pas tout, car dans un texte chaque lettre identique sera codée par le même nombre. Si plusieurs caractères doivent être chiffrés, il faudra donc brouiller le cryptogramme avec un chiffre de Vernam pour éviter une attaque par l'analyse de la fréquence d'apparition des nombres : donc conserver un code secret.
Ou bien en réserver l'usage au chiffrement des nombres.
Dans la pratique, les cryptosystèmes asymétriques ne chiffrent pas les caractères un à un, mais les regroupent en un seul entier, parfois très grand (donc hors des capacités de calcul du VBA) et c'est cet entier qui est chiffré.
Les cryptosystèmes asymétriques, qui mettent en œuvre des mathématiques complexes, sont donc généralement utilisés pour diffuser la clé sécrète des cryptosystèmes symétriques, qui sont beaucoup plus rapides dans les traitements de chiffrement et déchiffrement.

Vous trouverez en annexe 3Annexe 3. Code VBA d'un cryptosystème asymétrique adapté à EXCEL le code complet en VBA d'un cryptosystème asymétrique compatible avec les capacités de calcul du VBA. Attention, c'est un cas d'école, car il chiffre les caractères un à un.

IV. CryptoVBA - Un cryptosystème adapté à EXCEL

Dans le classeur d'Alice partagé par plusieurs utilisateurs, seules certaines cellules renseignées par Bob et Margaux devront être chiffrées. Elles sont représentées ici en jaune dans l'extrait d'un tableau d'une centaine de lignes :

Image non disponible
  • Impossible de masquer les colonnes et de protéger la feuille par un mot de passe, car comme nous l'avons vu, cette protection peut facilement être cassée.
  • Impossible aussi d'envoyer à Bob et Margaux des valises diplomatiques remplies de pages de chiffres de Vernam, ou de changer de mot de passe à chaque chiffrement d'une cellule.
  • Et attention aux traces laissées par le chiffrement : dans la colonne « Avis », deux choix sont possibles, et la taille du cryptogramme ne doit pas permettre d'en déduire le contenu.
  • Pire, dans certains cas, le chiffrement peut livrer des informations sur la clé secrète utilisée, comme dans ce tableau où chacun sait que Mathieu, qui est un élève brillant, aura un avis favorable.
  • Enfin, il est plus prudent que Bob et Margaux ne partagent pas le même mot de passe, mais chacun pouvant chiffrer des cellules, il faut qu'Alice puisse déchiffrer les cryptogrammes de ses collègues sans avoir à savoir qui a chiffré quoi, dit autrement, la clé de déchiffrement doit être trouvée automatiquement par l'algorithme parmi la liste des clés enregistrées.
  • Bien entendu, Alice est persuadée que Bob, très négligent, va laisser traîner le code source de l'algorithme, ou pire, le divulguer fièrement sur « developpez.com », et donner ainsi des indices aux pirates.

J'ai donc développé un cryptosystème adapté à EXCEL respectant ces contraintes…

- Qui utilise les propriétés de l'opérateur XOR pour manipuler bit à bit les octets de la chaîne à chiffrer ou déchiffrer : « L'opérateur XOR renvoie VRAI si les deux opérandes A et B ont des valeurs distinctes. »

Image non disponible

Voici un exemple pour chiffrer le caractère M avec la clé 124 :

Le caractère M vaut 77 en ANSI, soit l'octet : 01001101
La clé vaut 124, soit l'octet : 01111100
Une opération XOR donne l'octet : 00110001, soit la valeur 49.

Pour déchiffrer, on applique simplement à nouveau une opération XOR sur la clé et l'octet codé :
l'octet codé 49 : 00110001 ;
la clé 124 : 01111100.
Une opération XOR donne : 01001101, soit la valeur 77 qui correspond à M.

- Qui brouille le chiffrement pour éviter une analyse de la fréquence d'apparition des lettres.
Si on se contente de coder les octets avec un XOR et une clé secrète, toutes les mêmes lettres sont codées avec la même valeur. Pour éviter cela, la solution que j'ai retenue consiste :

  • à utiliser 4 clés au lieu d'une seule, les octets seront chiffrés 4 par 4, chacun possédant sa clé : clé1, clé2, clé3, clé4. Ces 4 clés forment « la clé secrète » ;
  • à faire varier ces 4 clés avant chaque nouveau chiffrement d'un octet dans un message :
    clé1 = clé1 + reste de ((clé1 x Q) / Coef). Idem pour clé2, clé3, clé4.
    Où Q est un entier aléatoire, et Coef est la multiplication des 4 clés divisée par 400.

- Qui permet d'obtenir des cryptogrammes différents si l'on chiffre plusieurs fois le même message avec la même clé.
La valeur de Q dans la formule ci-dessus est propre à chaque message. Ce qui permet de modifier le chiffrement alors que la clé sécrète reste identique.
Cette valeur sera enregistrée en en-tête du cryptogramme après avoir été codée pour ne pas donner d'indice : Q' = Q + (clé1 x clé2) / 1000.

Le pseudocode du chiffrement d'une chaîne donne :

  • décomposition de la clé secrète passée en argument en 4 clés de chiffrement notées clé1, clé2, clé3, clé4 ;
  • choix aléatoire d'un entier Q et enregistrement de Q' ;
  • calcul de l'entier Coef = (clé1 x clé2 x clé3 x clé4) / 400 ;
  • pour coder des groupes de 4 octets, il faut s'assurer que la taille de la chaîne à coder passée en argument est un multiple de 4 : si ce n'est pas le cas, alors ajout du caractère 1 pour indiquer une fin de chaîne puis ajout de caractères aléatoires jusqu'à obtenir une taille multiple de 4. Idem pour obtenir une chaîne d'une longueur minimale de 100 octets ;
  • boucle sur les caractères de la chaîne en avançant de 4 octets à chaque passage :

    • récupération des 4 octets à coder,
    • incrémentation des 4 clés,
    • pour chacun des 4 octets : opération XOR sur l'octet et le reste de (la clé de l'octet / 255),
    • conversion des 4 octets codés en un entier pour incrémenter le cryptogramme ;
  • Fin de la boucle.

Nous ajouterons aussi dans le cryptogramme la référence de la clé utilisée, c'est-à-dire sa date de création (au format année, mois, jour, heure au centième de seconde) cela permettra d'identifier automatiquement la clé à utiliser pour le déchiffrement parmi la liste des clés disponibles.
Ainsi Alice pourra déchiffrer les cryptogrammes de Bob et de Margaux sans avoir à savoir quelle clé elle doit utiliser dans sa liste de clés.

Remplacer le contenu d'une cellule par son cryptogramme aurait un effet esthétique désastreux. La solution retenue est d'enregistrer le cryptogramme dans le commentaire de la cellule. Le contenu de la cellule sera remplacé par des caractères neutres, par exemple « ### » juste pour signaler que la cellule est chiffrée.

Lors du déchiffrement, le commentaire est lu, le cryptogramme est déchiffré et la cellule reprend son contenu d'origine, qui peut être des caractères, une valeur, une formule, peu importe, car nous utiliserons dans nos traitements la propriété « Formula » et non pas « Value » de la cellule.

Si un commentaire existait déjà pour la cellule, il n'est pas supprimé, mais il est lui aussi chiffré.
Il sera déchiffré en même temps que la cellule.

Le pseudocode du déchiffrement d'une chaîne donne :

  • boucle sur la liste des clés pour retrouver la clé utilisée pour le chiffrement, d'après la référence contenue dans le cryptogramme passé en argument ;
  • décomposition de la clé en 4 clés de déchiffrement ;
  • calcul de la valeur de Q utilisée pour le chiffrement d'après Q' contenu dans le cryptogramme :
    Q = Q' - Entier((clé1 x clé2) / 1000) ;
  • calcul de l'entier Coef = (clé1 x clé2 x clé3 x clé4) / 400 ;
  • boucle sur le cryptogramme :

    • extraction des 4 octets codés à partir de l'entier enregistré,
    • incrémentation des 4 clés,
    • pour chacun des 4 octets : Opération XOR sur l'octet à décoder et le reste de (la clé de l'octet / 255), puis ajoute le caractère décodé au message déchiffré ou sort de la boucle si la valeur 1 est trouvée ;
  • fin de la boucle.

V. L'interface de l'application CryptoVBA

Vous trouverez en pièce jointe le fichier CryptoVBA pour EXCEL 2010 (version 32 bits, compatible 2016) qui assure les différents traitements dans une barre de menu personnelle « Compléments » (voir le tome 1 pour plus d'informations) :

Image non disponible

Au lancement de l'application, si aucune clé n'existe, une clé nommée CryptoVBA est créée automatiquement.
Vous pouvez ainsi commencer immédiatement vos chiffrements avec cette clé, ou utiliser le menu « Gestion des clés » puis « Générer une nouvelle clé pour chiffrer et déchiffrer » :
un formulaire s'ouvre pour renseigner le nom à donner à la clé.
Par exemple, Alice veut une clé pour que Bob puisse chiffrer les évaluations de ses élèves dans le tableau présenté en début de chapitre, elle saisit « Evaluation Bob » et clique sur le bouton « Valider ».

Image non disponible

Un formulaire indique la clé à communiquer à Bob qui devra chiffrer (ou déchiffrer) des cellules avec cette clé.

Image non disponible

Avec un copier/coller, Alice communique à Bob la clé secrète par messagerie sécurisée.

Les 4 premières valeurs forment la clé secrète, la dernière est la référence.

Une clé (préalablement sélectionnée) peut être communiquée à tout moment via le menu « Gestion des clés », puis « Communiquer la clé active à un autre utilisateur ».

Alice retrouvera cette clé dans la liste déroulante via le menu « Méthode Cryto », puis « Utiliser une Clé », ou via « Gestion des clés », puis « Utiliser une autre clé ».

Bob enregistre cette clé dans son classeur CryptoVBA en sélectionnant le menu « Gestion des clés », puis « Ajouter une clé qui vous a été communiquée » :

Image non disponible

Bob saisit un libellé lui permettant de reconnaître la clé à utiliser lorsqu'il chiffre les évaluations de ses élèves.
Puis il colle la clé que lui a communiquée Alice.

Image non disponible

Lorsque Bob clique sur « Valider », l'application lance un contrôle de cohérence de la clé en chiffrant puis déchiffrant un texte. La progression de ces traitements est affichée dans la barre de commande.

Image non disponible

La clé active est affichée dans le menu.

Bob retrouvera cette clé dans la liste déroulante des clés disponibles : soit en cliquant sur « Méthode Crypto », puis « Utiliser une Clé », soit en cliquant sur « Gestion des clés », « Utiliser une autre clé », soit en cliquant sur le bouton où est affiché le nom de la clé.

C'est par ces chemins qu'est sélectionnée la clé active. Cette clé sera utilisée pour le chiffrement, elle peut aussi être communiquée, renommée ou supprimée, via le menu « Gestion des clés » :

Image non disponible

Si le nom qu'il a donné à la clé ne lui convient plus, Bob pourra le modifier en sélectionnant le menu « Gestion des clés », puis « Modifier le nom de la clé active ».

Cette clé peut être supprimée en la sélectionnant dans la liste des clés disponibles (voir plus haut), puis en allant dans le menu « Gestion des clés », « Supprimer définitivement la clé active de la liste des clés ».

Image non disponible

Évidemment, une confirmation est demandée avant de supprimer une clé. S'il n'existe plus de clé dans l'application, une nouvelle clé nommée CryptoVBA sera automatiquement générée.

Pour chiffrer des cellules : Bob sélectionne les cellules concernées dans le classeur des évaluations (ici la plage C2:E3), choisit une clé dans la liste des clés disponibles, puis clique sur « Chiffrer la sélection ».
Les cellules chiffrées prennent la valeur « ### ». Le cryptogramme est enregistré dans le commentaire.

Image non disponible

Pour déchiffrer ces cellules : Alice sélectionne les cellules concernées dans le classeur (facilement repérables avec leur valeur à « ### » et leur commentaire) puis clique sur « Déchiffrer la sélection ».
Alice peut aussi sélectionner des cellules non chiffrées (voire toutes les cellules de la feuille avec les touches [Ctrl]+[A] ou le bouton « Sélectionner tout »), cela n'a pas d'incidence sur le traitement.
Ou ne sélectionner que les cellules chiffrées avec la clé active depuis le menu « Gestion des clés », puis « Sélectionner les cellules chiffrées avec la clé active ».

Image non disponible

Le déchiffrement ne nécessite pas de choisir au préalable la clé (ou les clés) à utiliser, car la bonne clé est recherchée dans la liste des clés disponibles.

Le traitement « visualiser une cellule » permet d'afficher le déchiffrement (et la clé utilisée) dans une boîte de message, sans affecter le contenu de la cellule :

Image non disponible

Ici la cellule D2, encore chiffrée, a été sélectionnée. Si la cellule contenait un commentaire, celui-ci serait affiché en clair à la suite du déchiffrement de la cellule.

Vous pouvez interrompre un traitement de chiffrement ou de déchiffrement en maintenant enfoncées les touches [Majuscule]+[Fin].

VI. Ça marche aussi pour les autres applications

Alice est dépitée : elle vient de lire sur les réseaux sociaux que des piratent peuvent lire le contenu de ses mails privés, car la messagerie de son opérateur n'offre pas d'option de chiffrement.
Il lui vient une idée, pourquoi ne pas utiliser CryptoVBA pour chiffrer ses messages personnels ?

Concrètement, Alice saisit en clair son courrier, sélectionne ce texte et fait un « copier » avec [Ctrl]+[C] pour l'insérer dans le presse-papiers, le code avec CryptoVBA qui va lire le presse-papiers au lieu de lire une cellule EXCEL, puis colle avec [Ctrl]+[V] le cryptogramme obtenu en remplacement de son message d'origine.
Le destinataire utilisera lui aussi CryptoVBA pour décoder le message.

Voici un exemple d'utilisation pour chiffrer un courrier qui ne doit en aucun cas tomber dans des mains indiscrètes :

Image non disponible

Alice saisit son courrier.
Sélectionne le texte et fait un « copier » avec [Ctrl]+[C].

Image non disponible

Dans CryptoVBA, Alice choisit une clé puis clique sur « Chiffrer le presse-papiers ».

Image non disponible

Une boîte l'informe que le contenu du presse-papiers a bien été codé.
Pour des raisons techniques, la taille maximale du texte à chiffrer est de 24 000 caractères.

Image non disponible

Alice retourne dans sa messagerie et colle avec [Ctrl]+[V] le cryptogramme obtenu.
Et envoie son courrier.

Quand Margaux reçoit ce cryptogramme, elle sélectionne le texte et fait un « copier » avec [Ctrl]+[C].
Et dans CryptoVBA, elle clique sur « Déchiffrer le presse-papiers » :

Image non disponible

Image non disponible

Une boîte affiche le cryptogramme déchiffré, qui est aussi placé dans le presse-papiers. Il pourra donc être collé dans une autre application avec [Ctrl]+[V].

La clé utilisée pour le déchiffrement est renseignée, ce qui permet également à Margaux de s'assurer de l'origine de l'émetteur.

Et si le courrier est vraiment très important, Alice peut effectuer un surchiffrement, c'est-à-dire chiffrer son message chiffré, avec le même algorithme, mais avec une autre clé. Casser le cryptogramme prendra alors deux fois plus de temps aux pirates.
Margaux aura juste à cliquer deux fois sur « Déchiffrer le presse-papiers ».

Évidemment, Alice doit avoir préalablement communiqué la clé secrète à Margaux.

Vous pouvez interrompre un traitement de chiffrement ou de déchiffrement du presse-papiers en maintenant enfoncées les touches [Majuscule]+[Fin].

VII. Ça marche aussi pour chiffrer ou déchiffrer un fichier

Alice veut allez plus loin : elle souhaite désormais chiffrer un fichier pour le diffuser à Bob.
Le menu propose la fonction « Chiffrer/Déchiffrer un fichier », qui ouvre une boîte de dialogue pour sélectionner un fichier :

Image non disponible

Deux cas sont possibles.

  • Sélection d'un fichier non chiffré : l'instruction Get du VBA permet de lire un fichier octet par octet. Les octets sont enregistrés par l'instruction Put après avoir été codés.
    Le fichier chiffré sera identifié par son extension « .Crypt ». Son en-tête contient le nombre utilisé pour le chiffrement, la référence de la clé pour permettre le déchiffrement sans avoir à sélectionner la clé dans la liste des clés disponibles, l'extension du fichier source.
  • Sélection d'un fichier chiffré reconnaissable par son extension « .Crypt » : l'en-tête du fichier permet de retrouver la clé à utiliser dans la liste des clés disponibles, ainsi que l'extension d'origine du fichier.

Image non disponible

La progression des traitements de chiffrement ou déchiffrement est affichée dans la barre de commande, suivie de l'estimation de la durée restante au format heures, minutes, secondes.

Vous pouvez interrompre un traitement de chiffrement ou de déchiffrement d'un fichier en maintenant enfoncées les touches [Majuscule]+[Fin].

VIII. Utiliser un mot de passe au lieu d'une clé

Alice n'a pas confiance en son administrateur système qui aurait la main sur son PC et pourrait lire en douce ses clés enregistrées dans CryptoVBA. Alors pour chiffrer ses données personnelles, elle préfère utiliser un mot de passe (c'est plus facile à se rappeler qu'une clé) qui ne sera pas enregistré dans la liste des clés et donc ne laissera pas de trace.

Dans le menu « Méthode Crypto », Alice sélectionne « Utiliser un Mot de passe ».
Un formulaire s'ouvre où Alice saisit un mot de passe (de 50 caractères au maximum).

Le mot de passe saisi est converti en clé : les trois premiers caractères sont utilisés pour calculer les valeurs de « clé1 » et « clé2 », les trois derniers pour les valeurs de « clé3 » et « clé4 ».
La référence de la clé est l'addition des codes ANSI du mot de passe. Ici « Margaux1501 » est transformé en clé « 7496013/5071218/3485745/3223605/924 ».

Image non disponible

À l'aide d'un dictionnaire numérique, un pirate peut facilement sélectionner l'ensemble des mots qui correspondent à la référence de la clé, et tenter de retrouver le mot de passe. Alice, qui est prudente, évite donc les mots communs comme mot de passe.

Image non disponible

Le menu indique qu'un mot de passe sera utilisé pour chiffrer ou déchiffrer, et non plus une clé enregistrée. Un clic sur ce bouton permet de saisir un autre mot de passe, ou passez par le menu « Méthode Crypto », « Utiliser un Mot de passe ».

Les traitements de chiffrement et déchiffrement des cellules, du presse-papiers, et des fichiers, sont identiques qu'avec l'utilisation d'une clé, et peuvent être interrompus avec [Majuscule]+[Fin] enfoncées.
Seules différences, les cellules chiffrées prennent la valeur « @@@ », et les traitements « visualiser une cellule » ou « Déchiffrer le presse-papiers » indiquent qu'un mot de passe a été utilisé :

Image non disponible

Pour déchiffrer des cellules, le presse-papiers ou des fichiers, le mot de passe doit avoir été saisi au préalable.

Image non disponible

Cliquez sur ce bouton pour ne sélectionner que les cellules chiffrées avec le mot de passe actif. Mais attention, un mauvais mot de passe mais qui donne la même référence de clé (l'addition des codes ANSI du mot de passe), dans notre exemple « Margaux0115 », sera accepté par l'algorithme, mais générera un déchiffrement erroné.

Pour revenir au chiffrement par clés, Alice choisit « Utiliser une clé » dans le menu « Méthode Crypto ».

IX. Lancer automatiquement CryptoVBA à l'ouverture d'EXCEL

Si vous utilisez souvent CryptoVBA, vous pouvez placer cette application dans le répertoire « démarrer » d'EXCEL nommé XLSTART, afin qu'elle se lance automatiquement à l'ouverture d'EXCEL.
Pour simplifier cette manipulation, vous pouvez passer par le menu « Gestion des clés » puis « Lancer automatiquement CryptoVBA à l'ouverture d'EXCEL ». Un formulaire s'ouvre :

Image non disponible

En cas d'échec de l'installation automatique, un message s'affiche et vous invite à installer manuellement CryptoVBA dans le répertoire XLSTART. Le fichier d'aide CryptoVBA.chm devra être installé dans un sous-répertoire de XLSTART à créer et à nommer AideCryptoVBA :

Image non disponible

Par la suite, l'ouverture d'EXCEL lancera automatiquement CryptoVBA, que vous pourrez activer en cliquant sur le bouton « CryptoVBA » dans la barre de menu personnelle « Compléments » :

Image non disponible

À tout moment, vous pouvez annuler cette installation dans le dossier de lancement automatique d'EXCEL et déplacer l'application dans le dossier de votre choix en utilisant le menu « Gestion des clés » puis « Ne plus lancer automatiquement CryptoVBA à l'ouverture d'EXCEL ».

X. Conclusion

Comme pour tout cryptosystème symétrique, CryptoVBA nécessite que les clés utilisées ne soient connues que de l'expéditeur et du destinataire. Il faut donc être en mesure de les diffuser et de les archiver en toute sécurité.

  • Les clés pourront être communiquées par messagerie sécurisée.
  • Le classeur CryptoVBA peut être protégé en ouverture (menu « Enregistrer sous », dans la liste déroulante « Outils », piochez « Options générales » et saisissez un mot de passe pour la lecture). Attention, il semble que les meilleurs pirates arrivent à craquer ce mot de passe.
  • Une fois le chiffrement terminé, une clé peut être supprimée si elle n'a plus à être utilisée.
  • Utiliser un mot de passe au lieu d'une clé permet de ne pas laisser de trace dans CryptoVBA.

Mais la principale faille de ce cryptosystème vient de son usage dans EXCEL : Alice travaillant avec un fichier partagé, cela implique qu'un utilisateur malintentionné, ou distrait, peut effacer une cellule chiffrée, la déplacer, voire copier une ancienne cellule et la coller à la place d'une autre. Pour éviter cela, trois parades existent :

  • mettre un mot de passe pour enregistrer le fichier (menu « Enregistrer sous », dans la liste déroulante « Outils », piochez « Options générales » et saisissez un mot de passe pour la modification).
    Mais attention aussi ici, car il semble que les meilleurs pirates arrivent à craquer ce mot de passe ;
  • sur le réseau partagé, n'habilitez qu'en lecture seule les utilisateurs ordinaires, et en lecture-écriture ceux qui peuvent chiffrer les données ;
  • le menu « Gestion des clés », « Sélectionner les cellules chiffrées avec la clé active » (ou le bouton « Sélectionner… » pour un mot de passe) permet d'afficher la valeur de chiffrement de la clé, c'est-à-dire le cumul des codes ANSI des cryptogrammes pondérés par les coordonnées des cellules. Le chiffreur peut communiquer cette valeur au déchiffreur qui va s'assurer, avant de déchiffrer, qu'elle est identique. Une différence signifiant qu'une modification a été effectuée sur les cellules chiffrées avec cette clé (modification, déplacement, suppression, ajout).

Attention : Si CryptoVBA permet d'améliorer la confidentialité d'un classeur EXCEL, cette application n'a pas vocation à remplacer un logiciel professionnel de chiffrement. Pour vos échanges hautement confidentiels, respectez les consignes de sécurité de votre administrateur système.

J'espère vous avoir transmis l'envie d'approfondir vos connaissances dans le domaine très riche et très intéressant de la cryptologie, et vous recommande l'excellent tutoriel de « ram-0000 » à cette adresse : « http://ram-0000.developpez.com/tutoriels/cryptographie/ ».

Les annexes qui suivent apporteront des informations complémentaires à ceux qui souhaitent plus de détails sur le code VBA.

Vous pouvez bien sûr utiliser CryptoVBA, ou modifier cette application pour l'adapter à vos besoins, ou simplement vous inspirer du code pour réaliser votre propre cryptosystème.

Laurent OTT. 2017

Annexe 1. La programmation VBA

Vous trouverez le code source de l'application CryptoVBA dans trois modules :

  • Crypto_Menu : contient le code pour la barre de menu personnalisée ;
  • Crypto_Systeme : contient le code du cryptosystème. Les fonctions sont lancées depuis la barre de menu personnalisée (ou d'après un autre classeur, voir l'annexe 4Annexe 4. Utiliser CryptoVBA dans un autre projet) ;
  • Crypto_Clavier : contient le code source pour chiffrer et déchiffrer le presse-papiers.

Ce quatrième mémento peut être considéré comme une mise en pratique des notions de base sur la programmation en VBA acquises dans le premier mémento, voir « http://laurent-ott.developpez.com/tutoriels/programmation-excel-vba-tome-1/ ».

Le code de cette application ne présentant pas de difficulté majeure et étant largement commenté, je n'ai donc repris dans cette annexe que les nouveautés.

- Split(expression[, delimiter[, limit[, compare]]]) : renvoie un tableau de base zéro (à une dimension) contenant les sous-chaînes issues de la chaîne expression, délimitées par delimiter.
L'exemple suivant transforme dans ListeNom(0 à 5) la chaîne des noms et des âges séparés par « / », et affiche l'âge de Margaux :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
Dim ListeNom() As String, i As Integer

ListeNom() = Split("Alice/25 ans/Bob/28 ans/Margaux/16 ans", "/")

For i = 0 To UBound(ListeNom) Step 2
    If ListeNom(i) = "Margaux" Then MsgBox ListeNom(i + 1)
Next i

- InstrRev(stringcheck, stringmatch[, start[, compare]]) : renvoie la position d'une occurrence d'une chaîne dans une autre, à partir de la fin de la chaîne. Alors que InStr([start, ]string1, string2[, compare]) renvoie la position de la première occurrence d'une chaîne à l'intérieur d'une autre chaîne.
Par exemple pour isoler le nom d'un fichier à partir du chemin complet :

  • InStrRev("C:\Formation_VBA\CryptoVBA.xlsm", "\") renvoie « 17 ».
  • Puis Mid("C:\Formation_VBA\CryptoVBA.xlsm", 17+1) renvoie « CryptoVBA.xlsm ».

- Shell(pathname[,windowstyle]) : lance le programme indiqué dans pathname (chemin plus nom et éventuellement les arguments).
Cette fonction peut aussi ouvrir un fichier en utilisant l'explorateur Windows (Windows Explorer en anglais) qui associe automatiquement l'application permettant l'ouverture, comme dans cet exemple où StrFichier contient le chemin et le nom d'un fichier « pdf » :

 
Sélectionnez
1.
Call Shell("explorer.exe " & StrFichier, vbNormalFocus)

Windowstyle peut prendre les valeurs suivantes :

  • vbHide : la fenêtre est masquée et activée ;
  • vbNormalFocus : la fenêtre est activée et rétablie à sa taille et à sa position d'origine ;
  • vbMinimizedFocus : la fenêtre est affichée sous forme d'icône et activée ;
  • vbMaximizedFocus : la fenêtre est agrandie et activée ;
  • vbNormalNoFocus : idem vbNormalFocus mais la fenêtre active reste active ;
  • vbMinimizedNoFocus : idem vbMinimizedFocus mais la fenêtre active reste active.

- IsEmpty : renvoie une valeur de type Boolean (True, False) indiquant si une variable a été initialisée.
Dans l'exemple suivant :

 
Sélectionnez
1.
2.
3.
4.
Dim Tableau() As String, Q As Variant

Tableau = Split("", "/")
Q = Tableau(0)

la lecture de la dernière ligne provoque une erreur « 9 : l'indice n'appartient pas à la sélection », et le traitement tombe. Pour éviter cela, il est possible d'utiliser l'instruction On Error Resume Next et de gérer l'état de la variable Q avec la fonction IsEmpty :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
Tableau = Split("", "/")
On Error Resume Next
Q = Tableau(0)
If IsEmpty(Q) = True Then 
    MsgBox "Tableau(0) est vide"
Else
    Votre traitement…
End if

- Is Nothing : permet de savoir si un objet est assigné (renseigné) ou pas.
Par exemple, si la cellule A1 ne contient pas de commentaire, l'instruction pour lire le texte du commentaire MsgBox Range("A1").Comment.Text provoque une erreur « 91 : Variable objet ou variable de bloc With non définie ». Pour éviter cela, il convient de tester au préalable si l'objet commentaire est renseigné :

 
Sélectionnez
1.
2.
3.
4.
5.
If Range("A1").Comment Is Nothing = True Then
    MsgBox "Pas de commentaire en A1"
Else
    MsgBox "Commentaire A1 : " & Range("A1").Comment.Text
End If

- Err.Raise Number : cette méthode permet de provoquer volontairement une erreur d'exécution.
Cela suppose que le code contient une gestion des erreurs.
Dans cet exemple une erreur est générée si un nombre aléatoire inférieur à 0,01 ou supérieur à 0,99 a été tiré au sort sur 100 essais et la suite du traitement n'est pas exécutée :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Dim i As Long

On Error GoTo Gest_Err
For i = 1 To 100
    If Rnd() < 0.01 Then Err.Raise vbObjectError + 513
    If Rnd() > 0.99 Then Err.Raise vbObjectError + 514
Next i

Suite du traitement…

Gest_Err:
Select Case Err.Number
    Case vbObjectError + 513: Debug.Print "< 0.01"
    Case vbObjectError + 514: Debug.Print "> 0.99"
    Case 0: Debug.Print "Pas d'erreur"
End Select

Pour comprendre le code qui génère un fichier chiffré, il faut étudier l'exemple suivant qui fait une copie d'un fichier binaire, ici le fichier d'aide de l'application :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
' Définition de la structure d'un fichier:
Type TypeRecordByte
    ID As Byte
End Type

'---------------------------------------------------------------------------------------
Private Sub CopieUnFichier()
'---------------------------------------------------------------------------------------
Dim FileNumberSource As Long, FileNumberDest As Long
Dim StrFichierSource As String, StrFichierDest As String
Dim RecordByte As TypeRecordByte
Dim i As Long

' Identification des fichiers source et destination:
StrFichierSource = "C:\Formation_VBA\CryptoVBA.chm"
StrFichierDest = "C:\Formation_VBA\Copie_CryptoVBA.chm"

' Ouverture du fichier source:
FileNumberSource = FreeFile
Open StrFichierSource For Random As #FileNumberSource Len = Len(RecordByte)

' Ouverture du fichier Destination:
FileNumberDest = FreeFile
Open StrFichierDest For Random As #FileNumberDest Len = Len(RecordByte)

' Boucle sur le fichier source:
For i = 1 To FileLen(StrFichierSource)
    
    ' Lecture de l'octet du fichier source:
    Get #FileNumberSource, , RecordByte
    
    ' Ecriture de cet octet dans le fichier destination:
    Put #FileNumberDest, , RecordByte
    
Next i

' Fermeture des deux fichiers:
Close #FileNumberSource
Close #FileNumberDest

End Sub

Quelques points nécessitent des précisions.

  • En principe le fichier source est le numéro 1 et le fichier destination est le numéro 2. Mais par précaution nous utilisons la fonction FreeFile qui retourne un numéro de fichier disponible.
  • La boucle For i = 1 To FileLen(StrFichierSource) permet de lire l'ensemble des octets lisibles du fichier source. Car la boucle Do While Not EOF(FileNumFichierSource) … Loop, fait copier un octet de trop : l'octet de fin de fichier du fichier source, auquel s'ajoute automatiquement l'octet de fin de fichier du fichier destination à sa fermeture.
  • Le type personnalisé TypeRecordByte permet une adaptation rapide du code à une autre situation.

Annexe 2. Les fonctions mathématiques de calcul de modulo

Vous trouverez ci-dessous les fonctions VBA qui permettent de calculer l'exponentiation modulaire d'un nombre sans dépasser les capacités de calcul d'EXCEL.
Sources : « http://fordom.free.fr/ ».

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
'-----------------------------------------------------------------
Function ExpoMod(ByVal Nb As Variant, ByVal Expo As Variant, _
ByVal Modulo As Variant) As Variant
'-----------------------------------------------------------------
' EXPONENTIATION MODULAIRE RAPIDE : Nb^Expo MOD Modulo.
'-----------------------------------------------------------------
' Convertit les variants en Decimal:
Nb = CDec(Nb): Expo = CDec(Expo): Modulo = CDec(Modulo)

' Traitement:
ExpoMod = 1
Do
    If MOD2(Expo, 2) = 1 Then
        ExpoMod = MODProd(Nb, ExpoMod, Modulo)
        Expo = (Expo - 1) / 2
        Nb = MODProd(Nb, Nb, Modulo)
    End If
    
If MOD2(Expo, 2) = 0 Then
        ExpoMod = MODProd(ExpoMod, 1, Modulo)
        Expo = Expo / 2
        Nb = MODProd(Nb, Nb, Modulo)
    End If

Loop Until Expo = 0
End Function


'-----------------------------------------------------------------
Function MOD2(ByVal d As Variant, ByVal n As Variant) As Variant
'-----------------------------------------------------------------
' Renvoie le modulo de d et n:
'-----------------------------------------------------------------
d = CDec(d): n = CDec(n)
MOD2 = CDec(d - n * Int(d / n))
End Function



'-----------------------------------------------------------------
Function IsMultiple(ByVal Nb1 As Variant, ByVal Nb2 As Variant) As Boolean
'-----------------------------------------------------------------
' Teste si Nb1 est multiple de Nb2.
'-----------------------------------------------------------------
Nb1 = CDec(Nb1): Nb2 = CDec(Nb2)
If Nb2 = 0 Then IsMultiple = True: Exit Function
IsMultiple = ((Int(Nb1 / Nb2) = Nb1 / Nb2) And Nb1 <> 0)
End Function

'-----------------------------------------------------------------
Function MODProd(ByVal Nb1 As Variant, ByVal Nb2 As Variant, _
ByVal Modulo As Variant) As Variant
'-----------------------------------------------------------------
' Renvoie le modulo du produit "nb1*nb2 MOD Modulo" sans la limite Double.
'-----------------------------------------------------------------
' Convertit les variants en Decimal et teste la grandeur du produit:
Nb1 = CDec(Nb1): Nb2 = CDec(Nb2): Modulo = CDec(Modulo)
If Nb1 * Nb2 < 10 ^ 15 Then MODProd = MOD2(Nb1 * Nb2, Modulo): Exit Function

' Paramètre les variables en Decimal:
Dim r As Variant, c As Variant, Facteur As Variant, d As Variant
r = CDec(r): c = CDec(c): Facteur = CDec(Facteur): d = CDec(d)

' Prend le mini => plus rapide:
If Nb1 < Nb2 Then r = Nb2: Nb2 = Nb1: Nb1 = r

' Optimisation facteur:
Facteur = 9
r = MOD2(Nb1, Modulo)
Do
    If IsMultiple(Nb2, Facteur) Then
        r = MOD2(Facteur * r, Modulo)
        Nb2 = Nb2 / Facteur
    Else
        d = MOD2(Nb2, Facteur)
        c = MOD2(c + r * d, Modulo)
        Nb2 = Nb2 - d
    End If
Loop Until Nb2 = 0
MODProd = MOD2(c, Modulo)
End Function


'---------------------------------------------------------------------------------------
Private Function InversMod(ByVal Nba As Variant, ByVal NbB As Variant) As Variant
'---------------------------------------------------------------------------------------
Dim a, b, Q, T, x, y

' Convertit les variants en Decimal:
a = CDec(NbB): b = CDec(Nba): Q = CDec(Q): T = CDec(T): x = CDec(x): y = CDec(y)

x = 1: y = 0
While (b <> 0)
    T = b
    Q = Int(a / T)
    b = a - Q * T
    a = T
    T = x
    x = y - Q * T
    y = T
Wend
InversMod = CDec(y)
If y < 0 Then InversMod = CDec(y + NbB)
End Function

Annexe 3. Code VBA d'un cryptosystème asymétrique adapté à EXCEL

Les pages qui suivent présentent le code source d'un cryptosystème asymétrique adapté aux capacités de calcul d'EXCEL.
Certaines fonctions mathématiques utilisées ici sont décrites à l'annexe 2Annexe 2. Les fonctions mathématiques de calcul de modulo.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
'---------------------------------------------------------------------------------------
Public Sub Calculer_Clés(ByRef Clé_Chiffrement As String, ByRef Clé_Déchiffrement As String)
'---------------------------------------------------------------------------------------
Dim p, Q, e, n, Qn, d, M, Chiffré, DéChiffré

' Initialise le générateur de nombres aléatoires.
Randomize Timer

' Boucle tant que les clés ne permettent pas un chiffrement/déchiffrement correct:
Do

    ' Choix de deux chiffres premiers maxi = 10^7 avec des Doubles ou 10^13 avec des Decimal)
    ' en utilisant le test de Miller-Rabin pour savoir si le nombre est premier:
    p = CDec(Int(Rnd() * 10 ^ 7))
    While TestMillerRabin(p) = False
        p = p + 1
    Wend
    Q = CDec(Int(Rnd() * 10 ^ 7))
    While TestMillerRabin(Q) = False
        Q = Q + 1
    Wend
      
' Calcul du module de chiffrement:
    n = CDec(p * Q)

' Calcul de la valeur de l'indicétrie d'Euler en n:
    Qn = CDec((p - 1) * (Q - 1))
    
' Choix de l'exposant de chiffrement.
    e = CDec(Int(Rnd() * (Qn / 2)))
    
' Calcul de l'exposant de déchiffrement:
    d = InversMod(e, Qn)
    
' Le message à coder en test:
    M = 512
    Chiffré = ExpoMod(M, e, n)
    DéChiffré = ExpoMod(Chiffré, d, n)
    
Loop While M <> DéChiffré

Clé_Chiffrement = CStr(n) & "C" & CStr(e)
Clé_Déchiffrement = CStr(n) & "D" & CStr(d)

End Sub

Pour savoir si un nombre est un nombre premier, nous utilisons le test de Miller Rabin dont voici le code issu de « http://fordom.free.fr/ » :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
'---------------------------------------------------------------------------------------
Private Function TestMillerRabin(ByVal n As Double) As Boolean
'---------------------------------------------------------------------------------------
' Test MILLER RABIN. Retourne Vrai si n est un nombre premier
'---------------------------------------------------------------------------------------
Dim a As Long, BaseMaxi As Long
Dim base

' Optimisation nb base à tester:
base = Array(2, 3, 5, 7, 11, 13, 17, 19, 23)
BaseMaxi = Int(4 + Log(n) / 8 - Abs(4 - Log(n) / 8))

' Algo:
a = 0
Do
    If IsMultiple(n, base(a)) = False Then
        If MillerRabin(n, base(a)) = False Then Exit Function
    End If
a = a + 1
Loop Until a > BaseMaxi

TestMillerRabin = True
End Function



'---------------------------------------------------------------------------------------
Private Function MillerRabin(ByVal n As Variant, ByVal a As Variant) As Boolean
'---------------------------------------------------------------------------------------
' RQ : IMPOSSIBILITE DE REPONDRE SI n multiple de a
'---------------------------------------------------------------------------------------
' Tests triviaux:
If MOD2(n, 2) = 0 Or n < 3 Then Exit Function

' Paramètres:
Dim h As Long, d As Variant, i As Long

' Convertit les variants en Decimal:
n = CDec(n): a = CDec(a): d = CDec(d)

' Calcul de n-1 = 2^h * d avec d impair:
Do
    h = h + 1
    d = (n - 1) / 2 ^ h
Loop Until d = Int(d) And MOD2(d, 2) = 1

' Test a^d=1 mod n:
MillerRabin = (ExpoMod(a, d, n) = 1)
If MillerRabin Then Exit Function

' Test s'il existe un 0<= i <= h-1 tel que a^(h*2^i)=-1 mod n:
For i = 0 To h - 1
    MillerRabin = (ExpoMod(a, d * 2 ^ i, n) = n - 1)
    If MillerRabin Then Exit For
Next i

End Function

Passez en arguments dans la fonction de chiffrement : la chaîne à chiffrer, la clé de chiffrement, une chaîne vide qui sera alimentée du cryptogramme obtenu. La fonction retourne « Vrai » si tout se passe bien :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
'---------------------------------------------------------------------------------------
Public Function Chiffrer_Chaine(ByVal Chaine As String, ByVal Clé_Chiffrement As String, _
                                ByRef Crypto As String) As Boolean
'---------------------------------------------------------------------------------------
Dim i As Integer, StrN As String, e, n, Chiffré, M

' Recherche la position du caractère C dans la clé:
On Error GoTo Ges_Err
i = InStr(1, Clé_Chiffrement, "C", vbTextCompare): If i = 0 Then Exit Function

' La partie de gauche représente n et celle de droite e:
n = CDec(Mid(Clé_Chiffrement, 1, i - 1))
e = CDec(Mid(Clé_Chiffrement, i + 1))

' Boucle sur la longueur de la chaîne pour chiffrer chaque caractère:
Crypto = ""
For i = 1 To Len(Chaine)
    M = Asc(Mid(Chaine, i, 1))
    Chiffré = ExpoMod(M, e, n)
    Crypto = Crypto & Chiffré & "/"
Next i

' Retourne Vrai si aucune erreur dans le traitement:
Ges_Err:
If Err.Number = 0 Then Chiffrer_Chaine = True
Err.Clear
End Function

Passez en arguments dans la fonction de déchiffrement : le cryptogramme à déchiffrer, la clé de déchiffrement, une chaîne vide qui sera alimentée de la chaîne déchiffrée obtenue. La fonction retourne « Vrai » si tout se passe bien :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
'---------------------------------------------------------------------------------------
Public Function Déchiffrer_Chaine(ByVal Chaine As String, ByVal Clé_Déchiffrement As String, _
                                  ByRef Crypto As String) As Boolean
'---------------------------------------------------------------------------------------
Dim i As Integer, StrN As String, Tableau() As String, ListeClé() As String
Dim d, n, DéChiffré, Chiffré

' Recherche la position du caractère D dans la clé qui doit être présent:
On Error GoTo Ges_Err
i = InStr(1, Clé_Déchiffrement, "D", vbTextCompare): If i = 0 Then Exit Function

' La partie de gauche représente n et celle de droite d:
n = CDec(Mid(Clé_Déchiffrement, 1, i - 1))
d = CDec(Mid(Clé_Déchiffrement, i + 1))

' Transforme la chaîne en un tableau:
Tableau = Split(Chaine, "/")

' Boucle sur la longueur du tableau pour déchiffrer chaque caractère à partir du 2e:
Crypto = ""
For i = 0 To UBound(Tableau) - 1
    Chiffré = CDec(Tableau(i))
    DéChiffré = ExpoMod(Chiffré, d, n)
    Crypto = Crypto & Chr(DéChiffré)
Next i

' Retourne Vrai si aucune erreur dans le traitement:
Ges_Err:
If Err.Number = 0 Then Déchiffrer_Chaine = True
Err.Clear
End Function

Annexe 4. Utiliser CryptoVBA dans un autre projet

Nous allons voir ici trois façons d'utiliser CryptoVBA pour chiffrer/déchiffrer des cellules préalablement sélectionnées ou pour chiffrer/déchiffrer un fichier, à partir d'un autre classeur EXCEL.
Pour simplifier les exemples, les fichiers et la clé sont passés « en dur », mais dans la pratique, vous utiliserez des variables ou des références aux cellules EXCEL.

1re façon, en ouvrant le fichier CryptoVBA.xlsm qui, dans cet exemple pour chiffrer des cellules, est situé dans le répertoire du classeur appelant. La clé de chiffrement est passée en argument de la méthode Run. Le principe est identique pour déchiffrer des cellules (avec Déchiffrer_Sélection) ou un fichier (avec DéchiffrerUnFichier) même si les exemples ne sont pas repris ci-dessous :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Sub ChiffrerSélection()

' Ouvre le fichier CryptoVBA.xlsm situé dans le répertoire du classeur actif:
Application.Cursor = xlWait
Workbooks.Open ThisWorkbook.Path & "\CryptoVBA.xlsm"

' Lance la macro de chiffrement:
Run "CryptoVBA.xlsm!Crypto_Systeme.Chiffrer_Sélection", _
    "5963556/484997/4717915/3002436/201705185996854"

' Ferme le fichier CryptoVBA.xlsm:
Workbooks("CryptoVBA.xlsm").Close Savechanges:=False
Application.Cursor = xlDefault
End Sub

Pour chiffrer un fichier, deux arguments sont nécessaires : le fichier à chiffrer, la clé de chiffrement.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Sub ChiffrerUnFichier()

Application.Cursor = xlWait
Workbooks.Open ThisWorkbook.Path & "\CryptoVBA.xlsm"

Run "CryptoVBA.xlsm!Crypto_Systeme.ChiffrerUnFichier", "C:\Formation_VBA\Démo1.xlsx", _
    "5963556/484997/4717915/3002436/201705185996854"

Workbooks("CryptoVBA.xlsm").Close Savechanges:=False
Application.Cursor = xlDefault
End Sub

La 2e façon consiste à référencer le fichier de macros complémentaires CryptoVBA.xlam comme une bibliothèque d'objets incluse au projet (voir le tome 1). Dans EXCEL 2010, depuis l'éditeur choisir le menu « Outils / Références… », cliquez sur « Parcourir » et sélectionnez CryptoVBA.xlam (fichier joint, voir l'annexe 5Annexe 5. Les fichiers joints). Les fonctions publiques de CryptoVBA sont alors disponibles (attention, n'utilisez pas Option Explicit dans le module contenant ces fonctions) ce qui donne en reprenant les deux exemples précédents :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Sub ChiffrerSélection()

Application.Cursor = xlWait
Call CryptoVBA.Chiffrer_Sélection("5963556/484997/4717915/3002436/201705185996854")
Application.Cursor = xlDefault
End Sub

Sub ChiffrerUnFichier()

Application.Cursor = xlWait
Call CryptoVBA.ChiffrerUnFichier("C:\Formation_VBA\Démo1.xlsx", _
"5963556/484997/4717915/3002436/201705185996854")
Application.Cursor = xlDefault
End Sub

La 3e façon est extraite de l'excellente documentation de SilkyRoad, à consulter à cette adresse : « http://silkyroad.developpez.com/VBA/VisualBasicEditor/ ».
Elle permet d'installer des macros complémentaires (puis de les désinstaller si vous le désirez) contenues dans un fichier « .xlam » en utilisant le VBA, donc sans manipulation de l'utilisateur.
Attention, n'utilisez pas Option Explicit dans le module contenant ces fonctions.

Ce code installe les macros complémentaires d'un fichier « .xlam ». Le premier argument est le fichier (chemin plus nom) dans notre cas CryptoVBA.xlam. Le deuxième argument est le nom du projet VBA défini dans ce fichier, dans notre cas CryptoVBA. La fonction retourne « Vrai » si l'installation est réussie :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
'---------------------------------------------------------------------------------------
Function RéférencesAjouterXLAM(StrFichierXLAM As String, StrRéférence As String) As Boolean
'---------------------------------------------------------------------------------------
' Retourne Vrai si la référence passée a été ajoutée au projet actif.
'---------------------------------------------------------------------------------------
On Error GoTo Gest_Err

' Si la référence est déjà présente, ne rien faire, sinon l'installer:
If RéférencesEstInstallée(StrRéférence) = False Then
    ThisWorkbook.VBProject.References.AddFromFile StrFichierXLAM
End If

Gest_Err:
If Err.Number = 0 Then RéférencesAjouterXLAM = True
Err.Clear
End Function

Ce code appelle la fonction RéférencesEstInstallée qui retourne « Vrai » si la référence (c'est-à-dire le nom du projet VBA contenant les macros complémentaires) est déjà installée dans le classeur actif :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
'---------------------------------------------------------------------------------------
Function RéférencesEstInstallée(StrRéférence As String) As Boolean
'---------------------------------------------------------------------------------------
' Retourne Vrai si la référence passée en argument est installée dans le projet actif.
'---------------------------------------------------------------------------------------
Dim i As Integer
For i = 1 To ThisWorkbook.VBProject.References.Count
    If ThisWorkbook.VBProject.References(i).Name = StrRéférence Then
        RéférencesEstInstallée = True: Exit For
    End If
Next i
End Function

La suppression d'une référence est tout aussi simple. L'argument est le nom de la référence, dans notre cas CryptoVBA :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
'---------------------------------------------------------------------------------------
Function RéférencesSupprimer(StrRéférence As String) As Boolean
'---------------------------------------------------------------------------------------
' Retourne Vrai si la référence passée a été désinstallée du projet actif.
'---------------------------------------------------------------------------------------
Dim i As Integer
For i = 1 To ThisWorkbook.VBProject.References.Count
    If ThisWorkbook.VBProject.References(i).Name = StrRéférence Then
        ThisWorkbook.VBProject.References.Remove ThisWorkbook.VBProject.References.Item(i)
        RéférencesSupprimer = True
        Exit For
    End If
Next i
End Function

Ci-dessous un exemple pour chiffrer des cellules sélectionnées (valeur à 1 pour l'argument de la procédure « ChiffrerOuDéchiffrer », même principe pour déchiffrer des cellules, chiffrer ou déchiffrer un fichier, en modifiant cet argument par respectivement 2, 3, et 4).
Attention, l'installation de la macro complémentaire doit se faire dans une procédure différente de la procédure qui utilise les fonctions de CryptoVBA. Ce qui est fait dans la procédure « Démonstration », qui appelle ensuite la procédure « ChiffrerOuDéchiffrer ».

La fonction MotDePasseEnClé(StrMDP As String) de CryptoVBA convertit un mot de passe passé en argument en clé utilisable par le cryptosystème, et retourne cette clé.

Ici CryptoVBA.xlam est dans le même répertoire que le classeur appelant et la clé est passée en dur, mais utilisez des variables ou des références aux cellules dans vos projets :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
'---------------------------------------------------------------------------------------
Sub Démonstration()
'---------------------------------------------------------------------------------------
' Si l'installation de la référence est réussie:
If RéférencesAjouterXLAM(ThisWorkbook.Path & "\CryptoVBA.xlam", "CryptoVBA") = True Then
    ' Chiffre les cellules sélectionnées :
    Call ChiffrerOuDéchiffrer(1, "Margaux1501")
    ' Supprime la référence:
    Call RéférencesSupprimer("CryptoVBA")
End If
End Sub

'---------------------------------------------------------------------------------------
Sub ChiffrerOuDéchiffrer(Action As Integer, ByVal Clé As String, Optional Fichier As String)
'---------------------------------------------------------------------------------------
' L'argument Action détermine le traitement à exécuter:
' 1 = Chiffrer les cellules sélectionnées, 2 = déchiffrer les cellules sélectionnées,
' 3 = Chiffrer un fichier, 4 = déchiffrer un fichier.
' Clé : clé ou mot de passe.
' Fichier : éventuellement le fichier à chiffrer ou déchiffrer.
'---------------------------------------------------------------------------------------
Dim Tableau() As String

' Transforme la clé en tableau pour voir si elle est exploitable ou si c'est un mot de passe:
Tableau = Split(Clé, "/")
If UBound(Tableau) <> 4 Then Clé = CryptoVBA.MotDePasseEnClé(Clé)

' Différentes actions possibles:
Application.Cursor = xlWait
Select Case Action
    Case 1: Call CryptoVBA.Chiffrer_Sélection(Clé)
    Case 2: Call CryptoVBA.DéChiffrer_Sélection(Clé)
    Case 3: Call CryptoVBA.ChiffrerUnFichier(Fichier, Clé)
    Case 4: Call CryptoVBA.DéChiffrerUnFichier(Fichier, Clé)
End Select

Application.Cursor = xlDefault
End Sub

Maintenir enfoncées les touches [Majuscule]+[Fin] permet d'interrompre ces traitements de chiffrement, déchiffrement.

Annexe 5. Les fichiers joints

  • CryptoVBA.xlsm : le fichier pour EXCEL 2010 (version 32 bits, compatible 2016). À son ouverture, pensez à activer les macros si nécessaire. Et vérifiez que l'option « Désactiver toutes les macros sans notification » n'est pas cochée dans le menu « Fichier / Options / Centre de gestion de la confidentialité / paramètres du Centre de gestion de la confidentialité / Paramètres des macros ».
    Ce fichier contient différents modules :

    • Crypto_Menu : contient le code pour la barre de menu personnalisée ;
    • Crypto_Système : contient le code du cryptosystème. Les fonctions sont lancées depuis la barre de menu personnalisée ;
    • Crypto_Clavier : contient le code source pour chiffrer et déchiffrer le presse-papiers.
  • CryptoVBA.xlam : le fichier des macros complémentaires si vous souhaitez chiffrer/déchiffrer des cellules ou des fichiers, en VBA, à partir d'un autre classeur que CryptoVBA.xlsm, voir l'annexe 4Annexe 4. Utiliser CryptoVBA dans un autre projet.
  • CryptoVBA.xls et CryptoVBA.xla : les fichiers pour la version EXCEL 97.
  • CryptoVBA.chm : le fichier d'aide de l'application et son fichier projet CryptoVBA.hnd.
  • Démo_Tome4.xlsm : le fichier pour EXCEL 2010 des exemples présentés dans ce mémento. Et aussi :

    • RSA : exemple d'un cryptosystème asymétrique ;
    • NP_Aléatoires : contient le code d'une fonction qui retourne un tableau (de n éléments) de nombres premiers compris aléatoirement entre 10.000 et 1015 ;
    • NP_Crible : contient le code d'une fonction qui permet de calculer les nombres premiers, jusqu'aux capacités de calcul d'EXCEL. Soit en utilisant les colonnes d'EXCEL (environ 15 à 20 colonnes suivants les ressources disponibles) pour stocker les nombres premiers, soit en utilisant des fichiers texte.

Exemple de configuration pour calculer les premiers 10 millions de nombres premiers dans 10 colonnes d'EXCEL de 1 million de lignes :

 
Sélectionnez
1.
2.
3.
4.
5.
Const MaxiColonne As Long = 10
Const NbColonneEXCEL As Long = 10
Const MaxiNP As Long = 

1000000

Exemple de configuration pour calculer les premiers 10 millions de nombres premiers dans 10 fichiers texte :

 
Sélectionnez
1.
2.
3.
Const MaxiColonne As Long = 10
Const NbColonneEXCEL As Long = 0
Const MaxiNP As Long = 1000000

Exemple de configuration pour calculer les premiers 100 millions de nombres premiers dans 100 fichiers texte, en reprenant les calculs à l'étape précédente où les 10 premiers millions ont déjà été calculés :

 
Sélectionnez
1.
2.
3.
4.
Const MaxiColonne As Long = 100
Const NbColonneEXCEL As Long = 0
Const MaxiNP As Long = 1000000 
Const ReprendDepuisColonne As Long = 10

Comptez environ 3 secondes pour calculer une série d'un million de nombres premiers et les enregistrer dans un fichier texte. Et entre 10 et 14 Mo d'espace sur le disque dur par fichier.

Remerciements

Je tiens à remercier Gaby277 pour ses nombreux conseils et pour sa rédaction du fichier d'aide, ainsi que Pierre Fauconnier, Arkham46, Lolo78 pour la relecture technique, Winjerome et Siguillaume pour la mise au gabarit et Claude Leloup pour la relecture orthographique.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2017 Laurent OTT. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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. Droits de diffusion permanents accordés à Developpez LLC.