September 2014
S M T W T F S
« Aug    
 123456
78910111213
14151617181920
21222324252627
282930  

Recent Posts

DiceLockIVIndexedOMCheck, C++ program for Linux to verify DiceLock encryption cipher architecture with DiceLockIVIndexed class and Block cipher operation modes

DiceLockIVIndexedOMCheck is a C++ program for Linux to verify that DiceLockIVIndexed class implementing one of DiceLock different architectures is working as expected.

DiceLockIVIndexed class is the class that implements DiceLock architecture with the following characteristics:
– base encryption cipher/decipher is any symmetric cipher (stream cipher or block cipher operation mode) working with symmetric key, and initialization vector (IV) are needed,
ciphered index pointing symmetric key modification plus ciphertext is checked for random number test properties,
– any function that is able to change original symmetric key with new values generating index pointing out such modification,
bit random number tests that can verify that encrypted ciphertext is at random.

Current algorithm classes that can be used with DiceLockIVIndexed architecture are:

– as base encryption cipher/decipher:

  • stream ciphers with initialization vector as:
      HC 128,
      HC 256,
      Rabbit,
      Salsa 20/20 128,
      Salsa 20/20 256,
      Sosemanuk 128,
      Sosemanuk 256,
  • block cipher operatin modes as:
      CBC (cipher block chaining),
      CFB (cipher feedback),
      OFB (output feedback),
  • with any of following block ciphers:
      AES (Advanced Encryption Standard) with 128, 192 or 256 key bits,
      Camellia with 128, 192 or 256 key bits,
      Serpent with 128, 192 or 256 key bits,
      Twofish with 128, 192 or 256 key bits, or
      TDEA (Triple Data Encryption Algorithm) with 192 key bits,
  • – symmetric key changers: IncreaseBase0IndexModifier_6_0_0_1 and DecreaseBase0IndexModifier_6_0_0_1,
    – random number tests: Frequency, Block Frequency, Cumulative Sum Forward, Cumulative Sum Reverse, Runs, Longest Run Of Ones, Rank, Universal, Approximate Entropy, Serial, Discrete Fourier Transform tests and random number test Suite with any or all previous enumerated random number tests.

    Because of so many alternative encryption/decryption engines can be used, we have split DiceLockIVIndexed class tests in two main C++ program tests:
    DiceLockIVIndexedNoOMCheck C++ Source Code program making use of stream ciphers, and
    DiceLockIVIndexedOMCheck C++ Source Code program making use of block cipher operation modes with multiple block ciphers.

    In this test we verify DiceLockIVIndexedOMCheck C++ Source Code program making use of block ciphers and block cipher operation modes with the configuration shown below.

    With CBC operation mode all three implemented crypto pad systems (ANSI X.923, ISO/IEC 9797-1 and PKCS7) are used. They are selected on a random basis and such election is logged only when a recipher is performed over the text being randomized-encrypted.

    In order to verify that DiceLockIVIndexed class is performing the following program has been used. Execution call must be:
    DiceLockIVIndexedOMCheck [block cipher operation mode][block cipher][key modifier][stream type] log_output_file, where the different values can be easily infered from source code.

    Test program in C++ language:

    // DiceLockIVIndexedOMCheck.cpp : Defines the entry point for the console application.
    //
    
    #include 
    #include 
    #include "DiceLockCipher.h"
    
    using namespace DiceLockSecurity::Cipher::SymmetricCipher::DiceLock;
    using namespace DiceLockSecurity::Cipher::SymmetricCipher::SymmetricStreamer::StreamCipher;
    
    #define MIN_LENGTH_TESTS	8
    #define MAX_LENGTH_TESTS	500000
    #define RANDOM_ALPHA		0.001
    #define FILE_NAME_LENGTH	300
    
    
    BaseBlockCipherOperationMode_with_IV* SetOMType(unsigned char operationMode) {
    	BaseBlockCipherOperationMode_with_IV* omObject;
    
    	omObject = NULL;
    	switch (operationMode) {
    		case '0' :	omObject = new CBC_Mode();
    			break;
    		case '1' :	omObject = new CFB_Mode();
    			break;
    		case '2' :	omObject = new OFB_Mode();
    			break;
    	}
    	return omObject;
    }
    
    void RemoveOMType(BaseBlockCipherOperationMode_with_IV* omObject, unsigned char operationMode) {
    
    	switch (operationMode) {
    		case '0' :	delete (CBC_Mode*)omObject; 
    			break;
    		case '1' :	delete (CFB_Mode*)omObject;
    			break;
    		case '2' :	delete (OFB_Mode*)omObject;
    			break;
    	}
    }
    
    BaseBlockCipher* SetBlockCipherType(unsigned char blockCipher) {
    	BaseBlockCipher* cipherObject;
    
    	cipherObject = NULL;
    	switch (blockCipher) {
    		case '0' :	cipherObject = new AES128();
    			break;
    		case '1' :	cipherObject = new AES192();
    			break;
    		case '2' :	cipherObject = new AES256();
    			break;
    		case '3' :	cipherObject = new Camellia128();
    			break;
    		case '4' :	cipherObject = new Camellia192();
    			break;
    		case '5' :	cipherObject = new Camellia256();
    			break;
    		case '6' :	cipherObject = new Serpent128();
    			break;
    		case '7' :	cipherObject = new Serpent192();
    			break;
    		case '8' :	cipherObject = new Serpent256();
    			break;
    		case '9' :	cipherObject = new Twofish128();
    			break;
    		case 'A' :	cipherObject = new Twofish192();
    			break;
    		case 'B' :	cipherObject = new Twofish256();
    			break;
    		case 'C' :	cipherObject = new TDEA();
    			break;
    	}
    	return cipherObject ;
    }
    
    void RemoveBlockCipherType(BaseBlockCipher* cipher, unsigned char blockCipher) {
    
    	switch (blockCipher) {
    		case '0' :	delete (AES128*)cipher;
    			break;
    		case '1' :	delete (AES192*)cipher;
    			break;
    		case '2' :	delete (AES256*)cipher;
    			break;
    		case '3' :	delete (Camellia128*)cipher;
    			break;
    		case '4' :	delete (Camellia192*)cipher;
    			break;
    		case '5' :	delete (Camellia256*)cipher;
    			break;
    		case '6' :	delete (Serpent128*)cipher;
    			break;
    		case '7' :	delete (Serpent192*)cipher;
    			break;
    		case '8' :	delete (Serpent256*)cipher;
    			break;
    		case '9' :	delete (Twofish128*)cipher;
    			break;
    		case 'A' :	delete (Twofish192*)cipher;
    			break;
    		case 'B' :	delete (Twofish256*)cipher;
    			break;
    		case 'C' :	delete (TDEA*)cipher;
    			break;
    	}
    }
    
    BaseCryptoPad* SetCryptoPad(unsigned long int pad) {
    	BaseCryptoPad* padObject;
    
    	padObject = NULL;
    	switch ( pad ) {
    		case 0 : padObject = new ANSI_X_923();
    			break;
    		case 1 : padObject = new ISO_IEC_9797_1();
    			break;
    		case 2 : padObject = new PKCS7();
    			break;
    	}
    	return padObject;
    }
    
    BaseIndexModifier* SetIndexModifier(unsigned long int indexer, unsigned long int indexLength) {
    	BaseIndexModifier* modifier;
    
    	modifier = NULL;
    	if ( indexer == '0' ) {
    		modifier = new IncreaseBase0IndexModifier_6_0_0_1();
    		((IncreaseBase0IndexModifier_6_0_0_1*)modifier)->SetBitIndexLength(indexLength);
    	}
    	if ( indexer == '1' ) {
    		modifier = new DecreaseBase0IndexModifier_6_0_0_1();
    		((DecreaseBase0IndexModifier_6_0_0_1*)modifier)->SetBitIndexLength(indexLength);
    	}
    	return modifier;
    }
    
    void RemoveIndexModifier(BaseIndexModifier* modifier, unsigned long int indexer) {
    
    	if ( indexer == '0' ) {
    		delete (IncreaseBase0IndexModifier_6_0_0_1*)modifier;
    	}
    	if ( indexer == '1' ) {
    		delete (DecreaseBase0IndexModifier_6_0_0_1*)modifier;
    	}
    }
    
    BaseCryptoRandomStream*	SetStreamType(unsigned char stream, unsigned long int bitLength) {
    	BaseCryptoRandomStream* streamObject;
    
    	streamObject = NULL;
    	switch (stream) {
    		case '0' :	streamObject = new DefaultCryptoRandomStream(bitLength);
    			break;
    		case '1' :	streamObject = new PhysicalCryptoRandomStream(bitLength);
    			break;
    	}
    	return streamObject;
    }
    
    void RemoveStreamType(BaseCryptoRandomStream* streamObject, unsigned char stream) {
    
    	switch (stream) {
    		case '0' :	delete (DefaultCryptoRandomStream*)streamObject;
    			break;
    		case '1' :	delete (PhysicalCryptoRandomStream*)streamObject;
    			break;
    	}
    }
    
    void SetRandomTestsAndAlpha(RandomTestSuite* suite) {
    
    	suite->AddFrequencyTest();
    	suite->AddBlockFrequencyTest();
    	suite->AddCumulativeSumForwardTest();
    	suite->AddLongestRunOfOnesTest();
    	suite->AddRunsTest();
    	suite->SetAlpha(RANDOM_ALPHA);
    }
    
    void VerifyDecryption(BaseCryptoRandomStream* plaintext, BaseCryptoRandomStream* decipheredtext, unsigned long int* correctDecipher, unsigned long int* incorrectDecipher) {
    
    	if ( plaintext->Equals(decipheredtext) ) {
    		(*correctDecipher)++;
    	}
    	else {
    		(*incorrectDecipher)++;
    	}
    }
    
    int main(int argc, char* argv[])
    {
    
    	unsigned long int performedTests;
    	unsigned long int length;
    	unsigned long int reciphers;
    	unsigned long int maxReciphers;
    	unsigned long int correctDecipher;
    	unsigned long int incorrectDecipher;
    	unsigned char operationMode;
    	unsigned char cipher;
    	unsigned char keyModifier;
    	unsigned char dataStream;
    	unsigned char pad;
    	char reciphersFile[FILE_NAME_LENGTH];
    	FILE* fp;
    	FILE* fr;
    
    	DiceLockIVIndexed* diceLock;
    	BaseBlockCipherOperationMode_with_IV* operMode;
    	BaseBlockCipher* blockCipher;
    	BaseCryptoPad*	 padding;
    	RandomTestSuite* randomSuite;
    	BaseIndexModifier* modifier;
    	BaseCryptoRandomStream* key;
    	BaseCryptoRandomStream* iv;
    	BaseCryptoRandomStream* plaintext;
    	BaseCryptoRandomStream* ciphertext;
    	BaseCryptoRandomStream* decipheredtext;
    
    	pad = 0;
    	padding = NULL;
    	// Gets execution parameters from command line
    	operationMode = argv[1][0];
    	cipher = argv[1][1];
    	keyModifier = argv[1][2];
    	dataStream = argv[1][3];
    
    	// Pseudo-random generation, fixed intitialitation seed allows 
    	// re-run same test with identical data
    	srand(1);
    
    	performedTests = 0;
    	reciphers = 0;
    	maxReciphers = 0;
    	memset(reciphersFile, 0, FILE_NAME_LENGTH);
    	strcat(reciphersFile, argv[2]);
    	strcat(reciphersFile, ".reciphered");
    	if ( (fr = fopen(reciphersFile, "w")) == NULL ) {
    		printf(" ERROR OPENING FILE\n");
    		return 1;
    	}
    	if ( operationMode == '0' ) { 
    		fprintf(fr, "keyUC, ivUC, plainUC, length, cryptoPad, reciphers\n");
    	}
    	else {
    		fprintf(fr, "keyUC, ivUC, plainUC, length, reciphers\n");
    	}
    	correctDecipher = 0;
    	incorrectDecipher = 0;
    
    	for ( length = MIN_LENGTH_TESTS; length <= MAX_LENGTH_TESTS; length = length + 8 ) {
    
    		printf("length: %lu\n", length);
    		performedTests++;
    
    		// Encryption
    		diceLock =  new DiceLockIVIndexed();
    		operMode = SetOMType(operationMode);
    		if ( operationMode == '0' ) {
    			pad = rand() % 3;
    			padding = SetCryptoPad(pad);
    			((CBC_Mode*)operMode)->SetCryptoPad(padding);
    		}
    		blockCipher = SetBlockCipherType(cipher);
    		operMode->SetBlockCipher(blockCipher);
    		diceLock->SetSymmetricStreamer(operMode);
    		randomSuite = new RandomTestSuite();
    		SetRandomTestsAndAlpha(randomSuite);
    		diceLock->SetRandomTestSuite(randomSuite);
    		modifier = SetIndexModifier(keyModifier, diceLock->GetBitKeyLength());
    		diceLock->SetIndexModifier(modifier);
    
    		key = SetStreamType(dataStream, diceLock->GetBitKeyLength());
    		iv = SetStreamType(dataStream, diceLock->GetBitIVLength());
    		plaintext = SetStreamType(dataStream, length);
    		ciphertext = SetStreamType(dataStream, diceLock->GetBitCiphertextLength(plaintext->GetBitLength()));
    		
    		key->FillUC((unsigned char)(rand() & 0x000000FF));
    		iv->FillUC((unsigned char)(rand() & 0x000000FF));
    		plaintext->FillUC((unsigned char)(rand() & 0x000000FF));
    
    		diceLock->Initialize();
    		diceLock->SetEncryptionSymmetricKey(key);
    		diceLock->SetIV(iv);
    		diceLock->Cipher(plaintext, ciphertext);
    
    		if ( diceLock->GetReciphers() > 0 ) {
    			reciphers++;
    			if ( maxReciphers < diceLock->GetReciphers() ) {
    				maxReciphers = diceLock->GetReciphers();
    			}
    			if ( operationMode == '0' ) {
    				fprintf(fr, "%02x,%02x,%02x,%lu,%d,%lu\n", key->GetUCPosition(0), iv->GetUCPosition(0), plaintext->GetUCPosition(0), length, padding->GetCryptoPadType(), diceLock->GetReciphers());
    			}
    			else {
    				fprintf(fr, "%02x,%02x,%02x,%lu,%lu\n", key->GetUCPosition(0), iv->GetUCPosition(0), plaintext->GetUCPosition(0), length, diceLock->GetReciphers());
    			}
    		}
    
    		RemoveIndexModifier(modifier, keyModifier);
    		delete randomSuite;
    		RemoveBlockCipherType(blockCipher, cipher);
    		if ( operationMode == '0' ) {
    			delete padding;
    		}
    		RemoveOMType(operMode, operationMode);
    		delete diceLock;
    
    		// Decryption
    		diceLock =  new DiceLockIVIndexed();
    		operMode = SetOMType(operationMode);
    		if ( operationMode == '0' ) {
    			padding = SetCryptoPad(pad);
    			((CBC_Mode*)operMode)->SetCryptoPad(padding);
    		}
    		blockCipher = SetBlockCipherType(cipher);
    		operMode->SetBlockCipher(blockCipher);
    		diceLock->SetSymmetricStreamer(operMode);
    		modifier = SetIndexModifier(keyModifier, diceLock->GetBitKeyLength());
    		diceLock->SetIndexModifier(modifier);
    
    		decipheredtext = SetStreamType(dataStream, diceLock->GetBitDecipheredtextLength(ciphertext->GetBitLength()));
    
    		diceLock->Initialize();
    		diceLock->SetDecryptionSymmetricKey(key);
    		diceLock->SetIV(iv);
    		diceLock->Decipher(ciphertext, decipheredtext);
    
    		RemoveIndexModifier(modifier, keyModifier);
    		RemoveBlockCipherType(blockCipher, cipher);
    		if ( operationMode == '0' ) {
    			delete padding;
    		}
    		RemoveOMType(operMode, operationMode);
    		delete diceLock;
    
    		// Verifying plaintext and decipheredtext
    		VerifyDecryption(plaintext, decipheredtext, &correctDecipher, &incorrectDecipher);
    
    		RemoveStreamType(key, dataStream);
    		RemoveStreamType(iv, dataStream);
    		RemoveStreamType(plaintext, dataStream);
    		RemoveStreamType(ciphertext, dataStream);
    		RemoveStreamType(decipheredtext, dataStream);
    	}
    	fclose(fr);
    
    	// Total Output 
    	if ( (fp = fopen(argv[2], "w")) == NULL ) {
    		printf(" ERROR OPENING FILE\n");
    		return 1;
    	}
    	fprintf(fp, "Verified:\n");
    	fprintf(fp, "---------\n");
    	fprintf(fp, "%s\n", argv[2]);
    	fprintf(fp, "\n");
    	fprintf(fp, "Number of streams tested: %lu\n", performedTests);
    	fprintf(fp, "\n");
    	fprintf(fp, "From length of shorter stream tested in bits: %d\n", MIN_LENGTH_TESTS);
    	fprintf(fp, "Up to length of larger stream tested in bits: %d\n", MAX_LENGTH_TESTS);
    	fprintf(fp, "\n");
    	fprintf(fp, "\n");
    	fprintf(fp, "Number of correct streams deciphered: %lu\n", correctDecipher);
    	fprintf(fp, "Number of incorrect streams deciphered: %lu\n", incorrectDecipher);
    	if ( incorrectDecipher == 0 ) {
    		fprintf(fp, "Incorrect deciphered streams = %lu ==> ---OK---\n", incorrectDecipher);
    	}
    	else {
    		fprintf(fp, "Incorrect deciphered streams = %lu ==> ---ERROR---\n", incorrectDecipher);
    	}
    	fprintf(fp, "\n");
    	fprintf(fp, "Total encrypted streams reciphered at least once: %lu\n", reciphers);
    	fprintf(fp, "Maximum number of reciphers performed over one stream being reciphered: %lu\n", maxReciphers);
    	fprintf(fp, "\n");
    	fprintf(fp, "File with reciphered stream data:\n");
    	fprintf(fp, "%s\n", reciphersFile);
    	fprintf(fp, "\n");
    	fclose(fp);
    
    	return 0;
    }
    
    

    All different tests are performed over 62.500 streams and we will post each one result promptly.

    2 comments to DiceLockIVIndexedOMCheck, C++ program for Linux to verify DiceLock encryption cipher architecture with DiceLockIVIndexed class and Block cipher operation modes

    Leave a Reply