jeudi 27 octobre 2016

03 - Le chiffrement par bloc


Le chiffrement par bloc

Deux grandes catégories : 

La différence essentielle se situe sur la taille de bloc entre 32 et 512 bits.

     Chiffrement symétrique

             Anciennement le standard était le DES sur 64 bit,
             il a été remplacé en 2000 par le standard AES  sur 128 bits

     Chiffrement par flot


              Il est possible de transformer un chiffrement de bloc en un chiffrement par flot 
              en utilisant un mode d'opération comme ECB (chaque bloc chiffré indépendamment 
              des autres) ou CFB (on chaîne le chiffrement en effectuant un XOR entre les 
              résultats successifs).


l'Advanced Encryption Standard (AES


          L'algorithme Rijndael a été conçu par deux chercheurs belges qui sont Joan Daemen et Vincent Rijmen pour devenir le successeur de l'algorithme DES.


        L'objectif de l'AES se résume en trois points:

       - Une résistance à tout type d'attaque et à la cryptoanalyse
       - Une simplicité de conception
       - Une grande rapidité du code selon l'optimisation de l'implémentation sur les plate-formes.


Fonctionnement

     L'algorithme travaille sur des blocs plaintext P de 128 bits et les convertir en blocs Ciphers C de 128 bits selon un nombre de tours (10,12,14) qui peut être exécuter en séquence en fonction d'une clé d'une taille variable pouvant aller de 128,196,256 bits.



Nombre de tour

Selon la taille de la clé  le nombre de tours évolue

                                                  Key length
                           128bits nk=4     196bits nk=6       256bits nk=8
 Block Length
 128 bits nb=4            10                  12                       14
 196 bits nb=6            12                  12                       14
 256 bits nb=8            14                  14                       14

Expansion de la clé

Après avoir subi une extension (Key Expansion), la clé sera découpée en sous-clés (appelées clés de tour),




Processus de chiffrement d'un tour (Ki)





Byte Substitution (SubBytes)

Les 16 octets d'entrée sont substitués en recherchant une table fixe (S-box). Le résultat est une matrice de quatre rangées et quatre colonnes.


ShiftRows

Chacune des quatre rangées de la matrice est décalée vers la gauche. Toutes les entrées qui sortent à gauche sont réinsérés sur le côté droit de la ligne.
Selon la méthode effectuée comme suit: -
  • La première rangée n'est pas décalée.
  • La deuxième rangée est décalée d'une position (octet) vers la gauche.
  • La troisième rangée est décalée de deux positions vers la gauche.
  • La quatrième rangée est décalé de trois positions vers la gauche.
  • Le résultat est une nouvelle matrice constituée par les mêmes 16 octets, mais décalé par rapport à l'autre.


MixColumns

Chaque colonne de quatre octets est maintenant transformé en utilisant une fonction mathématique particulière. 
Cette fonction prend en entrée les quatre octets d'une colonne et quatre nouveaux octets en sorties qui remplacent la colonne d'origine. 
Le résultat est une nouvelle matrice constituée de 16 octets. Il convient de noter que cette étape ne sera pas réalisée dans le dernier tour.

AddRoundKey

Les 16 octets de la matrice sont désormais considérés comme 128 bits et sont XORés aux 128 bits de la  clé de tour . 

Note: A chaque tour, une clé de tour est générée à partir de la clé secrète par un sous-algorithme (dit de cadencement). Cette clé de tour est ajoutée par un ou exclusif au dernier bloc obtenu.
Si c'est le dernier tour, alors le résultat est le cryptogramme. Sinon, les 128 bits résultants sont interprétés comme 16 octets et nous recommençons un autre tour similaire.

Rijndael_key_schedule

Processus de déchiffrement
Le processus de déchiffrement d'un cryptogramme AES est similaire au processus de chiffrement mais éxécuter dans l'ordre inverse. Chaque tour se compose des quatre processus .

           Ajouter  une clé de tour
  • Mélanger les colonnes
  • Le décalage lignes 
  • la substitution d'octet
Depuis les sous-processus, a chaque tour exécuté, les algorithmes de chiffrement et de déchiffrement doit être mis en œuvre séparément, bien qu'ils sont très étroitement liés.

Peudo code 

Encryption Algorithm (128-bit version)


Cipher(byte in[16], byte out[16], word w[44])beginbyte state[4,4]state = inAddRoundKey(state, w[0, 3])for round = 1 step 1 to 10SubBytes(state)ShiftRows(state)MixColumns(state)AddRoundKey(state, w[round*4, (round+1)*4-1])end forSubBytes(state)ShiftRows(state)AddRoundKey(state, w[40, 43])out = stateend
Liens utiles

Advanced Encryption Standard

Rijndael_Animation

C AES encrypt/decrypt
AES_Decrypt.cpp
AES_Encrypt.cpp

voir exemple java ci-dessous :



Code Main Test


package test;

public class TestAES {

    public static void main(String[] args) {

        String key = "2efa3ec8dab164f3";
        String plainText = "bonjour ceci est un test AES";

        try{

            //AES key 16 bytes, 128 bits
            System.out.println("Text en clair plainText: "+plainText);

            byte[] encryptedData = AES.encrypt128(plainText.getBytes(), key.getBytes());
            System.out.println("Test chiffrement avec AES: {"+new String(encryptedData)+"]");

            byte[] decrypteData = AES.decrypt128(encryptedData, key.getBytes());

            System.out.println("Test dechiffrement avec AES: ["+new String(decrypteData)+"]" );

        }catch(Exception e){
            e.printStackTrace();
        }
    }

}


Java Code Exemple AES 128, il est possible de faire évoluer en 196 bits, 256bits, selon la taille de clé, le nombre de tour et la taille du bloc. Cet exemple est inspiré de divers autres exemples écrit en C que j'ai mis au point.

public class AES {

    /*  Nb: number bloc     * Nk: number subkey     * Nr: round number     */
    private static int Nb, Nk, Nr;
    private static byte[][] roundKey;
    private static final int DATA_BLOC_SIZE = 16;
    private static final int KEY_SIZE = 16;

    /*     * S_BOX encrypt     */    
private static int[] sbox = {0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F,
            0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82,
            0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C,
            0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
            0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23,
            0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27,
            0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52,
            0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
            0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58,
            0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9,
            0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92,
            0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
            0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E,
            0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A,
            0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0,
            0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62,
            0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E,
            0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78,
            0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B,
            0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
            0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98,
            0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55,
            0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41,
            0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16};

    /*     *     * S-box decrypt     */    
private static int[] inv_sbox = {0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5,
            0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3,
            0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4,
            0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
            0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1,
            0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B,
            0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4,
            0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
            0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D,
            0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4,
            0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA,
            0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
            0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF,
            0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD,
            0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47,
            0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E,
            0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79,
            0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD,
            0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27,
            0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
            0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B,
            0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53,
            0x99, 0x61, 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1,
            0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D};

    /*     * sub key generation data     */    
public static int Rcon[] = {0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
            0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
            0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
            0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
            0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
            0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
            0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
            0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
            0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
            0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
            0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
            0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
            0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
            0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
            0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
            0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb};


public static byte[] xor(byte[] a, byte[] b) {
        byte[] out = new byte[a.length];
        for (int i = 0; i < a.length; i++)
            out[i] = (byte) (a[i] ^ b[i]);
        return out;
    }


    public static byte[][] KeyExpansion(byte[] key) {
        int i, j;
        byte[] temp;
        byte k;

        byte[][] roundKey = new byte[Nb * (Nr + 1)][4];

        //  premier tour, decompose la clé en sous partie de de 4 bytes
        for (i = 0; i < Nk; i++) {
            roundKey[i][0] = key[i * 4];
            roundKey[i][1] = key[i * 4 + 1];
            roundKey[i][2] = key[i * 4 + 2];
            roundKey[i][3] = key[i * 4 + 3];
        }

        // calcul des sous clés pour tous les autre tours,        // substitution de sous cle via un xor avec les bytes de la sbox
        while (i < (Nb * (Nr + 1))) {
            temp = new byte[4];

            for (j = 0; j < 4; j++)
                temp[j] = roundKey[i - 1][j];

            if (i % Nk == 0) {
                RotWord(temp);
                temp = SubWord(temp);
                temp[0] = (byte) (temp[0] ^ (Rcon[i / Nk] & 0xff));
            } else if (Nk > 6 && i % Nk == 4) {
                temp = SubWord(temp);
            }
            roundKey[i] = xor(roundKey[(i - Nk)], temp);
            i++;
        }

        return roundKey;
    }


    public static void RotWord(byte[] temp) {
        byte k;
        k = temp[0];
        temp[0] = temp[1];
        temp[1] = temp[2];
        temp[2] = temp[3];
        temp[3] = k;
    }


    public static byte[] SubWord(byte[] in) {
        byte[] tmp = new byte[in.length];

        for (int i = 0; i < tmp.length; i++)
            tmp[i] = (byte) (sbox[in[i] & 0x000000ff] & 0xff);

        return tmp;
    }


    public static byte[][] AddRoundKey(byte[][] state, byte[][] roundKey, int round) {
        int i, j;
        for (i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++)
                state[i][j] = (byte) (state[i][j] ^ roundKey[round * Nb + i][j]);
        }
        return state;
    }


    public static byte[][] SubBytes(byte[][] state) {

        byte[][] tmp = state.clone();
        int i, j;
        for (i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++) {
                state[i][j] = (byte) (byte) (sbox[(state[i][j] & 0x000000ff)] & 0xff);
            }
        }
        return tmp;
    }

      public static byte[][] InvSubBytes(byte[][] state) {

        byte[][] tmp = state.clone();
        for (int row = 0; row < 4; row++)
            for (int col = 0; col < Nb; col++)
                tmp[row][col] = (byte) (inv_sbox[(tmp[row][col] & 0x000000ff)] & 0xff);
        return tmp;
      }

      private static byte[][] ShiftRows(byte[][] state) {

        byte[][] tmp = state.clone();
        for (int r = 1; r < 4; r++) {
            int j = 0;
            byte[] t = new byte[4];
            for (int c = 0; c < Nb; c++) {
                t[j] = tmp[r][(c + r) % Nb];
                j++;
            }
            tmp[r] = t;
        }
        return tmp;
    }

        private static byte[][] InvShiftRows(byte[][] state) {
        byte[][] tmp = state.clone();
        for (int r = 1; r < 4; r++) {
            byte[] t = new byte[4];
            for (int c = 0; c < Nb; c++)
                t[(c + r) % Nb] = tmp[r][c];
            for (int c = 0; c < Nb; c++)
                tmp[r] = t;
        }
        return tmp;
        }


        private static byte[][] MixColumns(byte[][] s) {
        int[] sp = new int[4];
        byte b02 = (byte) 0x02, b03 = (byte) 0x03;
        for (int c = 0; c < 4; c++) {
            sp[0] = gMul(b02, s[0][c]) ^ gMul(b03, s[1][c]) ^ s[2][c] ^ s[3][c];
            sp[1] = s[0][c] ^ gMul(b02, s[1][c]) ^ gMul(b03, s[2][c]) ^ s[3][c];
            sp[2] = s[0][c] ^ s[1][c] ^ gMul(b02, s[2][c]) ^ gMul(b03, s[3][c]);
            sp[3] = gMul(b03, s[0][c]) ^ s[1][c] ^ s[2][c] ^ gMul(b02, s[3][c]);
            for (int i = 0; i < 4; i++) s[i][c] = (byte) (sp[i]);
        }
        return s;
        }
private static byte[][] InvMixColumns(byte[][] s) { int[] sp = new int[4]; byte b02 = (byte) 0x0e, b03 = (byte) 0x0b, b04 = (byte) 0x0d, b05 = (byte) 0x09; for (int c = 0; c < 4; c++) { sp[0] = gMul(b02, s[0][c]) ^ gMul(b03, s[1][c]) ^ gMul(b04, s[2][c]) ^ gMul(b05, s[3][c]); sp[1] = gMul(b05, s[0][c]) ^ gMul(b02, s[1][c]) ^ gMul(b03, s[2][c]) ^ gMul(b04, s[3][c]); sp[2] = gMul(b04, s[0][c]) ^ gMul(b05, s[1][c]) ^ gMul(b02, s[2][c]) ^ gMul(b03, s[3][c]); sp[3] = gMul(b03, s[0][c]) ^ gMul(b04, s[1][c]) ^ gMul(b05, s[2][c]) ^ gMul(b02, s[3][c]); for (int i = 0; i < 4; i++) s[i][c] = (byte) (sp[i]); } return s; } public static byte gMul(byte a, byte b) { // Galois Field (256) Multiplication of two Bytes byte p = 0; byte counter; byte hi_bit_set; for (counter = 0; counter < 8; counter++) { if ((b & 1) != 0) { p ^= a; } hi_bit_set = (byte) (a & 0x80); a <<= 1; if (hi_bit_set != 0) { a ^= (byte) 0x1b; /* x^8 + x^4 + x^3 + x + 1 */ } b >>= 1; } return p; } public static byte[] encryptDataBloc(byte[] in) { byte[] tmp = new byte[in.length]; byte[][] state = new byte[4][Nb]; for (int i = 0; i < in.length; i++) state[i / 4][i % 4] = in[i % 4 * 4 + i / 4]; state = AddRoundKey(state, roundKey, 0); for (int round = 1; round < Nr; round++) { state = SubBytes(state); state = ShiftRows(state); state = MixColumns(state); state = AddRoundKey(state, roundKey, round); } state = SubBytes(state); state = ShiftRows(state); state = AddRoundKey(state, roundKey, Nr); for (int i = 0; i < tmp.length; i++) tmp[i % 4 * 4 + i / 4] = state[i / 4][i % 4]; return tmp; } public static byte[] decryptDataBloc(byte[] in) { byte[] tmp = new byte[in.length]; byte[][] state = new byte[4][Nb]; for (int i = 0; i < in.length; i++) state[i / 4][i % 4] = in[i % 4 * 4 + i / 4]; state = AddRoundKey(state, roundKey, Nr); for (int round = Nr - 1; round >= 1; round--) { state = InvSubBytes(state); state = InvShiftRows(state); state = AddRoundKey(state, roundKey, round); state = InvMixColumns(state); } state = InvSubBytes(state); state = InvShiftRows(state); state = AddRoundKey(state, roundKey, 0); for (int i = 0; i < tmp.length; i++) tmp[i % 4 * 4 + i / 4] = state[i / 4][i % 4]; return tmp; } public static byte[] encrypt128(byte[] in, byte[] key) { Nb = 4; Nk = key.length / 4; Nr = Nk + 6; int lenght = 0; byte[] padding = new byte[1]; int i; lenght = DATA_BLOC_SIZE - in.length % DATA_BLOC_SIZE; padding = new byte[lenght]; padding[0] = (byte) 0x80; for (i = 1; i < lenght; i++) padding[i] = 0; byte[] tmp = new byte[in.length + lenght]; byte[] bloc = new byte[DATA_BLOC_SIZE]; roundKey = KeyExpansion(key); int count = 0; for (i = 0; i < in.length + lenght; i++) { if (i > 0 && i % DATA_BLOC_SIZE == 0) { bloc = encryptDataBloc(bloc); System.arraycopy(bloc, 0, tmp, i - DATA_BLOC_SIZE, bloc.length); } if (i < in.length) bloc[i % DATA_BLOC_SIZE] = in[i]; else { bloc[i % DATA_BLOC_SIZE] = padding[count % DATA_BLOC_SIZE]; count++; } } if (bloc.length == DATA_BLOC_SIZE) { bloc = encryptDataBloc(bloc); System.arraycopy(bloc, 0, tmp, i - DATA_BLOC_SIZE, bloc.length); } return tmp; } /* * AES Decryt */ public static byte[] decrypt128(byte[] in, byte[] key) { int i; byte[] tmp = new byte[in.length]; byte[] bloc = new byte[DATA_BLOC_SIZE]; Nb = 4; Nk = key.length / 4; Nr = Nk + 6; roundKey = KeyExpansion(key); for (i = 0; i < in.length; i++) { if (i > 0 && i % DATA_BLOC_SIZE == 0) { bloc = decryptDataBloc(bloc); System.arraycopy(bloc, 0, tmp, i - DATA_BLOC_SIZE, bloc.length); } if (i < in.length) bloc[i % DATA_BLOC_SIZE] = in[i]; } bloc = decryptDataBloc(bloc); System.arraycopy(bloc, 0, tmp, i - DATA_BLOC_SIZE, bloc.length); tmp = paddingClean(tmp); return tmp; } private static byte[] paddingClean(byte[] input) { int count = 0; int i = input.length - 1; while (input[i] == 0) { count++; i--; } byte[] tmp = new byte[input.length - count - 1]; System.arraycopy(input, 0, tmp, 0, tmp.length); return tmp; } }

Console execution output
com.intellij.rt.execution.application.AppMain test.TestAES

Text en clair plainText: bonjour ceci est un test AES
Test chiffrement avec AES: {�ܷ �� �� �Z����o ]�AQ#J�"��<1VQ]
Test dechiffrement avec AES: [bonjour ceci est un test AES]

Process finished with exit code 0



Aucun commentaire:

Enregistrer un commentaire