April 2014
S M T W T F S
« Oct    
 12345
6789101112
13141516171819
20212223242526
27282930  

Recent Posts

DiceLockIndexedCheck, C++ program for Windows to verify DiceLock encryption cipher architecture with DiceLockIndexed class

DiceLockIndexedCheck is a C++ program to verify that DiceLockIndexed class implementing one of DiceLock different architectures is working as expected.

DiceLockIndexed 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 just symmetric key, no initialization vector (IV) is used,
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 DiceLockIndexed architecture are:

– stream cipher: ARC4 and ARC4_Discarding (discarding initial 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.


While performing internal software quality assurance we have verified that DiceLockIndexedCheck in debug mode does not generate any memory leaks with any executed option.
Debug mode was run with the corresponding debugger and the C Run-Time Libraries (CRT) debug heap functions as well as with dump memory leak information function that can be obtained executing “_CrtDumpMemoryLeaks” statement before program ends execution.

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

Test program in C++ language:

// DiceLockIndexedCheck.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#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 KEY_BITS_LENGTH		128
#define INDEX_LENGTH		128
#define FILE_NAME_LENGTH	300


BaseSymmetricStreamer*	SetSymmetricStreamerCipherType(unsigned char cipher) {
	BaseSymmetricStreamer* streamCipherObject;

	switch (cipher) {
		case '0' :	streamCipherObject = new ARC4();
			break;
		case '1' :	streamCipherObject = new ARC4_Discarding();
					((ARC4_Discarding*)streamCipherObject)->SetDiscardedBytes(1536);
			break;
	}
	return streamCipherObject;
}

BaseIndexModifier* SetIndexModifier(unsigned long int indexer, unsigned long int indexLength) {
	BaseIndexModifier* modifier;

	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;

	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 cipher;
	unsigned char keyModifier;
	unsigned char dataStream;
	char reciphersFile[FILE_NAME_LENGTH];
	FILE* fp;
	FILE* fr;

	DiceLockIndexed* diceLock;
	BaseSymmetricStreamer* streamerCipher;
	RandomTestSuite* randomSuite;
	BaseIndexModifier* modifier;
	BaseCryptoRandomStream* key;
	BaseCryptoRandomStream* plaintext;
	BaseCryptoRandomStream* ciphertext;
	BaseCryptoRandomStream* decipheredtext;

	// Gets execution parameters from command line
	cipher = argv[1][0];
	keyModifier = argv[1][1];
	dataStream = argv[1][2];

	// 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_s(reciphersFile, argv[2]);
	strcat_s(reciphersFile, ".reciphered");
	if ( fopen_s(&fr, reciphersFile, "w+") != 0 ) {
		printf(" ERROR OPENING FILE\n");
		return 1;
	}
	fprintf(fr, "keyUC, plainUC, length, reciphers\n");
	correctDecipher = 0;
	incorrectDecipher = 0;

	for ( length = MIN_LENGTH_TESTS; length <= MAX_LENGTH_TESTS; length = length + 8 ) {

		printf("length: %d\n", length);
		performedTests++;

		// Encryption
		diceLock =  new DiceLockIndexed();
		streamerCipher = SetSymmetricStreamerCipherType(cipher);
		diceLock->SetSymmetricStreamer(streamerCipher);
		randomSuite = new RandomTestSuite();
		SetRandomTestsAndAlpha(randomSuite);
		diceLock->SetRandomTestSuite(randomSuite);
		modifier = SetIndexModifier(keyModifier, INDEX_LENGTH);
		diceLock->SetIndexModifier(modifier);

		key = SetStreamType(dataStream, KEY_BITS_LENGTH);
		plaintext = SetStreamType(dataStream, length);
		ciphertext = SetStreamType(dataStream, diceLock->GetBitCiphertextLength(plaintext->GetBitLength()));
		
		key->FillUC((unsigned char)(rand() & 0x000000FF));
		plaintext->FillUC((unsigned char)(rand() & 0x000000FF));

		diceLock->Initialize();
		diceLock->SetSymmetricKey(key);
		diceLock->Cipher(plaintext, ciphertext);

		if ( diceLock->GetReciphers() > 0 ) {
			reciphers++;
			if ( maxReciphers < diceLock->GetReciphers() ) {
				maxReciphers = diceLock->GetReciphers();
			}
			fprintf(fr, "%02x,%02x,%d,%d\n", key->GetUCPosition(0), plaintext->GetUCPosition(0), length, diceLock->GetReciphers());
		}

		RemoveIndexModifier(modifier, keyModifier);
		delete randomSuite;
		delete streamerCipher;
		delete diceLock;

		// Decryption
		diceLock =  new DiceLockIndexed();
		streamerCipher = SetSymmetricStreamerCipherType(cipher);
		diceLock->SetSymmetricStreamer(streamerCipher);
		modifier = SetIndexModifier(keyModifier, INDEX_LENGTH);
		diceLock->SetIndexModifier(modifier);

		decipheredtext = SetStreamType(dataStream, diceLock->GetBitDecipheredtextLength(ciphertext->GetBitLength()));

		diceLock->Initialize();
		diceLock->SetSymmetricKey(key);
		diceLock->Decipher(ciphertext, decipheredtext);

		RemoveIndexModifier(modifier, keyModifier);
		delete streamerCipher;
		delete diceLock;

		// Verifying plaintext and decipheredtext
		VerifyDecryption(plaintext, decipheredtext, &correctDecipher, &incorrectDecipher);

		RemoveStreamType(key, dataStream);
		RemoveStreamType(plaintext, dataStream);
		RemoveStreamType(ciphertext, dataStream);
		RemoveStreamType(decipheredtext, dataStream);
	}
	fclose(fr);

	// Total Output 
	if (fopen_s(&fp, argv[2], "w+") != 0) {
		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: %d\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: %d\n", correctDecipher);
	fprintf(fp, "Number of incorrect streams deciphered: %d\n", incorrectDecipher);
	if ( incorrectDecipher == 0 ) {
		fprintf(fp, "Incorrect deciphered streams = %d ==> ---OK---\n", incorrectDecipher);
	}
	else {
		fprintf(fp, "Incorrect deciphered streams = %d ==> ---ERROR---\n", incorrectDecipher);
	}
	fprintf(fp, "\n");
	fprintf(fp, "Total encrypted streams reciphered at least once: %d\n", reciphers);
	fprintf(fp, "Maximum number of reciphers performed over one stream being reciphered: %d\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.

Leave a Reply