diff --git a/DES.cpp b/DES.cpp index 503e41a..a3916b0 100644 --- a/DES.cpp +++ b/DES.cpp @@ -1,154 +1,154 @@ #include "DES.h" const uint8_t sbox[256] PROGMEM = { - /* 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 + /* 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[] PROGMEM = { - 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 + 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[] PROGMEM = { - 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 + 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[] PROGMEM = { - 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 + 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[] PROGMEM = { - 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 + 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[] PROGMEM = { - 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 + 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[] PROGMEM = { - 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 + 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[] PROGMEM = { - 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 + 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[] PROGMEM = { - 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 + 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 }; const uint8_t shiftkeyinv_permtab[] PROGMEM = { - 7, 7, - 28, 1, 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, - 56, 29, 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 + 7, 7, + 28, 1, 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, + 56, 29, 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 }; /* @@ -170,15 +170,15 @@ const uint8_t shiftkeyinv_permtab[] PROGMEM = { 2 1 1 0 */ -#define ROTTABLE 0x7EFC +#define ROTTABLE 0x7EFC #define ROTTABLE_INV 0x3F7E /******************************************************************************/ -DES::DES(){ - sprintf((char *)key,"000000000000000000000000\0"); - byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }; - memcpy(iv,ar_iv,8); - memcpy(&IVC,ar_iv,8); - arr_pad[0] = 0x01; +DES::DES() { + sprintf((char*)key, "000000000000000000000000\0"); + uint8_t ar_iv[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; + memcpy(iv, ar_iv, 8); + memcpy(&IVC, ar_iv, 8); + arr_pad[0] = 0x01; arr_pad[1] = 0x02; arr_pad[2] = 0x03; arr_pad[3] = 0x04; @@ -189,406 +189,453 @@ DES::DES(){ /*****************************************************************************/ -void DES::init(const void* m_key,unsigned long long int IVCl){ - sprintf((char *)key,"%s",m_key); - memcpy(iv,&IVCl,8); +void DES::init(const void* m_key, unsigned long long int IVCl) { + sprintf((char*)key, "%s", m_key); + memcpy(iv, &IVCl, 8); IVC = IVCl; } /*****************************************************************************/ -void DES::init(const void* m_key){ - sprintf((char *)key,"%s",m_key); +void DES::init(const void* m_key) { + sprintf((char*)key, "%s", m_key); } /*****************************************************************************/ -void DES::change_key(const void* m_key){ - sprintf((char *)key,"000000000000000000000000\0"); - sprintf((char *)key,"%s",m_key); +void DES::change_key(const void* m_key) { + sprintf((char*)key, "000000000000000000000000\0"); + sprintf((char*)key, "%s", m_key); } /*****************************************************************************/ -void DES::set_IV(unsigned long long int IVCl){ - memcpy(iv,&IVCl,8); +void DES::set_IV(unsigned long long int IVCl) { + memcpy(iv, &IVCl, 8); IVC = IVCl; } /******************************************************************************/ -void DES::get_IV(byte *out){ - memcpy(out,&IVC,8); +void DES::get_IV(uint8_t* out) { + memcpy(out, &IVC, 8); } /******************************************************************************/ -unsigned long long int DES::get_IV_int(){ +unsigned long long int DES::get_IV_int() { return IVC; } /*****************************************************************************/ -void DES::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 = pgm_read_byte(&ptable[1]); - ptable = &(ptable[2]); - for(byte=0; byte>(x%8)) ){ - t|=0x01; - } - } - out[byte]=t; - } +void DES::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 = pgm_read_byte(&ptable[1]); + ptable = &(ptable[2]); + for (byte = 0; byte < ob; ++byte) { + uint8_t x, t = 0; + for (bit = 0; bit < 8; ++bit) { + x = pgm_read_byte(ptable++) - 1; + t <<= 1; + if ((in[x / 8]) & (0x80 >> (x % 8))) { + t |= 0x01; + } + } + out[byte] = t; + } } /******************************************************************************/ -void DES::changeendian32(uint32_t * a){ - *a = (*a & 0x000000FF) << 24 | - (*a & 0x0000FF00) << 8 | - (*a & 0x00FF0000) >> 8 | - (*a & 0xFF000000) >> 24; +void DES::changeendian32(uint32_t* a) { + *a = (*a & 0x000000FF) << 24 | + (*a & 0x0000FF00) << 8 | + (*a & 0x00FF0000) >> 8 | + (*a & 0xFF000000) >> 24; } /******************************************************************************/ //static inline -void DES::shiftkey(uint8_t *key){ - uint8_t k[7]; - memcpy(k, key, 7); - permute((uint8_t*)shiftkey_permtab, k, key); +void DES::shiftkey(uint8_t* key) { + uint8_t k[7]; + memcpy(k, key, 7); + permute((uint8_t*)shiftkey_permtab, k, key); } /******************************************************************************/ //static inline -void DES::shiftkey_inv(uint8_t *key){ - uint8_t k[7]; - memcpy(k, key, 7); - permute((uint8_t*)shiftkeyinv_permtab, k, key); - +void DES::shiftkey_inv(uint8_t* key) { + uint8_t k[7]; + memcpy(k, key, 7); + permute((uint8_t*)shiftkeyinv_permtab, k, key); + } /******************************************************************************/ //static inline -uint64_t DES::splitin6bitwords(uint64_t a){ - uint64_t ret=0; - a &= 0x0000ffffffffffffLL; - permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret); - return ret; +uint64_t DES::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 DES::substitute(uint8_t a, uint8_t * sbp){ - uint8_t x; - x = pgm_read_byte(&sbp[a>>1]); - x = (a&1)?x&0x0F:x>>4; - return x; - +uint8_t DES::substitute(uint8_t a, uint8_t* sbp) { + uint8_t x; + x = pgm_read_byte(&sbp[a >> 1]); + x = (a & 1) ? x & 0x0F : x >> 4; + return x; + } /******************************************************************************/ -uint32_t DES::des_f(uint32_t r, uint8_t* kr){ - uint8_t i; - uint32_t t=0,ret; - uint64_t data; - uint8_t *sbp; /* sboxpointer */ - permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); - for(i=0; i<7; ++i) - ((uint8_t*)&data)[i] ^= kr[i]; - - /* 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); - - permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret); - - return ret; +uint32_t DES::des_f(uint32_t r, uint8_t* kr) { + uint8_t i; + uint32_t t = 0, ret; + uint64_t data; + uint8_t* sbp; /* sboxpointer */ + permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); + for (i = 0; i < 7; ++i) + ((uint8_t*)&data)[i] ^= kr[i]; + + /* 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); + + permute((uint8_t*)p_permtab, (uint8_t*)&t, (uint8_t*)&ret); + + return ret; } /******************************************************************************/ -void DES::encrypt(void* out, const void* in, const void* key){ +void DES::encrypt(void* out, const void* in, const void* key) { #define R (data.v32[1]) #define L (data.v32[0]) - uint8_t kr[6],k[7]; - uint8_t i; - union { - uint8_t v8[8]; - uint32_t v32[2]; - } data; - - permute((uint8_t*)ip_permtab, (uint8_t*)in, data.v8); - permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); - for(i=0; i<8; ++i){ - shiftkey(k); - if(ROTTABLE&((1<<((i<<1)+0))) ) - shiftkey(k); - permute((uint8_t*)pc2_permtab, k, kr); - L ^= des_f(R, kr); - - shiftkey(k); - if(ROTTABLE&((1<<((i<<1)+1))) ) - shiftkey(k); - permute((uint8_t*)pc2_permtab, k, kr); - R ^= des_f(L, kr); - - } - /* L <-> R*/ - R ^= L; - L ^= R; - R ^= L; - permute((uint8_t*)inv_ip_permtab, data.v8, (uint8_t*)out); + uint8_t kr[6], k[7]; + uint8_t i; + union { + uint8_t v8[8]; + uint32_t v32[2]; + } data; + + permute((uint8_t*)ip_permtab, (uint8_t*)in, data.v8); + permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); + for (i = 0; i < 8; ++i) { + shiftkey(k); + if (ROTTABLE & ((1 << ((i << 1) + 0)))) + shiftkey(k); + permute((uint8_t*)pc2_permtab, k, kr); + L ^= des_f(R, kr); + + shiftkey(k); + if (ROTTABLE & ((1 << ((i << 1) + 1)))) + shiftkey(k); + permute((uint8_t*)pc2_permtab, k, kr); + R ^= des_f(L, kr); + + } + /* L <-> R*/ + R ^= L; + L ^= R; + R ^= L; + permute((uint8_t*)inv_ip_permtab, data.v8, (uint8_t*)out); +} + +/******************************************************************************/ + +void DES::decrypt(void* out, const void* in, const uint8_t* key) { + uint8_t kr[6], k[7]; + union { + uint8_t v8[8]; + uint32_t v32[2]; + } data; + int8_t i; + permute((uint8_t*)ip_permtab, (uint8_t*)in, data.v8); + permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); + for (i = 7; i >= 0; --i) { + + permute((uint8_t*)pc2_permtab, k, kr); + L ^= des_f(R, kr); + shiftkey_inv(k); + if (ROTTABLE & ((1 << ((i << 1) + 1)))) { + shiftkey_inv(k); + } + + permute((uint8_t*)pc2_permtab, k, kr); + R ^= des_f(L, kr); + shiftkey_inv(k); + if (ROTTABLE & ((1 << ((i << 1) + 0)))) { + shiftkey_inv(k); + } + + } + /* L <-> R*/ + R ^= L; + L ^= R; + R ^= L; + permute((uint8_t*)inv_ip_permtab, data.v8, (uint8_t*)out); +} + +/******************************************************************************/ + +void DES::tripleEncrypt(void* out, void* in, const void* key) { + encrypt(out, in, (uint8_t*)key + 0); + decrypt(out, out, (uint8_t*)key + 8); + encrypt(out, out, (uint8_t*)key + 16); +} + +/******************************************************************************/ + +void DES::tripleDecrypt(void* out, void* in, const uint8_t* key) { + decrypt(out, in, (uint8_t*)key + 16); + encrypt(out, out, (uint8_t*)key + 8); + decrypt(out, out, (uint8_t*)key + 0); } /******************************************************************************/ -void DES::decrypt(void* out, const void* in, const uint8_t* key){ - uint8_t kr[6],k[7]; - union { - uint8_t v8[8]; - uint32_t v32[2]; - } data; - int8_t i; - permute((uint8_t*)ip_permtab, (uint8_t*)in, data.v8); - permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); - for(i=7; i>=0; --i){ - - permute((uint8_t*)pc2_permtab, k, kr); - L ^= des_f(R, kr); - shiftkey_inv(k); - if(ROTTABLE&((1<<((i<<1)+1))) ){ - shiftkey_inv(k); - } - - permute((uint8_t*)pc2_permtab, k, kr); - R ^= des_f(L, kr); - shiftkey_inv(k); - if(ROTTABLE&((1<<((i<<1)+0))) ){ - shiftkey_inv(k); - } - - } - /* L <-> R*/ - R ^= L; - L ^= R; - R ^= L; - permute((uint8_t*)inv_ip_permtab, data.v8, (uint8_t*)out); +void DES::xor_blocks(uint8_t* dst, const uint8_t* src, size_t len) { + for (size_t i = 0; i < len; i++) { + dst[i] ^= src[i]; + } } /******************************************************************************/ -void DES::tripleEncrypt(void* out, void* in, const void* key){ - encrypt(out, in, (uint8_t*)key + 0); - decrypt(out, out, (uint8_t*)key + 8); - encrypt(out, out, (uint8_t*)key +16); +void DES::decrypt_3des_cbc(uint8_t* ciphertext, size_t ciphertext_len, uint8_t* key, uint8_t* iv, uint8_t* plaintext) { + if (ciphertext_len % 8 != 0) { + printf("Error: Ciphertext length must be a multiple of 8 bytes.\n"); + return; + } + uint8_t block[8]; + uint8_t prev_block[8]; + memcpy(prev_block, iv, 8); + for (size_t i = 0; i < ciphertext_len; i += 8) { + tripleDecrypt(block, ciphertext + i, key); + xor_blocks(block, prev_block, 8); + memcpy(plaintext + i, block, 8); + memcpy(prev_block, ciphertext + i, 8); + } } /******************************************************************************/ -void DES::tripleDecrypt(void* out, void* in, const uint8_t* key){ - decrypt(out, in, (uint8_t*)key +16); - encrypt(out, out, (uint8_t*)key + 8); - decrypt(out, out, (uint8_t*)key + 0); +void DES::encrypt_3des_cbc(uint8_t* plaintext, size_t plaintext_len, uint8_t* key, uint8_t* iv, uint8_t* ciphertext) { + if (plaintext_len % 8 != 0) { + printf("Error: Plaintext length must be a multiple of 8 bytes.\n"); + return; + } + uint8_t block[8]; + uint8_t prev_block[8]; + memcpy(prev_block, iv, 8); + for (size_t i = 0; i < plaintext_len; i += 8) { + memcpy(block, plaintext + i, 8); + xor_blocks(block, prev_block, 8); + tripleEncrypt(ciphertext + i, block, key); + memcpy(prev_block, ciphertext + i, 8); + } } /******************************************************************************/ -void DES::iv_inc(){ +void DES::iv_inc() { IVC += 1; - memcpy(iv,&IVC,8); + memcpy(iv, &IVC, 8); } /******************************************************************************/ -byte* DES::get_key(){ +uint8_t* DES::get_key() { return key; } /******************************************************************************/ -int DES::get_size(){ +int DES::get_size() { return size; } /******************************************************************************/ -void DES::set_size(int sizel){ +void DES::set_size(int sizel) { size = sizel; } /******************************************************************************/ -void DES::calc_size_n_pad(int p_size){ +void DES::calc_size_n_pad(int p_size) { int s_of_p = p_size - 1; - if ( s_of_p % 8 == 0){ - size = s_of_p; - }else{ - size = s_of_p + (8-(s_of_p % 8)); + if (s_of_p % 8 == 0) { + size = s_of_p; + } + else { + size = s_of_p + (8 - (s_of_p % 8)); } pad = size - s_of_p; -} +} /******************************************************************************/ -void DES::padPlaintext(void* in,byte* out) +void DES::padPlaintext(void* in, uint8_t* out) { - memcpy(out,in,size); - for (int i = size-pad; i < size; i++){; + memcpy(out, in, size); + for (int i = size - pad; i < size; i++) { + ; out[i] = arr_pad[pad - 1]; } } /******************************************************************************/ -bool DES::CheckPad(byte* in,int lsize){ - if (in[lsize-1] <= 0x08){ - int lpad = (int)in[lsize-1]; - for (int i = lsize - 1; i >= lsize-lpad; i--){ - if (arr_pad[lpad - 1] != in[i]){ +bool DES::CheckPad(uint8_t* in, int lsize) { + if (in[lsize - 1] <= 0x08) { + int lpad = (int)in[lsize - 1]; + for (int i = lsize - 1; i >= lsize - lpad; i--) { + if (arr_pad[lpad - 1] != in[i]) { return false; } } - }else{ + } + else { return true; } -return true; + return true; } /******************************************************************************/ -void DES::tdesCbcEncipher(byte* in,byte* out) +void DES::tdesCbcEncipher(uint8_t* in, uint8_t* out) { - #if defined(DES_PRINT) +#if defined(DES_PRINT) printf_P(PSTR("\n")); printf_P(PSTR("====== Triple-DES CBC encipher test ======\n")); printf_P(PSTR("Encrypt...")); - #endif - for (int i = 0; i < size; i += 8) - { - //CBC algorithm - //IMPORTANT: THIS WILL MODIFY THE INPUT ARRAY!!! - for (uint8_t xorIdx = 0; xorIdx < 8; xorIdx++) - { - // 0 -> use IV; >0 -> use ciphertext - if (i == 0) - { - in[i + xorIdx] = in[i + xorIdx] ^ iv[xorIdx]; - } - else - { - in[i + xorIdx] = in[i + xorIdx] ^ out[(i - 8) + xorIdx]; - } - } - - tripleEncrypt(out + i, in + i, key); - } - #if defined(DES_PRINT) +#endif + for (int i = 0; i < size; i += 8) + { + //CBC algorithm + //IMPORTANT: THIS WILL MODIFY THE INPUT ARRAY!!! + for (uint8_t xorIdx = 0; xorIdx < 8; xorIdx++) + { + // 0 -> use IV; >0 -> use ciphertext + if (i == 0) + { + in[i + xorIdx] = in[i + xorIdx] ^ iv[xorIdx]; + } + else + { + in[i + xorIdx] = in[i + xorIdx] ^ out[(i - 8) + xorIdx]; + } + } + + tripleEncrypt(out + i, in + i, key); + } +#if defined(DES_PRINT) printArray(out); - #endif +#endif } /******************************************************************************/ -void DES::tdesCbcDecipher(byte* in,byte* out) +void DES::tdesCbcDecipher(uint8_t* in, uint8_t* out) { - #if defined(DES_PRINT) +#if defined(DES_PRINT) printf_P(PSTR("\n")); printf_P(PSTR("====== Triple-DES CBC decipher test ======\n")); printf_P(PSTR("Decrypt...")); - #endif - for (int i = 0; i < size; i += 8) - { - tripleDecrypt(out + i, in + i, key); - - //CBC algorithm - for (uint8_t xorIdx = 0; xorIdx < 8; xorIdx++) - { - // 0 -> use IV; >0 -> use ciphertext - if (i == 0) - { - out[i + xorIdx] = out[i + xorIdx] ^ iv[xorIdx]; - } - else - { - out[i + xorIdx] = out[i + xorIdx] ^ in[(i - 8) + xorIdx]; - } - } - } - #if defined(DES_PRINT) - printArray((byte*)out,(bool)true); - #endif +#endif + for (int i = 0; i < size; i += 8) + { + tripleDecrypt(out + i, in + i, key); + + //CBC algorithm + for (uint8_t xorIdx = 0; xorIdx < 8; xorIdx++) + { + // 0 -> use IV; >0 -> use ciphertext + if (i == 0) + { + out[i + xorIdx] = out[i + xorIdx] ^ iv[xorIdx]; + } + else + { + out[i + xorIdx] = out[i + xorIdx] ^ in[(i - 8) + xorIdx]; + } + } + } +#if defined(DES_PRINT) + printArray((uint8_t*)out, (bool)true); +#endif } /******************************************************************************/ -void DES::printArray(byte output[],bool p_pad) +void DES::printArray(uint8_t output[], bool p_pad) { -uint8_t i,j; -uint8_t loops = size/8; -uint8_t outp = 8; -for (j = 0; j < loops; j += 1){ - if (p_pad && (j == (loops - 1)) ) { outp = 8 - pad; } - for (i = 0; i < outp; i++) - { - printf_P(PSTR("%c"),output[j*8 + i]); - } -} - printf_P(PSTR("\n")); + uint8_t i, j; + uint8_t loops = size / 8; + uint8_t outp = 8; + for (j = 0; j < loops; j += 1) { + if (p_pad && (j == (loops - 1))) { outp = 8 - pad; } + for (i = 0; i < outp; i++) + { + printf_P(PSTR("%c"), output[j * 8 + i]); + } + } + printf_P(PSTR("\n")); } /******************************************************************************/ -void DES::printArray(byte output[],int sizel) +void DES::printArray(uint8_t output[], int sizel) { - for (int i = 0; i < sizel; i++) - { - printf_P(PSTR("%x"),output[i]); - } - printf_P(PSTR("\n")); + for (int i = 0; i < sizel; i++) + { + printf_P(PSTR("%x"), output[i]); + } + printf_P(PSTR("\n")); } /******************************************************************************/ -void DES::do_3des_encrypt(byte *plain,int size_p,byte *cipher,const void *key, bool inc){ - if (inc){ +void DES::do_3des_encrypt(uint8_t* plain, int size_p, uint8_t* cipher, const void* key, bool inc) { + if (inc) { iv_inc(); } calc_size_n_pad(size_p); - byte plain_p[get_size()]; - padPlaintext(plain,plain_p); - change_key (key); - tdesCbcEncipher(plain_p,cipher); + uint8_t plain_p[get_size()]; + padPlaintext(plain, plain_p); + change_key(key); + tdesCbcEncipher(plain_p, cipher); } /******************************************************************************/ -void DES::do_3des_decrypt(byte *cipher,int size_c,byte *plain,const void *key, unsigned long long int ivl){ +void DES::do_3des_decrypt(uint8_t* cipher, int size_c, uint8_t* plain, const void* key, unsigned long long int ivl) { size = size_c; - change_key (key); + change_key(key); set_IV(ivl); - tdesCbcDecipher(cipher,plain); + tdesCbcDecipher(cipher, plain); } /******************************************************************************/ #if defined(DES_LINUX) -double DES::millis(){ +double DES::millis() { gettimeofday(&tv, NULL); return (tv.tv_sec + 0.000001 * tv.tv_usec); } diff --git a/DES.h b/DES.h index 9d133c6..26d9634 100644 --- a/DES.h +++ b/DES.h @@ -1,7 +1,7 @@ /* DES.h - Library for DES and 3DES encryption and decryption Ported to the Arduino platform 2013 by Tim Riemann - + Original version taken from the AVR-Crypto-Lib (http://www.das-labor.org/wiki/AVR-Crypto-Lib) Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de) @@ -30,7 +30,7 @@ #include "DES_config.h" -/* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA. + /* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA. * Also we only implement the three key mode */ #define tdea_enc tdes_enc @@ -38,324 +38,331 @@ class DES { - public: - /** \fn void decrypt(void* out, const void* in, const void* key) - * \brief encrypt a block with DES - * - * This function encrypts a block of 64 bits (8 bytes) with the DES algorithm. - * Key expansion is done automatically. The key is 64 bits long, but note that - * only 56 bits are used (the LSB of each byte is dropped). The input and output - * blocks may overlap. - * - * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to - * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from - * \param key pointer to the key (64 bit = 8 byte) - */ - void encrypt(void* out, const void* in, const void* key); - - /** \fn void encrypt(void* out, const void* in, const void* key) - * \brief decrypt a block with DES - * - * This function decrypts a block of 64 bits (8 bytes) with the DES algorithm. - * Key expansion is done automatically. The key is 64 bits long, but note that - * only 56 bits are used (the LSB of each byte is dropped). The input and output - * blocks may overlap. - * - * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to - * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from - * \param key pointer to the key (64 bit = 8 byte) - */ - void decrypt(void* out, const void* in, const uint8_t* key); - - /** \fn void tripleEncrypt(void* out, const void* in, const void* key) - * \brief encrypt a block with Tripple-DES - * - * This function encrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE) - * algorithm. Key expansion is done automatically. The key is 192 bits long, but - * note that only 178 bits are used (the LSB of each byte is dropped). The input - * and output blocks may overlap. - * - * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to - * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from - * \param key pointer to the key (192 bit = 24 byte) - */ - void tripleEncrypt(void* out, void* in, const void* key); - - /** \fn void tripleDecrypt(void* out, const void* in, const void* key) - * \brief decrypt a block with Tripple-DES - * - * This function decrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE) - * algorithm. Key expansion is done automatically. The key is 192 bits long, but - * note that only 178 bits are used (the LSB of each byte is dropped). The input - * and output blocks may overlap. - * - * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to - * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from - * \param key pointer to the key (192 bit = 24 byte) - */ - void tripleDecrypt(void* out, void* in, const uint8_t* key); - - /** \fn DES() - * \brief DES constructor - * - * This function initialized an instance of DES - */ - DES(); - - /** \fn void init(const void* m_key,unsigned long long int IVCl) - * \brief initiallize the key and IVC and IV array - * - * This function initialized the basic variables needed for 3DES - * - * \param m_key (64 bit = 8 byte) - * \param IVCl int or hex value of iv , ex. 0x0000000000000001 - */ - void init(const void* m_key,unsigned long long int IVCl); - - /** \fn void init(const void* m_key) - * \brief initiallize the key - * - * This function initialized the basic variables needed for DES - * - * \param m_key (64 bit = 8 byte) - */ - void init(const void* m_key); - - /** \fn void change_key(const char* m_key); - * \brief change the key for DEs and 3DES - * - * This function changes the key variable needed for DES - * - * \param m_key (64 bit = 8 byte) - */ - void change_key(const void* m_key); - - /** \fn void change_IV(unsigned long long int IVCl); - * \brief Change IVC and iv - * - * This function changes the ivc and iv variables needed for 3DES - * - * \param IVCl int or hex value of iv , ex. 0x0000000000000001 - */ - void set_IV(unsigned long long int IVCl); - - /** Getter method for IV - * - * This function return the IV - * @param *out byte pointer that gets the IV. - * @return none, the IV is writed to the out pointer. - */ - void get_IV(byte *out); - - /** Getter method for IV - * - * This function return the IV - * @param out byte pointer that gets the IV. - * @return none, the IV is writed to the out pointer. - */ - unsigned long long int get_IV_int(); - - /** \fn voiv_inc() - * \brief inrease the IVC and iv but 1 - * - * This function increased the VI by one step in order to have a different IV each time - * - */ - void iv_inc(); - - /** \fn get_key() - * \brief getter method for key - * - * This function return the key - * @return returns the key - - */ - byte* get_key(); - - /** \fn get_size() - * \brief getter method for size - * - * This function return the size - * @return returns the size - - */ - int get_size(); - - /** Setter method for size - * - * This function sets the size of the plaintext+pad - * - */ - void set_size(int sizel); - - /** \fn calc_size_n_pad(uint8_t p_size) - * \brief calculates the size of the plaintext and the padding - * - * calculates the size of theplaintext with the padding - * and the size of the padding needed. Moreover it stores them in their variables. - * - * \param p_size the size of the byte array ex sizeof(plaintext) - */ - void calc_size_n_pad(int p_size); - - /** \fn padPlaintext(void* in,byte* out) - * \brief pads the plaintext - * - * This function pads the plaintext and returns an char array with the - * plaintext and the padding in order for the plaintext to be compatible with - * 8bit size blocks required by 3DES - * - * \param in the string of the plaintext in a byte array - * \param out the string of the padded plaintext in a byte array - */ - void padPlaintext(void* in,byte* out); - - /** \fn CheckPad(void* in,int size) - * \brief check the if the padding is correct - * - * This functions checks the padding of the plaintext. - * - * \param *in the string of the plaintext in a byte array - * \param size the size of the string - * \return true if correct / false if not - */ - bool CheckPad(byte* in,int size); - - /** \fn tdesCbcEncipher(byte* in,byte* out) - * \brief the main encrypt 3DES with IV function - * - * This function uses the IV to xor (^) the first block of the string - * and encrypts it using tripleEncrypt function - * - * \param in the string of the plaintext in a byte array - * \param out the string of the ciphertext in a byte array - */ - void tdesCbcEncipher(byte* in,byte* out); - - /** \fn tdesCbcDecipher(byte* in,byte* out) - * \brief the main decrypt 3DES with IV function - * - * This function if the reverse of the tdesCbcEncipher function. - * used the IV and then the tripleDecrypt - * - * \param in the string of the ciphertext in a byte array - * \param out the string of the plaintext in a byte array - */ - void tdesCbcDecipher(byte* in,byte* out); - - /** \fn tprintArray(byte output[],bool p_pad = true) - * \brief Prints the array given - * - * This function prints the given array with size equal \var size - * and pad equal \var pad. It is mainlly used for debugging purpuses or to output the string. - * - * \param output the string of the plaintext in a byte array - * \param p_pad optional, used to print with out the padding characters - */ - void printArray(byte output[],bool p_pad = true); - - /** Prints the array given. - * - * This function prints the given array in Hexadecimal. - * - * @param output[] the string of the text in a byte array - * @param sizel the size of the array. - */ - void printArray(byte output[],int sizel); - - /** User friendly implementation of AES-CBC encryption. - * - * @param *plain pointer to the plaintext - * @param size_p size of the plaintext - * @param *cipher pointer to the ciphertext - * @param *key pointer to the key that will be used. - * @param inc optional parameter to automaticaly increase IV - * @note The key will be stored in class variable. - */ - void do_3des_encrypt(byte *plain,int size_p,byte *cipher,const void *key, bool inc = false); - - /** User friendly implementation of AES-CBC decryption. - * - * @param *cipher pointer to the ciphertext - * @param size_c size of the ciphertext - * @param *plain pointer to the plaintext - * @param *key pointer to the key that will be used. - * @param ivl the initialization vector IV that will be used for decryption. - * @note The key will be stored in class variable. - */ - void do_3des_decrypt(byte *cipher,int size_c,byte *plain,const void *key, unsigned long long int ivl); - #if defined(DES_LINUX) - /** - * used in linux in order to retrieve the time in milliseconds. - * - * @return returns the milliseconds in a double format. - */ - double millis(); - #endif - private: - /** Permutation for DES. - * @param *ptable the permutaion table to be used. - * @param *in the pointer that holds the data before the permutations. - * @param *out the pointer that holds the data after the permutation. - * @return none, the output is inside the out pointer - * - */ - void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out); - - /** change endian form. - * @param *a the byte to change endian - */ - void changeendian32(uint32_t * a); - - /** used to shift the key. - * Used the shiftkey_permtab permutation table. - * @param *key the key to be shifted. - * - */ - inline void shiftkey(uint8_t *key); - - /** used to shift the key back. - * Used the shiftkeyinv_permtab permutation table. - * @param *key the key to be shifted. - * - */ - inline void shiftkey_inv(uint8_t *key); - - /** splits in 6 bit words - * - * @param a uint64_t size that will be slitted, permuted and returned. - * @return the permuted a. - * - */ - inline uint64_t splitin6bitwords(uint64_t a); - - /** main function for the substitutions - * @param a array position - * @param *sbp array to read byte from - * @returns the substituted byte. - * - */ - inline uint8_t substitute(uint8_t a, uint8_t * sbp); - - /** Primary function of DES. - * Used in encryption and decryption process. - * - * @param r unsigned intefer 32 bit, Data to be permuted. - * @param kr pointer of unsigned integers 8 bit, Data to be XOR with r after permutation - * @return - * - */ - uint32_t des_f(uint32_t r, uint8_t* kr); - byte key[24];/**< holds the key for the encryption */ - unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */ - byte iv[8];/**< holds the initialization vector that will be used in the cipher. */ - int pad;/**< holds the size of the padding. */ - int size;/**< hold the size of the plaintext to be ciphered */ - #if defined(DES_LINUX) - timeval tv;/**< holds the time value on linux */ - #endif - - byte arr_pad[7];/**< holds the hexadecimal padding values, initialisation in the constructor */ +public: + /** \fn void decrypt(void* out, const void* in, const void* key) + * \brief encrypt a block with DES + * + * This function encrypts a block of 64 bits (8 bytes) with the DES algorithm. + * Key expansion is done automatically. The key is 64 bits long, but note that + * only 56 bits are used (the LSB of each byte is dropped). The input and output + * blocks may overlap. + * + * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to + * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from + * \param key pointer to the key (64 bit = 8 byte) + */ + void encrypt(void* out, const void* in, const void* key); + + /** \fn void encrypt(void* out, const void* in, const void* key) + * \brief decrypt a block with DES + * + * This function decrypts a block of 64 bits (8 bytes) with the DES algorithm. + * Key expansion is done automatically. The key is 64 bits long, but note that + * only 56 bits are used (the LSB of each byte is dropped). The input and output + * blocks may overlap. + * + * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to + * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from + * \param key pointer to the key (64 bit = 8 byte) + */ + void decrypt(void* out, const void* in, const uint8_t* key); + + /** \fn void tripleEncrypt(void* out, const void* in, const void* key) + * \brief encrypt a block with Tripple-DES + * + * This function encrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE) + * algorithm. Key expansion is done automatically. The key is 192 bits long, but + * note that only 178 bits are used (the LSB of each byte is dropped). The input + * and output blocks may overlap. + * + * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to + * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from + * \param key pointer to the key (192 bit = 24 byte) + */ + void tripleEncrypt(void* out, void* in, const void* key); + + /** \fn void tripleDecrypt(void* out, const void* in, const void* key) + * \brief decrypt a block with Tripple-DES + * + * This function decrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE) + * algorithm. Key expansion is done automatically. The key is 192 bits long, but + * note that only 178 bits are used (the LSB of each byte is dropped). The input + * and output blocks may overlap. + * + * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to + * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from + * \param key pointer to the key (192 bit = 24 byte) + */ + void tripleDecrypt(void* out, void* in, const uint8_t* key); + + /* TODO */ + void xor_blocks(uint8_t* dst, const uint8_t* src, size_t len); + /* TODO */ + void decrypt_3des_cbc(uint8_t* ciphertext, size_t ciphertext_len, uint8_t* key, uint8_t* iv, uint8_t* plaintext); + /* TODO */ + void encrypt_3des_cbc(uint8_t* plaintext, size_t plaintext_len, uint8_t* key, uint8_t* iv, uint8_t* ciphertext); + + /** \fn DES() + * \brief DES constructor + * + * This function initialized an instance of DES + */ + DES(); + + /** \fn void init(const void* m_key,unsigned long long int IVCl) + * \brief initiallize the key and IVC and IV array + * + * This function initialized the basic variables needed for 3DES + * + * \param m_key (64 bit = 8 byte) + * \param IVCl int or hex value of iv , ex. 0x0000000000000001 + */ + void init(const void* m_key, unsigned long long int IVCl); + + /** \fn void init(const void* m_key) + * \brief initiallize the key + * + * This function initialized the basic variables needed for DES + * + * \param m_key (64 bit = 8 byte) + */ + void init(const void* m_key); + + /** \fn void change_key(const uint8_t* m_key); + * \brief change the key for DEs and 3DES + * + * This function changes the key variable needed for DES + * + * \param m_key (64 bit = 8 byte) + */ + void change_key(const void* m_key); + + /** \fn void change_IV(unsigned long long int IVCl); + * \brief Change IVC and iv + * + * This function changes the ivc and iv variables needed for 3DES + * + * \param IVCl int or hex value of iv , ex. 0x0000000000000001 + */ + void set_IV(unsigned long long int IVCl); + + /** Getter method for IV + * + * This function return the IV + * @param *out uint8_t pointer that gets the IV. + * @return none, the IV is writed to the out pointer. + */ + void get_IV(uint8_t* out); + + /** Getter method for IV + * + * This function return the IV + * @param out uint8_t pointer that gets the IV. + * @return none, the IV is writed to the out pointer. + */ + unsigned long long int get_IV_int(); + + /** \fn voiv_inc() + * \brief inrease the IVC and iv but 1 + * + * This function increased the VI by one step in order to have a different IV each time + * + */ + void iv_inc(); + + /** \fn get_key() + * \brief getter method for key + * + * This function return the key + * @return returns the key + + */ + uint8_t* get_key(); + + /** \fn get_size() + * \brief getter method for size + * + * This function return the size + * @return returns the size + + */ + int get_size(); + + /** Setter method for size + * + * This function sets the size of the plaintext+pad + * + */ + void set_size(int sizel); + + /** \fn calc_size_n_pad(uint8_t p_size) + * \brief calculates the size of the plaintext and the padding + * + * calculates the size of theplaintext with the padding + * and the size of the padding needed. Moreover it stores them in their variables. + * + * \param p_size the size of the uint8_t array ex sizeof(plaintext) + */ + void calc_size_n_pad(int p_size); + + /** \fn padPlaintext(void* in, uint8_t* out) + * \brief pads the plaintext + * + * This function pads the plaintext and returns an uint8_t array with the + * plaintext and the padding in order for the plaintext to be compatible with + * 8bit size blocks required by 3DES + * + * \param in the string of the plaintext in a uint8_t array + * \param out the string of the padded plaintext in a uint8_t array + */ + void padPlaintext(void* in, uint8_t* out); + + /** \fn CheckPad(void* in,int size) + * \brief check the if the padding is correct + * + * This functions checks the padding of the plaintext. + * + * \param *in the string of the plaintext in a uint8_t array + * \param size the size of the string + * \return true if correct / false if not + */ + bool CheckPad(uint8_t* in, int size); + + /** \fn tdesCbcEncipher(uint8_t* in,uint8_t* out) + * \brief the main encrypt 3DES with IV function + * + * This function uses the IV to xor (^) the first block of the string + * and encrypts it using tripleEncrypt function + * + * \param in the string of the plaintext in a uint8_t array + * \param out the string of the ciphertext in a uint8_t array + */ + void tdesCbcEncipher(uint8_t* in, uint8_t* out); + + /** \fn tdesCbcDecipher(uint8_t* in,uint8_t* out) + * \brief the main decrypt 3DES with IV function + * + * This function if the reverse of the tdesCbcEncipher function. + * used the IV and then the tripleDecrypt + * + * \param in the string of the ciphertext in a uint8_t array + * \param out the string of the plaintext in a uint8_t array + */ + void tdesCbcDecipher(uint8_t* in, uint8_t* out); + + /** \fn tprintArray(uint8_t output[],bool p_pad = true) + * \brief Prints the array given + * + * This function prints the given array with size equal \var size + * and pad equal \var pad. It is mainlly used for debugging purpuses or to output the string. + * + * \param output the string of the plaintext in a uint8_t array + * \param p_pad optional, used to print with out the padding characters + */ + void printArray(uint8_t output[], bool p_pad = true); + + /** Prints the array given. + * + * This function prints the given array in Hexadecimal. + * + * @param output[] the string of the text in a uint8_t array + * @param sizel the size of the array. + */ + void printArray(uint8_t output[], int sizel); + + /** User friendly implementation of AES-CBC encryption. + * + * @param *plain pointer to the plaintext + * @param size_p size of the plaintext + * @param *cipher pointer to the ciphertext + * @param *key pointer to the key that will be used. + * @param inc optional parameter to automaticaly increase IV + * @note The key will be stored in class variable. + */ + void do_3des_encrypt(uint8_t* plain, int size_p, uint8_t* cipher, const void* key, bool inc = false); + + /** User friendly implementation of AES-CBC decryption. + * + * @param *cipher pointer to the ciphertext + * @param size_c size of the ciphertext + * @param *plain pointer to the plaintext + * @param *key pointer to the key that will be used. + * @param ivl the initialization vector IV that will be used for decryption. + * @note The key will be stored in class variable. + */ + void do_3des_decrypt(uint8_t* cipher, int size_c, uint8_t* plain, const void* key, unsigned long long int ivl); +#if defined(DES_LINUX) + /** + * used in linux in order to retrieve the time in milliseconds. + * + * @return returns the milliseconds in a double format. + */ + double millis(); +#endif +private: + /** Permutation for DES. + * @param *ptable the permutaion table to be used. + * @param *in the pointer that holds the data before the permutations. + * @param *out the pointer that holds the data after the permutation. + * @return none, the output is inside the out pointer + * + */ + void permute(const uint8_t* ptable, const uint8_t* in, uint8_t* out); + + /** change endian form. + * @param *a the byte to change endian + */ + void changeendian32(uint32_t* a); + + /** used to shift the key. + * Used the shiftkey_permtab permutation table. + * @param *key the key to be shifted. + * + */ + inline void shiftkey(uint8_t* key); + + /** used to shift the key back. + * Used the shiftkeyinv_permtab permutation table. + * @param *key the key to be shifted. + * + */ + inline void shiftkey_inv(uint8_t* key); + + /** splits in 6 bit words + * + * @param a uint64_t size that will be slitted, permuted and returned. + * @return the permuted a. + * + */ + inline uint64_t splitin6bitwords(uint64_t a); + + /** main function for the substitutions + * @param a array position + * @param *sbp array to read byte from + * @returns the substituted byte. + * + */ + inline uint8_t substitute(uint8_t a, uint8_t* sbp); + + /** Primary function of DES. + * Used in encryption and decryption process. + * + * @param r unsigned intefer 32 bit, Data to be permuted. + * @param kr pointer of unsigned integers 8 bit, Data to be XOR with r after permutation + * @return + * + */ + uint32_t des_f(uint32_t r, uint8_t* kr); + uint8_t key[24];/**< holds the key for the encryption */ + unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */ + uint8_t iv[8];/**< holds the initialization vector that will be used in the cipher. */ + int pad;/**< holds the size of the padding. */ + int size;/**< hold the size of the plaintext to be ciphered */ +#if defined(DES_LINUX) + timeval tv;/**< holds the time value on linux */ +#endif + + uint8_t arr_pad[7];/**< holds the hexadecimal padding values, initialisation in the constructor */ }; #endif @@ -366,7 +373,7 @@ class DES * * A simple example demonstrating the DES encyption decruption use using Hexadecimal values. */ - + /** * @example DESexample.cpp * For Rasberry pi
@@ -374,7 +381,7 @@ class DES * * A simple example demonstrating the DES encyption decruption use using Hexadecimal values. */ - + /** * @example DesedeCBCexample.ino * For Arduino
@@ -388,7 +395,7 @@ class DES *
* Using all functions manually. */ - + /** * @example DesedeCBCexample.cpp * For Rasberry pi
@@ -402,7 +409,7 @@ class DES *
* Using all function manually */ - + /** * @example DesedeCBC-easy.ino * For Arduino
@@ -412,7 +419,7 @@ class DES * NOTE:
* calc_size Function calculates the size for the ciphertext. */ - + /** * @example DesedeCBC-easy.cpp * For Rasberry pi
@@ -424,69 +431,69 @@ class DES */ -/** - * @mainpage DES library for Arduino and Raspberry pi. - * - * @section Goals Design Goals - * - * This library is designed to be... - * @li Fast and efficient. - * @li Able to effectively encrypt and decrypt any size of string. - * @li Able to encrypt and decrypt using DES and 3DES. - * @li Easy for the user to use in his programs. - * - * @section Acknowledgements Acknowledgements - * This is an DES library for the Arduino, based on tzikis's DES library, which you can find here:.
- * Tzikis library was based on scottmac`s library, which you can find here:
- * - * @section Installation Installation - *

Arduino

- * Create a folder named _DES_ in the _libraries_ folder inside your Arduino sketch folder. If the - * libraries folder doesn't exist, create it. Then copy everything inside. (re)launch the Arduino IDE.
- * You're done. Time for a mojito - * - *

Raspberry pi

- * install

- * - * sudo make install
- * cd examples_Rpi
- * make

- * - * What to do after changes to the library

- * sudo make clean
- * sudo make install
- * cd examples_Rpi
- * make clean
- * make

- * What to do after changes to a sketch

- * cd examples_Rpi
- * make

- * or
- * make clean
- * make


- * How to start a sketch

- * cd examples_Rpi
- * sudo ./

- * - * @section News News - * - * If issues are discovered with the documentation, please report them here - * @section Useful Useful References - * - * Please refer to: - * - * @li DES Class Documentation - * @li Download - * @li Source Code - * @li All spaniakos Documentation Main Page - * - * @section Board_Support Board Support - * - * Most standard Arduino based boards are supported: - * - Arduino - * - Intel Galileo support - * - Raspberry Pi Support - * - * - The library has not been tested to other boards, but it should suppport ATMega 328 based boards,Mega Boards,Arduino Due,ATTiny board - */ + /** + * @mainpage DES library for Arduino and Raspberry pi. + * + * @section Goals Design Goals + * + * This library is designed to be... + * @li Fast and efficient. + * @li Able to effectively encrypt and decrypt any size of string. + * @li Able to encrypt and decrypt using DES and 3DES. + * @li Easy for the user to use in his programs. + * + * @section Acknowledgements Acknowledgements + * This is an DES library for the Arduino, based on tzikis's DES library, which you can find here:.
+ * Tzikis library was based on scottmac`s library, which you can find here:
+ * + * @section Installation Installation + *

Arduino

+ * Create a folder named _DES_ in the _libraries_ folder inside your Arduino sketch folder. If the + * libraries folder doesn't exist, create it. Then copy everything inside. (re)launch the Arduino IDE.
+ * You're done. Time for a mojito + * + *

Raspberry pi

+ * install

+ * + * sudo make install
+ * cd examples_Rpi
+ * make

+ * + * What to do after changes to the library

+ * sudo make clean
+ * sudo make install
+ * cd examples_Rpi
+ * make clean
+ * make

+ * What to do after changes to a sketch

+ * cd examples_Rpi
+ * make

+ * or
+ * make clean
+ * make


+ * How to start a sketch

+ * cd examples_Rpi
+ * sudo ./

+ * + * @section News News + * + * If issues are discovered with the documentation, please report them here + * @section Useful Useful References + * + * Please refer to: + * + * @li DES Class Documentation + * @li Download + * @li Source Code + * @li All spaniakos Documentation Main Page + * + * @section Board_Support Board Support + * + * Most standard Arduino based boards are supported: + * - Arduino + * - Intel Galileo support + * - Raspberry Pi Support + * + * - The library has not been tested to other boards, but it should suppport ATMega 328 based boards,Mega Boards,Arduino Due,ATTiny board + */