CryptAfinity

  1. Description
    1. Auteurs
  2. Pré-requis
    1. Sur un système Debian GNU/Linux
    2. Sur un système Apple MacOSX (≥10.3)
    3. Sur un système Microsoft Windows
  3. Se procurer CryptAfinity
  4. Utiliser CryptAfinity
    1. Compilation
    2. Utilisation
  5. Documentation

1. Description

CryptAfinity est un logiciel libre permettant de déchiffrer des texte obfusqués par des systèmes Afines ou l'algorithme de Vigenère. Il possède les caractéristiques suivantes :

1.1. Auteurs

CryptAfinity a été entièrement réalisé par Glenn ROLLAND <glenux@fr.st> à l'occasion de travaux pratiques du cours de système du Master 2 Ingénierie Informatique - Systèmes, Réseaux et Internet.

2. Pré-requis

CryptAfinity nécessite les bibliothèques de fonctions suivantes (dans leur version de développement si compilez le programme vous-même):

2.1. Sur un système Debian GNU/Linux

Il vous suffit de taper (en tant qu'administrateur) les commandes suivantes pour installer le nécessaire: 

# apt-get install libglib-2.0-dev

2.2. Sur un système Apple MacOS X (>= 10.3)

Il est nécessaire d'avoir installé les autotools (automake, autoconf...) dans leur dernière version. À partir de là, il suffit de taper les commandes suivantes dans un terminal :

# sudo fink install glib2-dev

2.3. Sur un système Microsoft Windows

Cela ne fut pas (encore) testé, mais il est très probable que cela fonctionne sous Cygwin.

3. Se procurer CryptAfinity

Vous pouvez télécharger la dernière archive des sources, ou bien directement la version la plus récente du projet sur le dépôt Subversion du projet.

3.1. L'archive des sources

Elle est disponible à l'adresse :

http://glenux2.free.fr/pub/projets/CryptAfinity/archives/

3.2. Le dépôt Subversion

Afin d'obtenir les sources les plus à jour, vous pouvez utiliser le logiciel de contrôle de sources Subversion

$ svn checkout http://repository.glenux.ath.cx/svn/CryptAfinity/

Il n'y a pas de mot de passe, il suffit donc de presser la touche "Entrée" pour l'utilisateur "anonymous", si ce dernier vous est demandé.

4. Utiliser CryptAfinity

4.1. Compilation

Commencez par décompressez l'archive.

$ tar -xzvf CryptAfinity-0.1.tar.gz

Rendez vous ensuite dans le dossier qui vient d'être créé lors de la décompression.

$ cd CryptAfinity-0.2

Puis lancez l'auto-configuration du logiciel, puis la compilation.

$ ./autogen
$ ./configure
$ make

Le programme sous forme binaire se trouvera alors dans le sous-dossier src/tools/, sous le nom break_afinity

4.2. Utilisation

CryptAfinity nécessite de nombreux paramètres, avec la syntaxe suivante:

Usage: break_afinity -a <fichier> -e <float> -f <float> -p <fichier> -t <fichier> -m

Où les paramètres sont les suivants:      

-a, --alphabet <file>  Fichier contenant les lettres de l'alphabet, dans l'ordre.

-e, --epsilon <float>
Tolerance pour le test des clefs.
-f, --frequencies <float> Proportion moyenne que représentent les 9 lettres "prioritaires" dans le texte clair.
-k, --keylength <int>       Taille de la clef maximul (obsolète)
-p, --priorities <file> Lettres ordonnées par fréquence décroissante d'apparition dans le texte clair.
-t, --text <file> Fichier contenant le texte chiffré.
-m, --mode <a|v> Selection du mode "Afine" ou "Vigenère"

5. Documentation

5.1. Code

Vous pouvez trouver la documentation du code de CryptAfinity dans le dossier doc/html de l'application, ou en suivant ce lien.

5.2. Principe du "décodeur Afine"

On génère l'espace des clefs possibles pour l'alphabet donné en entrée:

int alpha_size; //taille de l'alphabet
std::list<int> orb; // nombre premiers avec alpha_size
MathTools mt; // bibliotheque d'outils mathématiques
std::list<KeyAfine> keyList;
std::list<int>::iterator orbIt;

for (i=1; i<alpha_size; i++){
    if (mt.pgcd(i, alpha_size) == 1) {
        orb.push_back(i);
    }
}
// 1 - générer l'espace des 312 clefs
for (orbIt = orb.begin(); orbIt != orb.end(); orbIt++){
    KeyAfine key;
    key.setCoefA((*orbIt));
    for (i=0; i<alpha_size; i++){
        key.setCoefB(i);
        keyList.push_back(key);
    }
}

Puis on fait une attaque par analyse de fréquence sur les textes obtenus par "décodage" du texte chiffré avec les clefs essayées.

float frequencies; // fréquence cumulée des 9 lettres les plus présentes
float epsilon; // marge d'erreur

std::list<KeyAfine>::iterator kLIt;
for (kLIt = keyList.begin(); kLIt != keyList.end(); kLIt++){
    float score = 0;
    printf("Trying key %s\n", (*kLIt).toString().c_str());

    plainText = codec.decode(cypherText, *kLIt);   
    plainText.setAlphabet(this->_config.getAlphabet());
    for (int i=0; i<9; i++){
        score += plainText.getCountOf(prio_conf[i]);
    }
    score = score / plainText.size();
    if (fabs(score - frequencies) < epsilon){
      printf("KEY = %s\n",(*kLIt).toString().c_str());
      printf("PLAIN TEXT(%f) = %s\n", fabs(score-frequencies),
        plainText.toAlphabet().c_str());
    }

}

5.3. Principe du "décodeur Vigenère"

On commence par faire récupérer les groupes de caratères qui se répètent dans le texte.

Une fois obtenue plusieurs groupes de lettres, on regarde la distance séparrant les deux premiers groupes (note d1) puis la distance entre les deux suivant (d2). Le PGCD de d1 et d2, doit donner un multiple de la longueur de la clef. L'hypothèse sous-jacente est que ces groupes de lettres sont issue du chiffrement des mêmes bouts de mots avec les mêmes bouts de la clef. Si le PGCD = 1 on peut raisonnablement supposer que ce n'est pas le cas.

L'étape suivante consiste à faire une analyse de fréquence en découpant le texte en un nombre de colonne correspondant au pgcd précédemment calculé. On tire de cette analyse de fréquence, un ordre de lettre par importance. Puis en fonction de données statistiques préalables correspondant au contexte connu à prioris du texte clair que l'on veut décrypter, on essaie de faire correspondre les lettres les plus souvent vu dans le texte avec le modèle de fréquence.

Ceci nous donne un ensemble de clef (réduit à un ou pas), dans lequel se trouve normalement la bonne clef.