Here is the arduino DES algorithm which implements a full DES encryption and decoding.
You can set the key and use any plaintext and cipher text and take the algorithm any way you want.
It is very visual in that every step prints to screen all the details so you can see how it works. This way you will quickly grasp the DES algorithm.
You can find the arduino DES algorithm code to download in my example below which is based on the Daniel Otte version (See link below). If you want to see the detailed steps of how a DES algorithm is built up you can look at this page describing the data encryption standard.
Click on the link below to see what the program looks like on the page.
[spoiler]
/*
* Title DES algorithm for the Data Encryption Standard implementation * based on DES algorithm by Daniel Ottee email daniel.otte@rub.de * date 14-02-2012 */ #include <stdint.h> #include <string.h> const uint8_t sbox[256] = { /* S-box 1 */ 0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07, 0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38, 0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50, 0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D, /* S-box 2 */ 0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A, 0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5, 0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F, 0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9, /* S-box 3 */ 0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28, 0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1, 0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7, 0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C, /* S-box 4 */ 0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F, 0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9, 0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84, 0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E, /* S-box 5 */ 0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9, 0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86, 0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E, 0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53, /* S-box 6 */ 0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B, 0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38, 0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6, 0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D, /* S-box 7 */ 0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61, 0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86, 0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92, 0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C, /* S-box 8 */ 0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7, 0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92, 0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58, 0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B }; const uint8_t e_permtab[] ={ 4, 6, /* 4 bytes in 6 bytes out*/ 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 }; const uint8_t p_permtab[] ={ 4, 4, /* 32 bit -> 32 bit */ 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 }; const uint8_t ip_permtab[] ={ 8, 8, /* 64 bit -> 64 bit */ 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 }; const uint8_t inv_ip_permtab[] ={ 8, 8, /* 64 bit -> 64 bit */ 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 }; const uint8_t pc1_permtab[] ={ 8, 7, /* 64 bit -> 56 bit*/ 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 }; const uint8_t pc2_permtab[] ={ 7, 6, /* 56 bit -> 48 bit */ 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 }; const uint8_t splitin6bitword_permtab[] = { 8, 8, /* 64 bit -> 64 bit */ 64, 64, 1, 6, 2, 3, 4, 5, 64, 64, 7, 12, 8, 9, 10, 11, 64, 64, 13, 18, 14, 15, 16, 17, 64, 64, 19, 24, 20, 21, 22, 23, 64, 64, 25, 30, 26, 27, 28, 29, 64, 64, 31, 36, 32, 33, 34, 35, 64, 64, 37, 42, 38, 39, 40, 41, 64, 64, 43, 48, 44, 45, 46, 47 }; const uint8_t shiftkey_permtab[] = { 7, 7, /* 56 bit -> 56 bit */ 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, 1, 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, 29 }; /* 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0 7 E F C Standard DES 2 1 1 1 1 1 1 1 2 2 1 1 1 2 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 8 0 C 4 Meteotime DES */ #define ROTTABLE 0x7EFC byte crypt [8]; byte plaintext [] = { 00,01,02,03,04,05,06,07}; byte keyword [] = { 0x3b,0x38,0x98,0x37,0x15,0x20,0xf7,0x5e}; byte test[8]; boolean DEBUG = true; int i,m; int Dx =0; uint32_t box=0,t; String showprint = ""; uint8_t data[8]; /******************************************************************************/ void setup(){ Serial.begin(19200); Serial.println("Start"); Serial.print ("Keyword = "); for (int j=0;j<8;j++){ if (keyword[j]<0x10) Serial.print("0"); Serial.print(keyword[j],HEX);Serial.print(" "); } Serial.println(); Serial.print ("Plaintext = "); for (int j=0;j<8;j++){ if (plaintext[j]<0x10) Serial.print("0"); Serial.print(plaintext[j],HEX);Serial.print(" "); } Serial.println(); Serial.println("Encrypting"); //void des_enc(void* out, const void* in, const void* key); des_enc( crypt, plaintext, keyword); Serial.print("Encrypted key = "); for (int j=0;j<8;j++){ if (crypt[j]<0x10) Serial.print("0"); Serial.print(crypt[j],HEX);Serial.print(" "); } Serial.println(); Serial.println("Decrypting"); //void des_dec(void* out, const void* in, const void* key); des_dec( plaintext, crypt, keyword); Serial.print("Decrypted key = "); for (int j=0;j<8;j++){ if (plaintext[j]<0x10) Serial.print("0"); Serial.print(plaintext[j],HEX);Serial.print(" "); } Serial.println(); Serial.println("Done"); } void loop(){ } void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){ uint8_t ob; /* in-bytes and out-bytes */ uint8_t byte, bit; /* counter for bit and byte */ ob = ptable[1]; ptable = &(ptable[2]); for(byte=0; byte<ob; ++byte){ uint8_t x,t=0; for(bit=0; bit<8; ++bit){ x=*ptable++ -1 ; t<<=1; if((in[x/8]) & (0x80>>(x%8)) ){ t|=0x01; } } out[byte]=t;test[byte]=t; } } /******************************************************************************/ void changeendian32(uint32_t * a){ *a = (*a & 0x000000FF) << 24 | (*a & 0x0000FF00) << 8 | (*a & 0x00FF0000) >> 8 | (*a & 0xFF000000) >> 24; box=((*a & 0x000000FF) << 24)| (*a & 0x0000FF00) << 8 | (*a & 0x00FF0000) >> 8 | (*a & 0xFF000000) >> 24; } /******************************************************************************/ static inline void shiftkey(uint8_t *key){ uint8_t k[7]; memcpy(k, key, 7); permute((uint8_t*)shiftkey_permtab, k, key); if (DEBUG == true) { Serial.print ("CD[");Serial.print(m);Serial.print ("] 56 xits = "); for (int j=0;j<7;j++){ if (test[j]<0x10) Serial.print("0"); Serial.print(test[j],HEX);Serial.print(" "); print_binary(test[j],8);Serial.print(" "); } Serial.println(); } } /******************************************************************************/ /******************************************************************************/ static inline uint64_t splitin6bitwords(uint64_t a){ uint64_t ret=0; a &= 0x0000ffffffffffffLL; permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret); return ret; } /******************************************************************************/ static inline uint8_t substitute(uint8_t a, uint8_t * sbp){ uint8_t x; x = sbp[a>>1]; x = (a&1)?x&0x0F:x>>4; return x; } /******************************************************************************/ uint32_t des_f(uint32_t r, uint8_t* kr){ uint8_t i; uint32_t ret; uint64_t data; uint8_t *sbp; /* sboxpointer */ permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); showprint ="E 48 bits = ";printout1(0,6); for(i=0; i<7; ++i) {((uint8_t*)&data)[i] ^= kr[i];} if (DEBUG == true) { Serial.print ("ExorKS 48 bits = "); for (int j=0;j<6;j++){ if (((uint8_t*)&data)[j]<0x10) Serial.print("0"); Serial.print(((uint8_t*)&data)[j],HEX);Serial.print(" "); print_binary(((uint8_t*)&data)[j],8);Serial.print(" "); } Serial.println(); } /* Sbox substitution */ data = splitin6bitwords(data); sbp=(uint8_t*)sbox; for(i=0; i<8; ++i){ uint8_t x; x = substitute(((uint8_t*)&data)[i], sbp); t<<=4; t |= x; sbp += 32; } changeendian32(&t); if (DEBUG == true) { Serial.print ("Sbox 32 bits = "); if (box/0x1000000<0x10) Serial.print("0"); Serial.print(box/0x1000000,HEX);Serial.print(" "); print_binary(box/0x1000000,8);Serial.print(" "); if (box/0x10000&0xFF<0x10) Serial.print("0"); Serial.print(box/0x10000&0xFF,HEX);Serial.print(" "); print_binary(box/0x10000&0xFF,8);Serial.print(" "); if (((box/0x100)&0xFF)<0x10) Serial.print("0"); Serial.print(box/0x100&0xFF,HEX);Serial.print(" "); print_binary(box/0x100,8);Serial.print(" "); if (box&0xFF<0x10) Serial.print("0"); Serial.print(box&0xFF,HEX);Serial.print(" "); print_binary(box&0xFF,8); Serial.println(); } permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret); showprint = "P 32 bits = "; printout1(0,4); return ret; } /******************************************************************************/ void des_enc(void* out, const void* in, const void* key){ #define R *((uint32_t*)&(data[4])) #define L *((uint32_t*)&(data[0])) uint8_t kr[6],k[7]; permute((uint8_t*)ip_permtab, (uint8_t*)in, data); showprint = "L[0] 32 bits = "; printout1(0,4); showprint = "R[0] 32 bits = "; printout1(4,8); permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); showprint = "CD[0] 56 bits = "; printout1(0,7); for(i=0; i<8; i++){ Dx=i*2+1; if (DEBUG == true) { Serial.print("Round ");Serial.println(Dx); } shiftkey(k); if(ROTTABLE&((1<<((i<<1)+0))) ) shiftkey(k); permute((uint8_t*)pc2_permtab, k, kr); showprint = "KS 48 bits = "; printout1(0,6); L ^= des_f(R, kr); showprint = "L[i] 32 bits = "; printout2(0,4); showprint = "R[i] 32 bits = "; printout2(4,8); Dx=i*2+2; if (DEBUG == true) { Serial.print("Round ");Serial.println(Dx); } shiftkey(k); if(ROTTABLE&((1<<((i<<1)+1))) ) shiftkey(k); permute((uint8_t*)pc2_permtab, k, kr); showprint = "KS 48 bits = "; printout1(0,6); R ^= des_f(L, kr); showprint = "L[i] 32 bits = "; printout2(0,4); showprint = "R[i] 32 bits = "; printout2(4,8); } /* L <-> R*/ R ^= L; L ^= R; R ^= L; showprint = "LR[16] 64 bits = "; printout2(0,8); permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out); showprint = "Crypt 64 bits = "; printout1(0,8); } /******************************************************************************/ void des_dec(void* out, const void* in, const uint8_t* key){ #define R *((uint32_t*)&(data[4])) #define L *((uint32_t*)&(data[0])) uint8_t kr[6],k[7]; Serial.print("crypt 64 bits = "); for (int j=0;j<8;j++){ if (crypt[j]<0x10) Serial.print("0"); Serial.print(crypt[j],HEX);Serial.print(" "); print_binary(crypt[j],8);Serial.print(" "); } Serial.println(); Serial.print("key 64 bits = "); for (int j=0;j<8;j++){ if (key[j]<0x10) Serial.print("0"); Serial.print(key[j],HEX);Serial.print(" "); print_binary(key[j],8);Serial.print(" "); } Serial.println(); permute((uint8_t*)ip_permtab, (uint8_t*)in, data); showprint = "L[0] 32 bits = "; printout1(0,4); showprint = "R[0] 32 bits = "; printout1(4,8); permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); showprint = "CD[0] 56 bits = "; printout1(0,7); for(i=7; i>=0; i--){ Dx=i*2+2; if (DEBUG == true) { Serial.print("Round ");Serial.println(Dx); } permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); for (m=1;m<Dx+1;m++){ shiftkey(k); if(ROTTABLE&(1<<(m-1))) shiftkey(k); } permute((uint8_t*)pc2_permtab, k, kr); showprint = "KS 48 bits = "; printout1(0,6); L ^= des_f(R, kr); showprint = "L[i] 32 bits = "; printout2(0,4); showprint = "R[i] 32 bits = "; printout2(4,8); Dx=i*2+1; if (DEBUG == true) { Serial.print("Round ");Serial.println(Dx); } permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); for (m=1;m<Dx+1;m++){ shiftkey(k); if(ROTTABLE&(1<<(m-1))) shiftkey(k); } permute((uint8_t*)pc2_permtab, k, kr); showprint = "KS 48 bits = "; printout1(0,6); R ^= des_f(L, kr); showprint = "L[i] 32 bits = "; printout2(0,4); showprint = "R[i] 32 bits = "; printout2(4,8); } /* L <-> R*/ R ^= L; L ^= R; R ^= L; showprint = "LR[16] 64 bits = "; printout2(0,8); permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out); showprint = "Plain 64 bits = "; printout1(0,8); } void print_binary(uint64_t v, int num_places) { uint64_t mask=0, n; for (n=1; n<=num_places; n++) { mask = (mask << 1) | 0x00000001; } v = v & mask; // truncate v to specified number of places while(num_places) { if (v & (0x00000001 << num_places-1)) { Serial.print("1"); } else { Serial.print("0"); } --num_places; if(((num_places%8) == 0) && (num_places != 0)) { Serial.print(" "); } } } void printout1(int min,int max) { if (DEBUG == true) { Serial.print (showprint); for (int j=min;j<max;j++){ if (test[j]<0x10) Serial.print("0"); Serial.print(test[j],HEX);Serial.print(" "); print_binary(test[j],8);Serial.print(" "); } Serial.println(); } } void printout2(int min,int max) { if (DEBUG == true) { Serial.print (showprint); for (int j=min;j<max;j++){ if (data[j]<0x10) Serial.print("0"); Serial.print(data[j],HEX);Serial.print(" "); print_binary(data[j],8);Serial.print(" "); } Serial.println(); } }
[/spoiler]
Other DES algorithm related stuff:
There are other encryption techniques such as AES etc used which can be seen here.
http://www.efgh.com/software/des.htm
http://dvd-copy-software-review.toptenreviews.com/the-dos-and-donts-of-decryption.html
There is a very good excel version of such a process which visualizes the whole process that can be downloaded from the bottom of the link above.
Other version non arduino of the DES algorithm by Daniel Otte.
Here you can find my other arduino projects.