Skip to main content

Data Encryption Standard (DES) Algorithm

Data Encryption Standard is a symmetric-key algorithm for the encrypting the data. It comes under block cipher algorithm which follows Feistel structure. Here is the block diagram of Data Encryption Standard.

DES Algorithm Block Diagram

Fig1: DES Algorithm Block Diagram [Image Source: Cryptography and Network Security Principles and Practices 4th Ed by William Stallings]

Explanation for above diagram: Each character of plain text converted into binary format. Every time we take 64 bits from that and give as input to DES algorithm, then it processed through 16 rounds and then converted to cipher text.

Initial Permutation: 64 bit plain text goes under initial permutation and then given to round 1. Since initial permutation step receiving 64 bits, it contains an 1×64 matrix which contains numbers from 1 to 64 but in shuffled order. After that, we arrange our original 64 bit text in the order mentioned in that matrix. [You can see the matrix in below code]

After initial permutation, 64 bit text passed through 16 rounds. In each round it processed with 48 bit key. That means we need total 16 sub keys, one for each round. See below diagram, it will show what happening in each round of algorithm.

Single Round of DES Algorithm

Fig2: Single Round of DES Algorithm. [Image Source: Cryptography and Network Security Principles and Practices 4th Ed by William Stallings]

Round i: In each round 64bit text divided into two 32bit parts. Left and Right. You can see in diagram Li-1 and Ri-1. As algorithm says, Right 32bits goes under Expansion Permutation.

Expansion Permutation: Right side 32bit part of text given to expansion permutation. It will produce a 48bit text as output. i.e. 16bits added in this step. Some bits below 32 are repeated and arranged in an 1×48 matrix form. We rearrange 32bit text by following the order of that matrix. [See the matrix in below code]

After expansion permutation we have to XOR the output 48bit with a 48bit sub key. Let see how that 48bit sub key generating from 64bit original key.

Permutated Choice 1: Initially we take a 64 bit key and then apply to permutated choice 1. It contains a 1×56 matrix but with shuffled 1 to 64 numbers except multiples of number 8. i.e. 8, 16, 24, 32, 40, 48, 56, 64 will be discarded. Remaining 64-8 = 56 number will be there in 1×56 matrix. We rearrange key in matrix specified order. [You can see the matrix in below code]

Left Circular Shift: 56bit key from permutated choice 1 given to left circular shift operation. Here that 56bit key divided into two equal halves of each 28bit. These 28bits shifted depends upon the round number. We already have the data that in each round how many bits circularly we have to shift. You can see this data in shifts array in code.

Permutated Choice 2: Result of Left circular shift 56bit key given to permutated choice 2. This step will produce 48bit sub key. For this it has an 1×48 matrix, in which out of 56, some random 8 bits will be discarded. And remaining 48 will be there. According to this bit positions we have to rearrange the key. You can see this matrix in below code.

Now output of permutated choice 2 will be Xor with output of expansion permutation, which results a 48bit one. This 48bit again reduced to 32bit using Substitution boxes [called S box].

Substitution boxes [S box]: In DES algorithm we have 8 S boxes. Input for S box is 48bit. And output from S box is 32 bit. The input 48 bit will be divided equally to 8 s boxes from s1, s2, … s8. So each s box will get 48/8= 6 bits as input. This Each S box reduce 6 bits to 4 bits. i.e input for each S box is 6 bits and output is 4 bits. Finally, 8*4 = 32 bit. Which is final output of S box operation.

Let see how 6bits converted to 4 bits from S box. S box is an 4×16 matrix containing numbers in range 0 to 15. Take example, assume input 6 bits for S box are 011011. In this first and last bit together represents row number. Since maximum number with two bits is 3, S box also contains 0 to 3 rows total of 4. And middle 4 numbers together represent column number. Since maximum number with 4 bits is 15, S box also contains columns 0 to 15 total of 16. So here first and last bit = 01 i.e. row number 1 and middle 4 bits 1101= 13 i.e. column number 13. So for this input the number positioned at row 1 and column 13 will be picked. As mentioned earlier S box only contains number in range 0 to 15. All can be represented in 4 bits. So picked number 4 bits are output for the S box. See the code for all S boxes.

Permutation: After getting output from all S boxes, we are applying again permutation. Here also a matrix with different arrangements will be there, we have to arrange according to that.

Final XOR: After this permutation, take the left half which initially divided 64bit text to two halves. Do XOR with this permutation output to left 32bit part. This result is new Right part. And Right 32bit part which passed through all permutation will be come as new Left Part. These 2 parts will be the inputs for the second round. Same as keys also, the parts before left shift are next round input keys.

All this explanation for a single round for a 62bit plain text. Like this, it passes through total 16 rounds.

32 bit swap: After completion of 16 rounds, final 64 bits divided into two 32 bit parts and they swap each other.

Inverse Initial Permutation: Here also a matrix will be there, in which bits are just shuffled. No adding or subtracting bits. See the code for this matrix.

Program for DES Algorithm in C

#include <stdio.h>

int Original_key [64] = { // you can change key if required
        0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0,
        0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1,
        1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0,
        1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1
};

int Permutated_Choice1[56] = {
          57, 49, 41, 33, 25, 17,  9,
           1, 58, 50, 42, 34, 26, 18,
          10,  2, 59, 51, 43, 35, 27,
          19, 11,  3, 60, 52, 44, 36,
          63, 55, 47, 39, 31, 23, 15,
           7, 62, 54, 46, 38, 30, 22,
          14,  6, 61, 53, 45, 37, 29,
          21, 13,  5, 28, 20, 12,  4
};

int Permutated_Choice2[48] = {
          14, 17, 11, 24,  1,  5,
           3, 28, 15,  6, 21, 10,
          23, 19, 12,  4, 26,  8,
          16,  7, 27, 20, 13,  2,
          41, 52, 31, 37, 47, 55,
          30, 40, 51, 45, 33, 48,
          44, 49, 39, 56, 34, 53,
          46, 42, 50, 36, 29, 32
};

int Iintial_Permutation [64] = {
          58, 50, 42, 34, 26, 18, 10, 2,
          60, 52, 44, 36, 28, 20, 12, 4,
          62, 54, 46, 38, 30, 22, 14, 6,
          64, 56, 48, 40, 32, 24, 16, 8,
          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
};

int Final_Permutation[] = 
{
          40, 8, 48, 16, 56, 24, 64, 32,
          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
};

int P[] = 
{
          16,  7, 20, 21,
          29, 12, 28, 17,
           1, 15, 23, 26,
           5, 18, 31, 10,
           2,  8, 24, 14,
          32, 27,  3,  9,
          19, 13, 30,  6,
          22, 11,  4, 25
};

int E[] = 
{
          32,  1,  2,  3,  4,  5,
           4,  5,  6,  7,  8,  9,
           8,  9, 10, 11, 12, 13,
          12, 13, 14, 15, 16, 17,
          16, 17, 18, 19, 20, 21,
          20, 21, 22, 23, 24, 25,
          24, 25, 26, 27, 28, 29,
          28, 29, 30, 31, 32,  1
};

int S1[4][16] = 
{
                14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
                0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
                4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
                15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13
};

int S2[4][16] = 
{
        15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
         3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
         0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
        13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9
};

int S3[4][16] = 
{
        10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
        13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
        13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
         1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12
};

int S4[4][16] = 
{
         7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
        13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
        10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
         3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14
};

int S5[4][16] = 
{
         2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
        14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
         4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
        11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3
};

int S6[4][16] = 
{
        12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
        10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
         9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
         4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13
};

int S7[4][16]= 
{
         4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
        13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
         1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
         6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12
};

int S8[4][16]= 
{
        13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
         1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
         7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
         2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
};

int shifts_for_each_round[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
int _56bit_key[56];
int _48bit_key[17][48];
int text_to_bits[99999], bits_size=0;
int Left32[17][32], Right32[17][32];
int EXPtext[48];
int XORtext[48];
int X[8][6];
int X2[32];
int R[32];
int chiper_text[64];
int encrypted_text[64];

int XOR(int a, int b) {
        return (a ^ b);
}

void Dec_to_Binary(int n) 
{ 
    int binaryNum[1000]; 
    int i = 0; 
    while (n > 0) { 
        binaryNum[i] = n % 2; 
        n = n / 2; 
        i++; 
    } 
    for (int j = i - 1; j >= 0; j--) {
                        text_to_bits[bits_size++] = binaryNum[j]; 
        }
} 

int F1(int i)
{
        int r, c, b[6];
        for (int j = 0; j < 6; j++)
                b[j] = X[i][j];

        r = b[0] * 2 + b[5];
        c = 8 * b[1] + 4 * b[2] + 2 * b[3] + b[4];
        if (i == 0)
                return S1[r][c];
        else if (i == 1)
                return S2[r][c];
        else if (i == 2)
                return S3[r][c];
        else if (i == 3)
                return S4[r][c];
        else if (i == 4)
                return S5[r][c];
        else if (i == 5)
                return S6[r][c];
        else if (i == 6)
                return S7[r][c];
        else if (i == 7)
                return S8[r][c];
}


int PBox(int pos, int bit)
{
        int i;
        for (i = 0; i < 32; i++)
                if (P[i] == pos + 1)
                        break;
        R[i] = bit;
}

int ToBits(int value)
{
        int k, j, m;
        static int i;
        if (i % 32 == 0)
                i = 0;
        for (j = 3; j >= 0; j--) 
        {
                m = 1 << j;
                k = value & m;
                if (k == 0)
                        X2[3 - j + i] = '0' - 48;
                else
                        X2[3 - j + i] = '1' - 48;
        }
        i = i + 4;
}

int SBox(int XORtext[])
{
        int k = 0;
        for (int i = 0; i < 8; i++)
                for (int j = 0; j < 6; j++)
                        X[i][j] = XORtext[k++];

        int value;
        for (int i = 0; i < 8; i++) 
        {
                value = F1(i);
                ToBits(value);
        }
}

void expansion_function(int pos, int bit)
{
        for (int i = 0; i < 48; i++)
                if (E[i] == pos + 1)
                        EXPtext[i] = bit;
}

void cipher(int Round, int mode)
{
        for (int i = 0; i < 32; i++)
                expansion_function(i, Right32[Round - 1][i]);

        for (int i = 0; i < 48; i++) 
        {
                if (mode == 0)
                        XORtext[i] = XOR(EXPtext[i], _48bit_key[Round][i]);
                else
                        XORtext[i] = XOR(EXPtext[i], _48bit_key[17 - Round][i]);
        }

        SBox(XORtext);

        for (int i = 0; i < 32; i++)
                PBox(i, X2[i]);
        for (int i = 0; i < 32; i++)
                Right32[Round][i] = XOR(Left32[Round - 1][i], R[i]);
}

void finalPermutation(int pos, int bit)
{
        int i;
        for (i = 0; i < 64; i++)
                if (Final_Permutation[i] == pos + 1)
                        break;
        encrypted_text[i] = bit;
}

void Encrypt_each_64_bit (int plain_bits [])
{
        int IP_result [64] , index=0;
        for (int i = 0; i < 64; i++) {
                IP_result [i] = plain_bits[ Iintial_Permutation[i] ];
        }
        for (int i = 0; i < 32; i++)
                Left32[0][i] = IP_result[i];
        for (int i = 32; i < 64; i++)
                Right32[0][i - 32] = IP_result[i];

        for (int k = 1; k < 17; k++) 
        { // processing through all 16 rounds
                cipher(k, 0);

                for (int i = 0; i < 32; i++)
                        Left32[k][i] = Right32[k - 1][i]; // right part comes as it is to next round left part
        }

        for (int i = 0; i < 64; i++) 
        { // 32bit swap as well as Final Inverse Permutation
                if (i < 32)
                        chiper_text[i] = Right32[16][i];
                else
                        chiper_text[i] = Left32[16][i - 32];
                finalPermutation(i, chiper_text[i]);
        }

        for (int i = 0; i < 64; i++)
                printf("%d", encrypted_text[i]);
}


void convert_Text_to_bits(char *plain_text){
        for(int i=0;plain_text[i];i++){
                int asci = plain_text[i];
                Dec_to_Binary(asci);
        }
}

void key56to48(int round, int pos, int bit)
{
        int i;
        for (i = 0; i < 56; i++)
                if (Permutated_Choice2[i] == pos + 1)
                        break;
        _48bit_key[round][i] = bit;
}

int key64to56(int pos, int bit)
{
        int i;
        for (i = 0; i < 56; i++)
                if (Permutated_Choice1[i] == pos + 1)
                        break;
        _56bit_key[i] = bit;
}

void key64to48(int key[])
{
        int k, backup[17][2];
        int CD[17][56];
        int C[17][28], D[17][28];

        for (int i = 0; i < 64; i++)
                key64to56(i, key[i]);

        for (int i = 0; i < 56; i++)
                if (i < 28)
                        C[0][i] = _56bit_key[i];
                else
                        D[0][i - 28] = _56bit_key[i];

        for (int x = 1; x < 17; x++) 
        {
                int shift = shifts_for_each_round[x - 1];

                for (int i = 0; i < shift; i++)
                        backup[x - 1][i] = C[x - 1][i];
                for (int i = 0; i < (28 - shift); i++)
                        C[x][i] = C[x - 1][i + shift];
                k = 0;
                for (int i = 28 - shift; i < 28; i++)
                        C[x][i] = backup[x - 1][k++];

                for (int i = 0; i < shift; i++)
                        backup[x - 1][i] = D[x - 1][i];
                for (int i = 0; i < (28 - shift); i++)
                        D[x][i] = D[x - 1][i + shift];
                k = 0;
                for (int i = 28 - shift; i < 28; i++)
                        D[x][i] = backup[x - 1][k++];
        }

        for (int j = 0; j < 17; j++) 
        {
                for (int i = 0; i < 28; i++)
                        CD[j][i] = C[j][i];
                for (int i = 28; i < 56; i++)
                        CD[j][i] = D[j][i - 28];
        }

        for (int j = 1; j < 17; j++)
                for (int i = 0; i < 56; i++)
                        key56to48(j, i, CD[j][i]);
}

int main(){
        char plain_text[] = "tomarrow we wiil be declaring war";
        convert_Text_to_bits(plain_text);
        key64to48(Original_key); // it creates all keys for all rounds
        int _64bit_sets = bits_size/64;
        printf("Decrypted output is\n");
        for(int i=0;i<= _64bit_sets ;i++) {
                Encrypt_each_64_bit (text_to_bits + 64*i);
        }
        return 0;
}

Output

Decrypted output is
0000111001101001001100011010111010010110111010111111111000010111001011111011111101010011011101011011000000111011100100000010110101000101011000011001000000101000001010011110101001011000111010011001110010110011011110110001101110000000001000001001000110111010

The post Data Encryption Standard (DES) Algorithm appeared first on The Crazy Programmer.



from The Crazy Programmer https://www.thecrazyprogrammer.com/2019/01/data-encryption-standard-des-algorithm.html

Comments

Popular posts from this blog

dotnet sdk list and dotnet sdk latest

Can someone make .NET Core better with a simple global command? Fanie Reynders did and he did it in a simple and elegant way. I'm envious, in fact, because I spec'ed this exact thing out in a meeting a few months ago but I could have just done it like he did and I would have used fewer keystrokes! Last year when .NET Core was just getting started, there was a "DNVM" helper command that you could use to simplify dealing with multiple versions of the .NET SDK on one machine. Later, rather than 'switching global SDK versions,' switching was simplified to be handled on a folder by folder basis. That meant that if you had a project in a folder with no global.json that pinned the SDK version, your project would use the latest installed version. If you liked, you could create a global.json file and pin your project's folder to a specific version. Great, but I would constantly have to google to remember the format for the global.json file, and I'd constan

R vs Python for Machine Learning

There are so many things to learn before to choose which language is good for Machine Learning. We will discuss each and everything about R as well as Python and the situation or problem in which situation we have to use which language. Let’s start Python and R are the two most Commonly used Programming Languages for Machine Learning and because of the popularity of both the languages Novice or you can say fresher are getting confused, whether they should choose R or Python language to commence their career in the Machine learning domain. Don’t worry guys through this article we will discuss R vs Python for Machine Learning. So, without exaggerating this article let’s get started. We will start it from the very Basics things or definitions. R vs Python for Machine Learning Introduction R is a programming language made by statisticians and data miners for statistical analysis and graphics supported by R foundation for statistical computing. R also provides high-quality graphics and

Top Tips For PCB Design Layout

Are you thinking about designing a printed circuit board? PCBs are quite complicated, and you need to make sure that the layout that you choose is going to operate as well as you want it to. For this reason, we have put together some top tips for PCB design layout. Keep reading if you would like to find out more about this. Leave Enough Space One of the most important design tips for PCB layout is that you need to make sure that you are leaving enough space between the components. While many people might think that packing components closely is the best route to take, this can cause problems further down the line. This is why we suggest leaving extra space for the wires that will spread. This way, you’ll have the perfect PCB design layout. Print Out Your Layout Struggling to find out if your components sizes match? Our next tip is to print out your layout and compare the printed version to your actual components. Datasheets can sometimes come with errors, so it doesn’t hurt to do