Symmetric Key Algorithms

1. Block Cipher & Stream Cipher

There are two kinds of symmetric key algorithms: One is block cipher. It divides a message into different blocks, then encrypt each block. There are five modes of cipher block operations: ECB, CBC, CTR, CFB, OFB. The other is stream cipher, which processes the message as a whole. The only stream cipher I know is RC4.

Obviously, the length of the message may not be the multiples of block size. Thus, padding is needed in most cases. There are several kinds of padding methods. For example, The input to the DES CBC encryption process shall be padded to a multiple of 8 octets, in the following manner.  Let n be the length in octets of the input.  Pad the input by appending 8-(n mod 8) octets to the end of the message, each having the value 8-(n mod 8), the number of octets being added.  In hexadecimal, the possible paddings are:  01, 0202, 030303, 04040404, 0505050505, 060606060606, 07070707070707, and 0808080808080808.  All input is padded with 1 to 8 octets to produce a multiple of 8 octets in length.  The padding can be removed unambiguously after decryption.

2. Random Numbers

In order to perform the timing tests, we decide to produce an array of random number.

If you're running on a Win32 OS, or a Unix OS with /dev/random, then you can use AutoSeededRandomPool:
 

   #include "osrng.h"
   using namespace CryptoPP;
   .
   .
   .
   AutoSeededRandomPool rng;
   byte randomBytes[10];
   rng.GenerateBlock(randomBytes, 10);

Otherwise you should use RandomPool and seed it yourself with random, unpredictable data:
 

   RandomPool rng;
   rng.Put(seed, seedLen);
   byte randomBytes[10];
   rng.GenerateBlock(randomBytes, 10);
e.g. The script is as follows:

else if (command == "des")
{
// VC60 workaround: use char array instead of std::string to workaround MSVC's getline bug
char plaintext[1024] = "", ciphertext[1024]="";
char detext[1024] = "";
const byte passPhrase[] = {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40};
/* corresponding 56 bit key is 40,81,02,04,08,10,20 */

AutoSeededRandomPool rng;
rng.GenerateBlock((byte*)plaintext, 8);
cout << "\nThe plain text is "<< plaintext <<"\n";
gettimeofday(&current_time, &tzp);
t1 = timeval2double(&current_time);
cout << "\nCurrent Time is "<<t1;

const byte iv2[] = {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40};

CBC_Mode<DES>::Encryption encryption_DES_CBC(passPhrase, 8, iv2);

encryption_DES_CBC.ProcessString((byte*)ciphertext, (byte*)plaintext, strlen(plaintext));


gettimeofday(&current_time, &tzp);
t2 = timeval2double(&current_time);
cout << "\nCurrent Time is "<<t2;
cout << "\nThe time difference is "<<t2-t1<<"\n";
cout << "\nThe cipher text is "<< ciphertext <<"\n";

CBC_Mode<DES>::Decryption decryption_DES_CBC;
decryption_DES_CBC.SetKeyWithIV(passPhrase, 8, iv2);//8x8bits = 64 bit key, 64bit IV
decryption_DES_CBC.ProcessString((byte*)detext, (byte*)ciphertext, strlen(ciphertext));

cout << "\nThe decrypted text is "<< detext <<"\n";
return 0;
}

3. Test DES

I use 8192 blocks plaintext in all. The code is:


struct timeval current_time;
struct timezone tzp;
double t1, t2, t3, t4;
char plaintext[65536] = "", ciphertext[65536]="", detext[65536] = "";
const byte passPhrase[] = {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40};
const byte iv2[] = {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40};
int j=0;

AutoSeededRandomPool rng;
rng.GenerateBlock((byte*)plaintext, 65536);
.................................................

else if (command == "des")
{
// 65536=8192*8,ie,8192 blocks
gettimeofday(&current_time, &tzp);
t1 = timeval2double(&current_time);

CBC_Mode<DES>::Encryption encryption_DES_CBC(passPhrase, 8, iv2);

do{
encryption_DES_CBC.ProcessString((byte*)(ciphertext+j*64), (byte*)(plaintext+j*64), 64);
j++;
}while(j<1024);

gettimeofday(&current_time, &tzp);
t2 = timeval2double(&current_time);
cout << "\nThe encryption time difference is "<<t2-t1<<"\n";


CBC_Mode<DES>::Decryption decryption_DES_CBC;
decryption_DES_CBC.SetKeyWithIV(passPhrase, 8, iv2);//8x8bits = 64 bit key, 64bit IV
gettimeofday(&current_time, &tzp);
t3 = timeval2double(&current_time);
j = 0;
do{
decryption_DES_CBC.ProcessString((byte*)(detext+j*64), (byte*)(ciphertext+j*64), 64);
j++;
}while(j<1024);

gettimeofday(&current_time, &tzp);
t4 = timeval2double(&current_time);
cout << "\nThe decryption time difference is "<<t4-t3<<"\n";

return 0;
}


The test result is 0.015527 for encryption, and 0.016129 for decryption.

4. Symmetric Method List

Substitution & Transposition.

1) DES

a) DES

Key length:
64 bits as encoded; 56 bits excluding parity bits.
Block size:
8 bytes.

b) 2DES

Key length:
128 bits, as encoded (112 excluding parity).
Block size:
8 bytes.

c) 3DES

Key length:
192 bits, as encoded (168 bits excluding parity).
Block size:
8 bytes.

d) XDES

Description:
If K, K1 and K2 are the subkeys encoded as described below, then encryption and decryption are defined by:

EDESX[K, K1, K2](P) = EDES[K](P XOR K1) XOR K2
DDESX[K, K1, K2](C) = DDES[K](C XOR K3) XOR K2

If the user key length is 24 bytes, the first 8 bytes represent the key K used for the DES operation, and the two subsequent blocks of 8 bytes represent the "whitening" keys K1 and K2, in that order.

If the user key length is 16 bytes, the first 8 bytes represent the key K used for the DES operation, the second 8 bytes represent the whitening key K1, and K2 is derived from K and K1 as specified in the first reference below.

Key length:
128 or 192 bits; default 192 bits, as encoded. See security comments for the effective key length.
Block size:
8 bytes.

2) AES

Key length:
128, 192 and 256 bits; default 128 bits.
Block size:
16 bytes.

3) R series

a) R2

A block cipher developed by Ron Rivest at RSA Data Security, Inc. 

The algorithm is designed to be easy to implement on 16-bit microprocessors.

Key length:
Minimum 0; maximum 1024, multiple of 8 bits; default 128 bits.
Block size:
8 bytes.
Security comment:
RC2 is vulnerable to related-key attacks, and therefore it should only be used with keys that are generated by a strong RNG, or by a source of bits that are sufficiently uncorrelated (such as the output of a hash function).

b) R4

A stream cipher licensed by RSA Data Security [RSADSI].

Key length:
Minimum 8, maximum 2048, multiple of 8 bits; default 128 bits.
Security comments:
The RC4 keystream is distinguishable from random given about 2 Gbytes of the stream.

RC4 is vulnerable to related-key attacks, and therefore it should only be used with keys that are generated by a strong RNG, or by a source of bits that are sufficiently uncorrelated (such as the output of a hash function).

c) R5

Parameters:
Integer rounds [creation/read, default 12] - the number of rounds to be performed (minimum 12, multiple of 2)
Key length:
Minimum 0; maximum 2040, multiple of 8 bits; default 128 bits.
Block size:
8 bytes.
Comments:
The block size could have been specified as a parameter; however it is unlikely that RC5 could be efficiently implemented with multiple block sizes sharing the same code, and therefore two different algorithms are specified (RC5 and RC5-64). Also note that the default (and minimum) number of rounds is different (12 vs 16).

The maximum key length is restricted to 2040 bits (see the RSA Labs FAQ entry for RC5); this is an incompatible change since SCAN 1.0.11.

Security comment:
The paper "On the Security of the RC5 Encryption Algorithm" gives an overview of cryptanalysis results against RC5 up to 1998.

d) R6

Parameters:
Integer rounds [creation/read, default 20] - the number of rounds to be performed (minimum 8, multiple of 4)
Key length:
Minimum 0; maximum 2040, multiple of 8 bits; default 128 bits.
Block size:
16 bytes.
Comments:
The block size could have been specified as a parameter; however it is unlikely that RC6 could be efficiently implemented with multiple block sizes sharing the same code, and therefore two different algorithms are specified (RC6 and RC6-64).

5) Fish Series

a) Twofish

Key length:
Minimum 8, maximum 256, multiple of 8 bits; default 128 bits.
Block size:
16 bytes.

b) Blowfish

Key length:
Minimum 32, maximum 448, multiple of 8 bits; default 128 bits.
Block size:
8 bytes.

6) IDEA

Key length:
128 bits.
Block size:
8 bytes.
Security comment:
IDEA is vulnerable to key schedule attacks, and therefore it should only be used with keys that are generated by a strong RNG, or by a source of bits that are sufficiently uncorrelated (such as the output of a hash function).