Version:0.9 StartHTML:0000000105 EndHTML:0000091588 StartFragment:0000000152 EndFragment:0000091554
TP n°2 de Cryptographie
 
 
PRESENTATION GENERALE DE L’ALGORITHME
DATA ENCRYPTION STANDARD
 
 
 
 
 
LUP SQT – Novembre 2004
 
 
 
 
 
Julien VEHENT
 
 
 
 
PRESENTATION 
 

En 1977, le Bureau Fédéral des Standards des États-Unis (US Fédéral Bureau of Standards) a approuvé un algorithme cryptographique conçu par la firme IBM pour la sécurité des données. Le Standard de Codage des Données (DES, Data Encryption Standard) a été approuvé uniquement pour des documents non classés secret-défense. Depuis lors, le DES a été largement adopté dans l'industrie du matériel cryptographique (processeur de cryptage), mais également dans l’industrie du logiciel où l'algorithme peut être implanté en un nombre limité de lignes de codes.

 

DES est un algorithme de cryptage rapide lorsqu’il est implanté matériellement. Aujourd’hui, il peut être cassé en un minimum de temps avec des moyens appropriés, comme le montre le résultat du dernier DES challenge animé par RSA Security.

 

On voit en effet que le groupe « Electronix Frontier Foundation » à cassé le code en 22 heures et 15 minutes en janvier 1999. DES n’est donc plus un système de cryptographie à toute épreuve, c’est pourquoi il a été remplacé par Advanced Encryption Standard en 2001.

 

La derniére spécification de DES est la Federal Information Processing Standards Publication n° 46-3 (FIPS46-3) datée du 25 octobre 1999. Il est peu probable de voir évoluer DES à l’avenir, étant donné son remplacement par AES.

 

 

Voici un extrait d’article qui retrace le parcours de DES :

« Dans les laboratoires secrets du gouvernement, lors de la Seconde Guerre mondiale, la cryptographie est entrée dans l’ère de l’informatique et a intégré les mathématiques. Toutefois, aucun professeur n’enseignant cette discipline et aucune conférence n’y étant consacrée, toutes les recherches américaines en la matière étaient menées à la National Security Agency (NSA).

A cette époque où l’internet n'était qu’une simple curiosité, la cryptographie n’était même pas une branche reconnue des mathématiques. C’est alors que le DES a fait son apparition.

Pour le début des années 1970, l’idée était révolutionnaire. Le NBS réclamait un standard de chiffrement gratuit. Comme le Bureau souhaitait que ce standard ne soit pas militaire, il s’est adressé au public pour la création d’algorithmes de chiffrement. Le NBS n’a reçu qu’un seul candidat sérieux: DES, provenant de recherches des laboratoires d’IBM. En 1976, celui-ci est devenu l’algorithme de chiffrement officiel du gouvernement américain pour les communications "sensibles mais non classées secrètes". Celles-ci incluaient par exemple des informations d’ordre personnel, financier et logistique. […] Lorsque IBM l’a proposé comme standard, personne ne disposait du savoir-faire pour l’analyser, excepté la NSA. Elle a apporté deux changements au DES: elle a adapté l’algorithme et réduit de plus de moitié la longueur de la clé.[…]

Les modifications apportés par la NSA ont provoqué un tollé parmi les rares personnes à y prêter attention. Elles furent choquées à la fois par "l'emprise invisible" de la NSA (les changements n’ont pas été rendus publics et aucune explication n’a été donnée quant à la forme finale de l’algorithme), et par la longueur réduite de la clé.

Toutefois, ce tollé s’est accompagné de recherche scientifique. Il n’est pas exagéré d'affirmer que la publication du DES a donné naissance à la cryptographie en tant que discipline académique moderne. Les premiers cryptographes universitaires ont commencé leur carrière en essayant de casser le DES ou, du moins, en essayant de comprendre les modifications apportées par la NSA.

Quasiment tous les algorithmes de chiffrement (en particulier ceux utilisés par la cryptographie "à clé publique" [utilisé par le fameux PGP]) peuvent retracer leurs origines jusqu'au DES »

 

Passons maintenant à l’analyse de l’algorithme DES :

 

 

TRAITEMENT DU TEXTE CLAIR

DES crypte des blocks de texte de 64 bits avec une clé de 56 bits. Cette derniére est réduite à deux parties de 24bits, soit 48 bits, pour le traitement dans l’algorithme.

La figure ci-dessous permet de visualiser le travail effectué sur le block de texte clair de 64 bits.

 

I)                  Le texte clair est permuté, c'est-à-dire que l’ordre des bits est réagencé selon une table définie dans le code. Le résultat est séparé en deux parties, que nous nommerons Gauche et Droite, de 32 bits.

---ENTREE DANS LES ITERATIONS, AU NOMBRE DE 16---

II)               La partie de droite est stockée pour devenir la partie de gauche de l’itération suivante.

 

III)            La partie de droite est expansée à 48 bits grâce à une table définie dans le code qui repète certains bits.

 

IV)             La partie de droite et la clé effectuent un XOR.

 

V)                Le block de 48 bits en sortie du XOR est envoyé dans les S-Box. Le fonctionnement des S-Box sera détaillé plus tard.

 

VI)             Le block de 32 bits en sortie des S-Box est permuté, le principe est le même que pour la permutation initiale mais la table change.

 

VII)          Ce dernier effectue un XOR avec la partie de gauche et le résultat deviens la partie de droite de l’itération suivante, qui commence juste après cette étape.

 
 
            A la fin de la 16éme itération, les deux parties sont concaténées et le block de 64bits obtenus est permutés avant d’être sorti du 
programme.
 
            En ce qui concerne le déchiffrage :
Si on considére l’entrée du 16éme étage de déchiffrage. On sais que G16 = D15 et que D16 = G16 XOR f(R15,K15). 
Selon les propriétés de l’algorithme, on démontre que la sortie du 1er étage de décryptage est égale au 32bits inversé de l’entrée du 16éme étage de cryptage.
 
 
            LA PERMUTATION INITIALE
 
                        static int table_DES_IP[64] = {
                       39,  7, 47, 15, 55, 23, 63, 31,
                       38,  6, 46, 14, 54, 22, 62, 30,
                       37,  5, 45, 13, 53, 21, 61, 29,
                       36,  4, 44, 12, 52, 20, 60, 28,
                       35,  3, 43, 11, 51, 19, 59, 27,
                       34,  2, 42, 10, 50, 18, 58, 26,
                       33,  1, 41,  9, 49, 17, 57, 25,
                       32,  0, 40,  8, 48, 16, 56, 24
                       };
 
La séquence en entrée est un block de 64 bits. Lors de la permutation initiale, les bits sont réagencés en suivant la table ci-dessus. 
C’est-à-dire que le bits numéro 39 passe en premiére position, suivi du bits numéro 7, puis du bits numéro 47, etc…..
 
            La FIPS46-3 définit une table de permutation différente de celle utilisée dans le code source ici étudiée, mais le principe est 
exactement le même.
 
            Après cette permutation, le block est séparé en deux block de 32 bits. Par rapport au block initial, les block « D » et « G » seront 
donc les bits suivant :
 
            G :        39,  7, 47, 15, 55, 23, 63, 31,                       D :        35,  3, 43, 11, 51, 19, 59, 27,
               38,  6, 46, 14, 54, 22, 62, 30,                              34,  2, 42, 10, 50, 18, 58, 26,
               37,  5, 45, 13, 53, 21, 61, 29,                              33,  1, 41,  9, 49, 17, 57, 25,
               36,  4, 44, 12, 52, 20, 60, 28,                              32,  0, 40,  8, 48, 16, 56, 24
 
 
 
        L’EXPANSION DE 32 à 48 BITS
 
            Le block D est expansé à 48 bits être de même taille que la clé. Cette expansion est réalisée en en répétant certains bits de l’ancien 
block dans le nouveau block.
 
 
static int table_DES_E[48] = {
    31,  0,  1,  2,  3,  4,  3,  4,
     5,  6,  7,  8,  7,  8,  9, 10,
    11, 12, 11, 12, 13, 14, 15, 16,
    15, 16, 17, 18, 19, 20, 19, 20,
    21, 22, 23, 24, 23, 24, 25, 26,
    27, 28, 27, 28, 29, 30, 31,  0
};
 
            Dans le tableau ci-dessus, les chiffres en rouges sont les chiffres répétés. Ils sont au nombre de 16 pour passer de 32 à 48 bits. 
            Cette table n’est pas celle de la FIPS46-3 mais le principe est le même.
 
 
            LES S-BOX
 
            Les S-Box sont aux nombres de 8. Chacune d’elle acceptent un nombre sur 6 bits en entrée, ce qui signifie que l’on traite un nombre 
de 48 bits (8*6).
 
Ce nombre binaire est décomposé. Les bits respectivement plus fort et plus faible sont utilisées pour repérer une ligne, les 4 bits 
centraux repèrent un colonne.
On obtient une coordonnée dans un tableau.
 
Ces tableaux contiennent des nombres sur 4 bits (entre 0 et 15) qui seront les valeurs en sortie des S-Box.
 
Ex :       101101
 
 
            Les bits en rouges sont la référence de ligne, soit 11 ou, en entier, le nombre 3.
            Les bits en bleu sont la référence de colonne, soit 0110 ou, en entier, le nombre 6.
 
            Maintenant considérons la table suivante, définie dans le code source de DES :
 
            /* table S[0] */
00..........{.13,  1,  2, 15,  8, 13,  4,  8,  6, 10, 15,  3, 11,  7,  1,  4,
01...........10, 12,  9,  5,  3,  6, 14, 11,  5,  0,  0, 14, 12,  9,  7,  2,
10...........7,  2, 11,  1,  4, 14,  1,  7,  9,  4, 12, 10, 14,  8,  2, 13,
11-------> 0, 15,  6, 12, 10,  9, 13,  0, 15,  3,  3,  5,  5,  6,  8, 11  },
..............................................||             
..............................................||
............................................0110
 
        On recherche dans la table la ligne correspondant à nos coordonnées. On tombe ici sur le chiffre 13 soit 1101 en binaire.
 
            Chaque S-Box possédent un tableau qui lui est propre. Ici, les tableaux ne sont pas ceux de la FIPS 46-3.
 
 
 

TRAITEMENT DE LA CLE

La clé, d’une longueur de 56 bits, est tout d’abord permutée (permutation de choix 1) via une table, comme pour le texte clair. Elle est ensuite séparée en deux blocks de 28 bits. Ces blocks subissent un « Left Shift » c'est-à-dire un décalage des bits à gauche. Dans notre code source, le décalage est de 1 ou 2 bits suivant le round dans lequel on se trouve.

Ces deux parties « Shiftées » sont stockées pour servir à l’itération suivante (oû elles subiront encore un « Left Shift »).

Dans l’itération en cours, Les deux blocks sont concaténées pour effectuer une permutation de choix 2. Lors de cette permutation, la taille du block est réduite de 56 à 48 bits

static int table_DES_PC2[48] = {
    24, 27, 20,  6, 14, 10,  3, 22,
     0, 17,  7, 12,  8, 23, 11,  5,
    16, 26,  1,  9, 19, 25,  4, 15,
    54, 43, 36, 29, 49, 40, 48, 30,
    52, 44, 37, 33, 46, 35, 50, 41,
    28, 53, 51, 55, 32, 45, 39, 42
};
 
Pour effectuer cette réduction, certains bits sont tout simplement supprimés. Ainsi, dans le tableau ci-dessus, les bits 
{2 ; 13 ; 18 ; 21 ; 31 ; 34 ; 38 ; 47 }
sont supprimés.
 
Le résultat de cette fonction effectue un XOR avec le block de texte clair de 48 bits (étape IV).
 
 
 
 
 

CODE SOURCE

Le code source ci-dessous reprend les points vu ci-dessus. Les opérations d’une itération de cryptage sont contenu dans une boucle « for » qui va de 0 à 15, soit 16 itérations.

 
 
 
 
 
/*****************************************************************************
 * des.c                                                                     *
 *                 Software Model of ASIC DES Implementation                 *
 *                                                                           *
 *   Written 1995-8 by Cryptography Research (http://www.cryptography.com)   *
 *   Original version by Paul Kocher. Placed in the public domain in 1998.   *
 *  THIS IS UNSUPPORTED FREE SOFTWARE. USE AND DISTRIBUTE AT YOUR OWN RISK.  *
 *                                                                           *
 *  IMPORTANT: U.S. LAW MAY REGULATE THE USE AND/OR EXPORT OF THIS PROGRAM.  *
 *                                                                           *
 *****************************************************************************
 *
 ******************************************************************************
 *Notes pour l'implémentation                                                 *
 *                                                                            *
 *     Cette implémentation de DES adhére aux spécifications de la "FEDERAL   *
 *  INFORMATION PROCESSING STANDARDS PUBLICATION" numéro 46-3 et produit des  *
 *     sorties standards. L'opération interne de l'algorithme est légèrement  *
 *    différentes de la FIPS46. Par exemple, les Sbox ont étaient réarrangées *
 *  pour simplifier l'implémentation et de nombreuses permutations ont étaient*
 *  modifiées.                                                                *
*****************************************************************************/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "des.h"
 
 
static void ComputeRoundKey(bool roundKey[56], bool key[56]);
static void RotateRoundKeyLeft(bool roundKey[56]);
static void RotateRoundKeyRight(bool roundKey[56]);
static void ComputeIP(bool L[32], bool R[32], bool inBlk[64]);
static void ComputeFP(bool outBlk[64], bool L[32], bool R[32]);
static void ComputeF(bool fout[32], bool R[32], bool roundKey[56]);
static void ComputeP(bool output[32], bool input[32]);
static void ComputeS_Lookup(int k, bool output[4], bool input[6]);
static void ComputePC2(bool subkey[48], bool roundKey[56]);
static void ComputeExpansionE(bool expandedBlock[48], bool R[32]);
static void DumpBin(char *str, bool *b, int bits);
static void Exchange_L_and_R(bool L[32], bool R[32]);
 
static int EnableDumpBin = 0;
 
 
 
/**********************************************************************/
/*                                                                    */
/*                            DES TABLES                              */
/*                                                                    */
/**********************************************************************/
 
 
/*
 *  IP: Output bit table_DES_IP[i] equals input bit i.
 *
 *  Permutation initiale: les bits du block de texte clair
 *  sont réarrangés selon la table ci-dessous
 */
static int table_DES_IP[64] = {
    39,  7, 47, 15, 55, 23, 63, 31,
    38,  6, 46, 14, 54, 22, 62, 30,
    37,  5, 45, 13, 53, 21, 61, 29,
    36,  4, 44, 12, 52, 20, 60, 28,
    35,  3, 43, 11, 51, 19, 59, 27,
    34,  2, 42, 10, 50, 18, 58, 26,
    33,  1, 41,  9, 49, 17, 57, 25,
    32,  0, 40,  8, 48, 16, 56, 24
};
 
 
/*
 *  FP: Output bit table_DES_FP[i] equals input bit i.
 *
 *  Permutation Finale: Le block de 64 bits en sorties
 *  des 16 itérations est réarrangé comme ci-dessous
 */
static int table_DES_FP[64] = {
    57, 49, 41, 33, 25, 17,  9,  1,
    59, 51, 43, 35, 27, 19, 11,  3,
    61, 53, 45, 37, 29, 21, 13,  5,
    63, 55, 47, 39, 31, 23, 15,  7,
    56, 48, 40, 32, 24, 16,  8,  0,
    58, 50, 42, 34, 26, 18, 10,  2,
    60, 52, 44, 36, 28, 20, 12,  4,
    62, 54, 46, 38, 30, 22, 14,  6
};
 
 
/*
 *  PC1: Permutation choice 1, used to pre-process the key
 *
 *  Permutation des bits sur la clé de 56 bits
 */
static int table_DES_PC1[56] = {
    27, 19, 11, 31, 39, 47, 55,
    26, 18, 10, 30, 38, 46, 54,
    25, 17,  9, 29, 37, 45, 53,
    24, 16,  8, 28, 36, 44, 52,
    23, 15,  7,  3, 35, 43, 51,
    22, 14,  6,  2, 34, 42, 50,
    21, 13,  5,  1, 33, 41, 49,
    20, 12,  4,  0, 32, 40, 48
};
 
 
/*
 *  PC2: Map 56-bit round key to a 48-bit subkey
 *
 *  Substitution de la clé de 56 bits par une clé de 48
 *  bits. Les bits qui ne sont pas dans la table ne
 *  sont pas utilisés
 */
static int table_DES_PC2[48] = {
    24, 27, 20,  6, 14, 10,  3, 22,
     0, 17,  7, 12,  8, 23, 11,  5,
    16, 26,  1,  9, 19, 25,  4, 15,
    54, 43, 36, 29, 49, 40, 48, 30,
    52, 44, 37, 33, 46, 35, 50, 41,
    28, 53, 51, 55, 32, 45, 39, 42
};
 
 
/*
 *  E: Expand 32-bit R to 48 bits.
 *
 *  Expansion de la partie droite du texte clair 
 *  de 32 bits à 48 bits.
 *  Les bits sont utilisés plusieurs fois pour
 *  arriver à  48 bits.
 */
 
static int table_DES_E[48] = {
    31,  0,  1,  2,  3,  4,  3,  4,
     5,  6,  7,  8,  7,  8,  9, 10,
    11, 12, 11, 12, 13, 14, 15, 16,
    15, 16, 17, 18, 19, 20, 19, 20,
    21, 22, 23, 24, 23, 24, 25, 26,
    27, 28, 27, 28, 29, 30, 31,  0
};
 
 
/*
 *  P: Permutation of S table outputs
 *
 *  Permutation en sortie des S-Box
 */
static int table_DES_P[32] = {
    11, 17,  5, 27, 25, 10, 20,  0,
    13, 21,  3, 28, 29,  7, 18, 24,
    31, 22, 12,  6, 26,  2, 16,  8,
    14, 30,  4, 19,  1,  9, 15, 23
};
 
 
/*
 *  S Tables: Introduce nonlinearity and avalanche
 *
 *  Définition des S-Box.  Au nombre de 8, Elles permettent
 *  de faire correspondre une sortie sur 32 bits à 
 *  une entrée sur 48 bits.
 *  
 */
static int table_DES_S[8][64] = {
 
    /* table S[0] */
        {   13,  1,  2, 15,  8, 13,  4,  8,  6, 10, 15,  3, 11,  7,  1,  4,
            10, 12,  9,  5,  3,  6, 14, 11,  5,  0,  0, 14, 12,  9,  7,  2,
             7,  2, 11,  1,  4, 14,  1,  7,  9,  4, 12, 10, 14,  8,  2, 13,
             0, 15,  6, 12, 10,  9, 13,  0, 15,  3,  3,  5,  5,  6,  8, 11  },
 
    /* table S[1] */
        {    4, 13, 11,  0,  2, 11, 14,  7, 15,  4,  0,  9,  8,  1, 13, 10,
             3, 14, 12,  3,  9,  5,  7, 12,  5,  2, 10, 15,  6,  8,  1,  6,
             1,  6,  4, 11, 11, 13, 13,  8, 12,  1,  3,  4,  7, 10, 14,  7,
            10,  9, 15,  5,  6,  0,  8, 15,  0, 14,  5,  2,  9,  3,  2, 12  },
 
    /* table S[2] */
        {   12, 10,  1, 15, 10,  4, 15,  2,  9,  7,  2, 12,  6,  9,  8,  5,
             0,  6, 13,  1,  3, 13,  4, 14, 14,  0,  7, 11,  5,  3, 11,  8,
             9,  4, 14,  3, 15,  2,  5, 12,  2,  9,  8,  5, 12, 15,  3, 10,
             7, 11,  0, 14,  4,  1, 10,  7,  1,  6, 13,  0, 11,  8,  6, 13  },
 
    /* table S[3] */
        {    2, 14, 12, 11,  4,  2,  1, 12,  7,  4, 10,  7, 11, 13,  6,  1,
             8,  5,  5,  0,  3, 15, 15, 10, 13,  3,  0,  9, 14,  8,  9,  6,
             4, 11,  2,  8,  1, 12, 11,  7, 10,  1, 13, 14,  7,  2,  8, 13,
            15,  6,  9, 15, 12,  0,  5,  9,  6, 10,  3,  4,  0,  5, 14,  3  },
 
    /* table S[4] */
        {    7, 13, 13,  8, 14, 11,  3,  5,  0,  6,  6, 15,  9,  0, 10,  3,
             1,  4,  2,  7,  8,  2,  5, 12, 11,  1, 12, 10,  4, 14, 15,  9,
            10,  3,  6, 15,  9,  0,  0,  6, 12, 10, 11,  1,  7, 13, 13,  8,
            15,  9,  1,  4,  3,  5, 14, 11,  5, 12,  2,  7,  8,  2,  4, 14  },
 
    /* table S[5] */
        {   10, 13,  0,  7,  9,  0, 14,  9,  6,  3,  3,  4, 15,  6,  5, 10,
             1,  2, 13,  8, 12,  5,  7, 14, 11, 12,  4, 11,  2, 15,  8,  1,
            13,  1,  6, 10,  4, 13,  9,  0,  8,  6, 15,  9,  3,  8,  0,  7,
            11,  4,  1, 15,  2, 14, 12,  3,  5, 11, 10,  5, 14,  2,  7, 12  },
 
    /* table S[6] */
        {   15,  3,  1, 13,  8,  4, 14,  7,  6, 15, 11,  2,  3,  8,  4, 14,
             9, 12,  7,  0,  2,  1, 13, 10, 12,  6,  0,  9,  5, 11, 10,  5,
             0, 13, 14,  8,  7, 10, 11,  1, 10,  3,  4, 15, 13,  4,  1,  2,
             5, 11,  8,  6, 12,  7,  6, 12,  9,  0,  3,  5,  2, 14, 15,  9  },
 
    /* table S[7] */
        {   14,  0,  4, 15, 13,  7,  1,  4,  2, 14, 15,  2, 11, 13,  8,  1,
             3, 10, 10,  6,  6, 12, 12, 11,  5,  9,  9,  5,  0,  3,  7,  8,
             4, 15,  1, 12, 14,  8,  8,  2, 13,  4,  6,  9,  2,  1, 11,  7,
            15,  5, 12, 11,  9,  3,  7, 14,  3, 10, 10,  0,  5,  6,  0, 13  }
};
 
 
 
 
/**********************************************************************/
/*                                                                    */
/*                             DES CODE                               */
/*                                                                    */
/**********************************************************************/
 
/*=============================================================================================
                                     ---EncryptDES---
                                   Fonction de Cryptage
                Cette fonction crypte des blocks de 64bits en utilisant DES
  =============================================================================================*/
 
void EncryptDES(bool key[56], bool outBlk[64], bool inBlk[64], int verbose) {
  int i,round;
  bool R[32], L[32], fout[32];
  bool roundKey[56];
 
  EnableDumpBin = verbose;                       /* Flag de débogage sur On/Off */
  DumpBin("input(left)", inBlk+32, 32);
  DumpBin("input(right)", inBlk, 32);
  DumpBin("raw key(left )", key+28, 28);
  DumpBin("raw key(right)", key, 28);
 
  /*Réalise la permutation de choix 1 sur la clé*/
  ComputeRoundKey(roundKey, key);
 
  DumpBin("roundKey(L)", roundKey+28, 28);
  DumpBin("roundKey(R)", roundKey, 28);
 
  /*Réalise la permutation initiale sur le block de texte clair de 64 bits et sépare le résultat
        en deux parties Left et Right  */
  ComputeIP(L,R,inBlk);
 
  DumpBin("after IP(L)", L, 32);
  DumpBin("after IP(R)", R, 32);
 
  /* Boucle for qui parcours les 16 rounds */
  for (round = 0; round < 16; round++) {
    if (verbose)
      printf("-------------- BEGIN ENCRYPT ROUND %d -------------\n", round);
    DumpBin("round start(L)", L, 32);
    DumpBin("round start(R)", R, 32);
 
    /* Chaque partie de la clé est décalé de 1 ou 2 bits (dépend du round) à  gauche */
    RotateRoundKeyLeft(roundKey);
    if (round != 0 && round != 1 && round != 8 && round != 15)
      RotateRoundKeyLeft(roundKey);
    DumpBin("roundKey(L)", roundKey+28, 28);
    DumpBin("roundKey(R)", roundKey, 28);
 
    /* Entrée dans l'itération */
    ComputeF(fout, R, roundKey);
    DumpBin("f(R,key)", fout, 32);
    for (i = 0; i < 32; i++)
      L[i] ^= fout[i];
    DumpBin("L^f(R,key)", L, 32);
        
        /*Fonction d'échange de Left et Right*/
    Exchange_L_and_R(L,R);
 
    DumpBin("round end(L)", L, 32);
    DumpBin("round end(R)", R, 32);
    if (verbose)
      printf("--------------- END ROUND %d --------------\n", round);
  }
  /*Fin des 16 rounds*/
  
  /*Fonction d'échange de Left et Right*/
  Exchange_L_and_R(L,R);
 
  /* Concaténation de Left et Right et exécution de la permutation finale */
  ComputeFP(outBlk,L,R);
  DumpBin("FP out( left)", outBlk+32, 32);
  DumpBin("FP out(right)", outBlk, 32);
}
 
/* FIN DE LA FONCTION DE CRYPTAGE DES*/
 
/*=============================================================================================
                                     ---DecryptDES---
                                  Fonction de décryptage
               Cette fonction décrypte des blocks de 64bits en utilisant DES
  =============================================================================================*/
 
void DecryptDES(bool key[56], bool outBlk[64], bool inBlk[64], int verbose) {
  int i,round;
  bool R[32], L[32], fout[32];
  bool roundKey[56];
 
  EnableDumpBin = verbose;                      /* Flag de débogage sur On/Off */
  DumpBin("input(left)", inBlk+32, 32);
  DumpBin("input(right)", inBlk, 32);
  DumpBin("raw key(left )", key+28, 28);
  DumpBin("raw key(right)", key, 28);
 
  /*Réalise la permutation de choix 1 sur la clé*/
  ComputeRoundKey(roundKey, key);
 
  DumpBin("roundKey(L)", roundKey+28, 28);
  DumpBin("roundKey(R)", roundKey, 28);
 
  /*Réalise la permutation initiale sur le block de texte clair de 64 bits et sépare le résultat
        en deux parties Left et Right  */
  ComputeIP(L,R,inBlk);
 
  DumpBin("after IP(L)", L, 32);
  DumpBin("after IP(R)", R, 32);
 
  /*Boucle for qui parcours les 16 rounds */
  for (round = 0; round < 16; round++) {
    if (verbose)
      printf("-------------- BEGIN DECRYPT ROUND %d -------------\n", round);
    DumpBin("round start(L)", L, 32);
    DumpBin("round start(R)", R, 32);
 
    /*Execute la fonction computeF et effectue un XOR entre la sortie et Left*/
    ComputeF(fout, R, roundKey);
    DumpBin("f(R,key)", fout, 32);
    for (i = 0; i < 32; i++)
      L[i] ^= fout[i];
    DumpBin("L^f(R,key)", L, 32);
 
    Exchange_L_and_R(L,R);
 
    /*Chaque partie de la clé est décalé de 1 ou 2 bits (dépend du round) à  gauche */
    DumpBin("roundKey(L)", roundKey+28, 28);
    DumpBin("roundKey(R)", roundKey, 28);
    RotateRoundKeyRight(roundKey);
    if (round != 0 && round != 7 && round != 14 && round != 15)
      RotateRoundKeyRight(roundKey);
 
    DumpBin("round end(L)", L, 32);
    DumpBin("round end(R)", R, 32);
    if (verbose)
      printf("--------------- END ROUND %d --------------\n", round);
  }
  /*Fin des 16 rounds*/
  
  /*Fonction d'échange de Left et Right*/
  Exchange_L_and_R(L,R);
 
  /* Concaténation de Left et Right et exécution de la permutation finale */
  ComputeFP(outBlk,L,R);
  DumpBin("FP out( left)", outBlk+32, 32);
  DumpBin("FP out(right)", outBlk, 32);
}
/* FIN DE LA FONCTION DE DECRYPTAGE DES*/
 
/*=============================================================================================
                                     DEFINITION DES FONCTIONS
  =============================================================================================*/
 
 
 
/*
 *  ComputeRoundKey: Execute la permutation de choix 1 sur la clé et stocke le résultat dans roundkey
 */
static void ComputeRoundKey(bool roundKey[56], bool key[56]) {
  int i;
 
  for (i = 0; i < 56; i++)
    roundKey[table_DES_PC1[i]] = key[i];
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  RotateRoundKeyLeft: rotation de chaque partie (de28bits) de la clé de 1 bits à gauche
 */
static void RotateRoundKeyLeft(bool roundKey[56]) {
  bool temp1, temp2;
  int i;
 
  temp1 = roundKey[27];
  temp2 = roundKey[55];
  for (i = 27; i >= 1; i--) {
    roundKey[i] = roundKey[i-1];
    roundKey[i+28] = roundKey[i+28-1];
  }
  roundKey[ 0] = temp1;
  roundKey[28] = temp2;
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  RotateRoundKeyRight: rotation de chaque partie (de28bits) de la clé de 1 bits à  gauche
 */
static void RotateRoundKeyRight(bool roundKey[56]) {
  bool temp1, temp2;
  int i;
 
  temp1 = roundKey[0];
  temp2 = roundKey[28];
  for (i = 0; i < 27; i++) {
    roundKey[i] = roundKey[i+1];
    roundKey[i+28] = roundKey[i+28+1];
  }
  roundKey[27] = temp1;
  roundKey[55] = temp2;
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  ComputeIP: Réalise la permutation initiale et découpe le block de 64 bits
 *       en deux parties de 32 bits Left et Right
 */
static void ComputeIP(bool L[32], bool R[32], bool inBlk[64]) {
  bool output[64];
  int i;
 
  /* Permutation
   */
  for (i = 63; i >= 0; i--)
    output[table_DES_IP[i]] = inBlk[i];
 
  /* Découpage entre Left et Right:   Les bits 63 à  32 vont à  gauche, les bits 31 à  0 à  droite.
   */
  for (i = 63; i >= 0; i--) {
    if (i >= 32)
      L[i-32] = output[i];
    else
      R[i] = output[i];
  }
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  ComputeFP: Concaténation de Left et Right et execution de la permutation finale
 */
static void ComputeFP(bool outBlk[64], bool L[32], bool R[32]) {
  bool input[64];
  int i;
 
  /* Concaténation de Left et Right dans une entrée de 64 bits
   */
  for (i = 63; i >= 0; i--)
    input[i] = (i >= 32) ? L[i - 32] : R[i];
 
  /* Permutation
   */
  for (i = 63; i >= 0; i--)
    outBlk[table_DES_FP[i]] = input[i];
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  ComputeF: Execution du cryptage DES et stockage du résultat dans fout
* Cette fonction est le traitement qui à  lieu dans UNE SEULE itération
*/
/* ----------------------DEBUT DE LA FONCTION COMPUTE F --------------------------------*/
 
static void ComputeF(bool fout[32], bool R[32], bool roundKey[56]) {
  bool expandedBlock[48], subkey[48], sout[32];
  int i,k;
 
  /* Expansion de Right en 48 bits via la fonction "ComputeExpansionE"*/
  ComputeExpansionE(expandedBlock, R);
  DumpBin("expanded E", expandedBlock, 48);
 
  /* Conversion de la clé de 56bits en sous-clé de 48 bits */
  ComputePC2(subkey, roundKey);
  DumpBin("subkey", subkey, 48);
 
  /* XOR de 48bits entre la  sous-clé et le texte expansé*/
  for (i = 0; i < 48; i++)
    expandedBlock[i] ^= subkey[i];
 
  /* Le résultat du XOR est divisé en 8 partie de 6 bits qui sont traités dans les S-Box
               Les 8 S-Box ressortent chacun 4 bits qui forment un block de 32bits                            */
  for (k = 0; k < 8; k++)
    ComputeS_Lookup(k, sout+4*k, expandedBlock+6*k);
 
  /* Appel de la fonction de permutation "ComputeP" ci-dessous */
  ComputeP(fout, sout);
}
/* ----------------------FIN DE LA FONCTION COMPUTE F --------------------------------*/
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  ComputeP: Réalise une permutation en sortie des S-Box via le tableau "table_DES_P[32]"
 */
static void ComputeP(bool output[32], bool input[32]) {
  int i;
 
  for (i = 0; i < 32; i++)
    output[table_DES_P[i]] = input[i];
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  Fonction S-Box
 * Cette fonction définie le traitement effectuée sur les block de 6 bits
 * Elle renvoie des block de 4 bits, soit un entier entre 0 et 15
 */
static void ComputeS_Lookup(int k, bool output[4], bool input[6]) {
  int inputValue, outputValue;
 
  /* conversion des block en entrée en entier */
  inputValue = input[0] + 2*input[1] + 4*input[2] + 8*input[3] +
          16*input[4] + 32*input[5];
 
  /* Recherche la valeur dans la S-Box numéro "k" - k de 0 à 7 */
  outputValue = table_DES_S[k][inputValue];
 
  /* Conversion du résultat en forme binaire */
  output[0] = (outputValue & 1) ? 1 : 0;
  output[1] = (outputValue & 2) ? 1 : 0;
  output[2] = (outputValue & 4) ? 1 : 0;
  output[3] = (outputValue & 8) ? 1 : 0;
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  ComputePC2: Permutation de choix 2- conversion d'une clé de 56 bits en 48 bits
 */
static void ComputePC2(bool subkey[48], bool roundKey[56]) {
  int i;
 
  for (i = 0; i < 48; i++)
    subkey[i] = roundKey[table_DES_PC2[i]];
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  ComputeExpansionE: Expansion du bloc de bits de 32 bits en 48 bits
 *  via le tableau "table_DES_E[48]"
 */
static void ComputeExpansionE(bool expandedBlock[48], bool R[32]) {
  int i;
 
  for (i = 0; i < 48; i++)
    expandedBlock[i] = R[table_DES_E[i]];
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  Exchange_L_and_R:  Echange entre les block Right et Left
 */
static void Exchange_L_and_R(bool L[32], bool R[32]) {
  int i;
 
  for (i = 0; i < 32; i++)
    L[i] ^= R[i] ^= L[i] ^= R[i];                 /* Echange de L[i] et R[i] */
}
 
/*--------------------------------------------------------------------------------------------------*/
 
/*
 *  DumpBin: Renvoie les valeurs intermédiaires si enableDumpBin est activé.
 */
static void DumpBin(char *str, bool *b, int bits) {
  int i;
/*Contrôle d'erreur d'appel*/
  if ((bits % 4)!=0 || bits>48) {
    printf("Bad call to DumpBin (bits > 48 or bit len not a multiple of 4\n");
    exit(1);
  }
 
/*Si DumpBin est activé*/
  if (EnableDumpBin) {
    for (i = strlen(str); i < 14; i++)
      printf(" ");
    printf("%s: ", str);
    for (i = bits-1; i >= 0; i--)
      printf("%d", b[i]);
    printf(" ");
    for (i = bits; i < 48; i++)
      printf(" ");
    printf("(");
    for (i = bits-4; i >= 0; i-=4)
      printf("%X", b[i]+2*b[i+1]+4*b[i+2]+8*b[i+3]);
    printf(")\n");
  }
}
/*-------------------------------------------FIN----------------------------------------------------*/