Test code for Crypto
//
// Lapetus Ltd Java Class. Copyright (c) Lapetus Systems Ltd, 2009, 2010.
// -----------------------------------------------------------------------
// This is the intellectual property of Lapetus Systems Ltd, Artemis, Greece.
// --------------------------------------------------------------------------
// www.lapetus-ltd.com, www.lapetus.com.gr, www.lapetus.eu
// -------------------------------------------------------
// $LastChangedRevision: 1168 $
// $LastChangedDate:: 2010-11-06 16:41:19#$
// ----------------------------------------
//
import com.lapetus_ltd.api.TLptsMainJut;
import com.lapetus_ltd.api.common.TLptsBytesUtil;
import com.lapetus_ltd.api.common.TLptsCryptoUtil;
import com.lapetus_ltd.api.common.TLptsFileUtil;
import com.lapetus_ltd.api.common.logger.TLptsLog;
import com.lapetus_ltd.api.common.logger.TLptsLogger;
import junit.framework.TestCase;
// ######################################################################################################
// #### Test code for the JUT build process. This code will stop the build process on ERROR ####
// ######################################################################################################
// Class Description : Test class for all capabilities of the Crypto Module.
//
// These tests include verification of the RSA and AES cipher types that are available in the crypto module.
// The foreign RSA encryption capability, which is normally used for transporting data, is also tested.
//
// Due to the many tests run below, we have commented every function as to its aim and purpose.
//
public class TestCrypto extends TestCase
{
public static void main(String[] args)
{
TestCrypto test = new TestCrypto();
test.runAllTests(false);
}
public void runAllTests(boolean isExit)
{
testRSADefault();
testAESDefault();
testRSADefaultDynamic();
testAESDefaultDynamic();
testRSAInstance();
testAESInstance();
testRSA2Files();
testAES2File();
testRSADefaultForeign();
testCredentials();
if (isExit)
System.exit(0);
}
// This is the simplest of tests, where we just check the default RSA for correct functionality.
// The RSA key pair (private and public) is 1024 bits by default and is stored in two files in the user home lapetus directory.
public void testRSADefault()
{
TLptsMainJut.init();
System.out.println("\nTesting Default RSA Encryption...");
byte[] data = generateDataToEncrypt(512);
byte[] encryptedData = TLptsCryptoUtil.defaultEncryptRSA(data);
byte[] decryptedData = TLptsCryptoUtil.defaultDecryptRSA(encryptedData);
System.out.println("Original Bytes: " + TLptsBytesUtil.getHexString(data));
System.out.println("Encrypted Bytes: " + TLptsBytesUtil.getHexString(encryptedData));
System.out.println("Decrypted Bytes: " + TLptsBytesUtil.getHexString(decryptedData));
if (!compareBytes(data, decryptedData))
failure();
}
// Now we do the same test as above, but with an increasing length of data (2-16384 bytes).
public void testRSADefaultDynamic()
{
TLptsMainJut.init();
System.out.println("\nTesting Default RSA Encryption with varying data sizes...");
for (int dataSize = 2; dataSize <= 16384; dataSize *= 2)
{
System.out.print(" " + dataSize + " : ");
byte[] data = generateDataToEncrypt(dataSize);
byte[] encryptedData = TLptsCryptoUtil.defaultEncryptRSA(data);
byte[] decryptedData = TLptsCryptoUtil.defaultDecryptRSA(encryptedData);
if (!compareBytes(data, decryptedData))
failure();
System.out.print(" " + (dataSize + 1) + " : ");
data = generateDataToEncrypt(dataSize + 1);
encryptedData = TLptsCryptoUtil.defaultEncryptRSA(data);
decryptedData = TLptsCryptoUtil.defaultDecryptRSA(encryptedData);
if (!compareBytes(data, decryptedData))
failure();
}
}
// This is the simplest of tests, where we just check the default AES for correct functionality.
// The AES key is 128 bits by default and is stored in a file in the user home lapetus directory.
public void testAESDefault()
{
TLptsMainJut.init();
System.out.println("\nTesting Default AES Encryption...");
byte[] data = generateDataToEncrypt(512);
byte[] encryptedData = TLptsCryptoUtil.defaultEncryptAES(data);
byte[] decryptedData = TLptsCryptoUtil.defaultDecryptAES(encryptedData);
System.out.println("Original Bytes: " + TLptsBytesUtil.getHexString(data));
System.out.println("Encrypted Bytes: " + TLptsBytesUtil.getHexString(encryptedData));
System.out.println("Decrypted Bytes: " + TLptsBytesUtil.getHexString(decryptedData));
if (!compareBytes(data, decryptedData))
failure();
}
// Now we do the same test as above, but with an increasing length of data (2-16384 bytes).
public void testAESDefaultDynamic()
{
TLptsMainJut.init();
System.out.println("\nTesting Default AES Encryption with varying data sizes...");
for (int dataSize = 2; dataSize <= 16384; dataSize *= 2)
{
System.out.print(" " + dataSize + " : ");
byte[] data = generateDataToEncrypt(dataSize);
byte[] encryptedData = TLptsCryptoUtil.defaultEncryptAES(data);
byte[] decryptedData = TLptsCryptoUtil.defaultDecryptAES(encryptedData);
if (!compareBytes(data, decryptedData))
failure();
System.out.print(" " + (dataSize + 1) + " : ");
data = generateDataToEncrypt(dataSize + 1);
encryptedData = TLptsCryptoUtil.defaultEncryptAES(data);
decryptedData = TLptsCryptoUtil.defaultDecryptAES(encryptedData);
if (!compareBytes(data, decryptedData))
failure();
}
}
// In the test below we verify the ability to create a new RSA key from the application, with the requested size (1024 bits).
public void testRSAInstance()
{
TLptsMainJut.init();
System.out.println("\nTesting Instance RSA Encryption...");
TLptsCryptoUtil cryptoModule = new TLptsCryptoUtil();
if (!cryptoModule.initCipherRSA(1024))
{
failure("Could not initiate 1024 bit RSA key pair.");
return;
}
byte[] data = generateDataToEncrypt(512);
byte[] encryptedData = cryptoModule.encryptRSA(data);
byte[] decryptedData = cryptoModule.decryptRSA(encryptedData);
System.out.println("Original Bytes: " + TLptsBytesUtil.getHexString(data));
System.out.println("Encrypted Bytes: " + TLptsBytesUtil.getHexString(encryptedData));
System.out.println("Decrypted Bytes: " + TLptsBytesUtil.getHexString(decryptedData));
if (!compareBytes(data, decryptedData))
failure();
}
// Now we will try to initiate an AES cipher starting with a 256 bit and going down to 128.
// Depending on whether JCE is Enhanced or not, the 256 bit cipher may initiate.
// The minimum requirement is the 128 bit cipher.
public void testAESInstance()
{
TLptsMainJut.init();
System.out.println("\nTesting Instance AES Encryption...");
TLptsCryptoUtil cryptoModule = new TLptsCryptoUtil();
if (!cryptoModule.initCipherAES(cryptoModule.generateKey4AES(256))) // may not be able to do this
if (!cryptoModule.initCipherAES(cryptoModule.generateKey4AES(192))) // may not be able to do this
if (!cryptoModule.initCipherAES(cryptoModule.generateKey4AES(128))) // should be able to do this
{
failure("Could not generate at least a 128 bit key for AES");
return;
}
byte[] data = generateDataToEncrypt(512);
byte[] encryptedData = cryptoModule.encryptAES(data);
byte[] decryptedData = cryptoModule.decryptAES(encryptedData);
System.out.println("Original Bytes: " + TLptsBytesUtil.getHexString(data));
System.out.println("Encrypted Bytes: " + TLptsBytesUtil.getHexString(encryptedData));
System.out.println("Decrypted Bytes: " + TLptsBytesUtil.getHexString(decryptedData));
if (!compareBytes(data, decryptedData))
failure();
}
// This test is basically to verify that the key pair can be written to files, read and utilised with success.
// We use both instance and the default keys.
public void testRSA2Files()
{
TLptsMainJut.init();
System.out.println("\nTesting Instance RSA Encryption using files...");
// we create a new key of 1024 bits, store it in files and use it to encrypt.
TLptsCryptoUtil cryptoModule = new TLptsCryptoUtil();
if (!cryptoModule.initCipherRSA(1024))
{
failure("Could not initiate 1024 bit RSA key pair.");
return;
}
cryptoModule.writeRSA2Files(TLptsFileUtil.getUserHomeLapetusDirectory() + "my.rsa.1024.private.key.xml",
TLptsFileUtil.getUserHomeLapetusDirectory() + "my.rsa.1024.public.key.xml");
TLptsCryptoUtil.defaultWriteRSA2Files(TLptsFileUtil.getUserHomeLapetusDirectory() + "rsa.test.default.private.key.xml",
TLptsFileUtil.getUserHomeLapetusDirectory() + "rsa.test.default.public.key.xml");
byte[] data = generateDataToEncrypt(512);
byte[] encryptedData1 = cryptoModule.encryptRSA(data);
byte[] encryptedData2 = TLptsCryptoUtil.defaultEncryptRSA(data);
// now we generate a new cryptos using the key files and then decrypt
TLptsCryptoUtil cryptoModule1 = new TLptsCryptoUtil();
if (!cryptoModule1.initCipherRSA(TLptsFileUtil.getUserHomeLapetusDirectory() + "my.rsa.1024.private.key.xml",
TLptsFileUtil.getUserHomeLapetusDirectory() + "my.rsa.1024.public.key.xml"))
{
failure("Could not instantiate RSA 1024 bit from file!");
return;
}
TLptsCryptoUtil cryptoModule2 = new TLptsCryptoUtil();
if (!cryptoModule2.initCipherRSA(TLptsFileUtil.getUserHomeLapetusDirectory() + "rsa.test.default.private.key.xml",
TLptsFileUtil.getUserHomeLapetusDirectory() + "rsa.test.default.public.key.xml"))
{
failure("Could not instantiate RSA 1024 bit from file!");
return;
}
byte[] decryptedData1 = cryptoModule1.decryptRSA(encryptedData1);
byte[] decryptedData2 = cryptoModule2.decryptRSA(encryptedData2);
System.out.println("Original Bytes: " + TLptsBytesUtil.getHexString(data));
System.out.println("Encrypted Bytes(1): " + TLptsBytesUtil.getHexString(encryptedData1));
System.out.println("Decrypted Bytes(1): " + TLptsBytesUtil.getHexString(decryptedData1));
System.out.println("Encrypted Bytes(2): " + TLptsBytesUtil.getHexString(encryptedData2));
System.out.println("Decrypted Bytes(2): " + TLptsBytesUtil.getHexString(decryptedData2));
if (!compareBytes(data, decryptedData1))
failure();
if (!compareBytes(data, decryptedData2))
failure();
}
// This is a test scenario which is an everyday situation. We have a foreign public key, which will be used to encrypt data.
// Then the encrypted data is decrypted by the foreign private key holder.
// We will test both an instantiated instance and the default static instance of the crypto module.
public void testRSADefaultForeign()
{
TLptsMainJut.init();
System.out.println("\nTesting Foreign RSA Encryption (default and instantiated) ...");
TLptsCryptoUtil foreignCrypto = new TLptsCryptoUtil();
TLptsCryptoUtil localCrypto = new TLptsCryptoUtil();
// the default string are not really required here, nor below. It is here for demonstration and test purposes.
if (!foreignCrypto.initCipherRSA(2048, TLptsCryptoUtil.DEFAULT_RSA_INSTANCE_STRING, TLptsCryptoUtil.DEFAULT_RSA_KEY_STRING))
{
failure("Could not initiate Foreign 2048 bit RSA.");
return;
}
byte[] data = generateDataToEncrypt(512);
// the RSA Instance string below is TLptsCryptoUtil.DEFAULT_RSA_INSTANCE_STRING, and the key string is also default.
TLptsCryptoUtil.defaultInitForeignPublicCipherRSA(foreignCrypto.getPublicRSAModulus(), foreignCrypto.getPublicRSAExponent(), foreignCrypto.getRSAKeyBitSize(),
TLptsCryptoUtil.DEFAULT_RSA_INSTANCE_STRING, TLptsCryptoUtil.DEFAULT_RSA_KEY_STRING);
localCrypto.initForeignPublicCipherRSA(foreignCrypto.getPublicRSAModulus(), foreignCrypto.getPublicRSAExponent(), foreignCrypto.getRSAKeyBitSize(),
foreignCrypto.getRSAInstanceString(), foreignCrypto.getRSAKeyString());
byte[] encryptedData1 = TLptsCryptoUtil.defaultForeignEncryptRSA(data);
byte[] encryptedData2 = localCrypto.foreignEncryptRSA(data);
byte[] decryptedData1 = foreignCrypto.decryptRSA(encryptedData1);
byte[] decryptedData2 = foreignCrypto.decryptRSA(encryptedData2);
System.out.println("Original Bytes: " + TLptsBytesUtil.getHexString(data));
System.out.println("Encrypted Bytes(1): " + TLptsBytesUtil.getHexString(encryptedData1));
System.out.println("Encrypted Bytes(2): " + TLptsBytesUtil.getHexString(encryptedData1));
System.out.println("Decrypted Bytes(1): " + TLptsBytesUtil.getHexString(decryptedData1));
System.out.println("Decrypted Bytes(2): " + TLptsBytesUtil.getHexString(decryptedData2));
if (!compareBytes(data, decryptedData1))
failure();
if (!compareBytes(data, decryptedData2))
failure();
}
// This test is basically to verify that the AES key can be written, read and utilised with success from a file.
// We use both instance and the default keys.
public void testAES2File()
{
TLptsMainJut.init();
System.out.println("\nTesting Instance AES Encryption using a file...");
TLptsCryptoUtil cryptoModule = new TLptsCryptoUtil();
if (!cryptoModule.initCipherAES(cryptoModule.generateKey4AES(128)))
{
failure("Could not generate 128 bit key for AES");
return;
}
cryptoModule.writeAES2File(TLptsFileUtil.getUserHomeLapetusDirectory() + "my.aes.key.xml");
TLptsCryptoUtil.defaultWriteAES2File(TLptsFileUtil.getUserHomeLapetusDirectory() + "aes.test.default.key.xml");
byte[] data = generateDataToEncrypt(512);
byte[] encryptedData1 = cryptoModule.encryptAES(data);
byte[] encryptedData2 = TLptsCryptoUtil.defaultEncryptAES(data);
// now we generate a new crypto using the key file and then decrypt
TLptsCryptoUtil cryptoModule1 = new TLptsCryptoUtil();
if (!cryptoModule1.initCipherAES(TLptsFileUtil.getUserHomeLapetusDirectory() + "my.aes.key.xml"))
{
failure("Could not initiate AES cipher from file.");
return;
}
TLptsCryptoUtil cryptoModule2 = new TLptsCryptoUtil();
if (!cryptoModule2.initCipherAES(TLptsFileUtil.getUserHomeLapetusDirectory() + "aes.test.default.key.xml"))
{
failure("Could not initiate AES cipher from file.");
return;
}
byte[] decryptedData1 = cryptoModule1.decryptAES(encryptedData1);
byte[] decryptedData2 = cryptoModule2.decryptAES(encryptedData2);
System.out.println("Original Bytes: " + TLptsBytesUtil.getHexString(data));
System.out.println("Encrypted Bytes(1): " + TLptsBytesUtil.getHexString(encryptedData1));
System.out.println("Decrypted Bytes(1): " + TLptsBytesUtil.getHexString(decryptedData1));
System.out.println("Encrypted Bytes(2): " + TLptsBytesUtil.getHexString(encryptedData2));
System.out.println("Decrypted Bytes(2): " + TLptsBytesUtil.getHexString(decryptedData2));
if (!compareBytes(data, decryptedData1))
failure();
if (!compareBytes(data, decryptedData2))
failure();
}
// We have the ability to store credentials (user name and password) in one byte array, encrypted either with AES or RSA.
// In this test we will verify both RSA ans AES, for both the default and instance of TLptsCryptoUtil.
public void testCredentials()
{
TLptsMainJut.init();
System.out.println("\nTesting Credential encryption/decryption (instance and default)...");
String userName = "This Is a Really Long User Name"; // even has spaces
String password = "With such a long user name, we need a very long and difficult password like !@#$%^&&*()09876543210 - Cool!";
TLptsCryptoUtil cryptoModule = new TLptsCryptoUtil();
// initiate 3 ciphers, 1024, 2048 and 128 bit. The 1024 and 128 are default.
if (!cryptoModule.initCipherRSA(2048) ||
!cryptoModule.initCipherAES(cryptoModule.generateKey4AES(128)))
{
failure("Could not create RSA and AES Cipher instances.(2048 & 128)");
return;
}
byte[] rsaDefault = TLptsCryptoUtil.defaultEncryptCredentialsRSA(userName, password);
byte[] rsaInstance = cryptoModule.encryptCredentialsRSA(userName, password);
byte[] aesDefault = TLptsCryptoUtil.defaultEncryptCredentialsAES(userName, password);
byte[] aesInstance = cryptoModule.encryptCredentialsAES(userName, password);
if (rsaDefault == null || rsaInstance == null || aesDefault == null || aesInstance == null)
{
failure("Could not encrypt credentials");
return;
}
TLptsCryptoUtil.Credentials rsaDefaultCredentials = TLptsCryptoUtil.defaultDecryptCredentialsRSA(rsaDefault);
TLptsCryptoUtil.Credentials rsaInstanceCredentials = cryptoModule.decryptCredentialsRSA(rsaInstance);
TLptsCryptoUtil.Credentials aesDefaultCredentials = TLptsCryptoUtil.defaultDecryptCredentialsAES(aesDefault);
TLptsCryptoUtil.Credentials aesInstanceCredentials = cryptoModule.decryptCredentialsAES(aesInstance);
if (!userName.equals(rsaDefaultCredentials.userName) ||
!userName.equals(rsaInstanceCredentials.userName) ||
!userName.equals(aesDefaultCredentials.userName) ||
!userName.equals(aesInstanceCredentials.userName))
{
failure("User Name is not the same after encryption and decryption.");
return;
}
if (!password.equals(rsaDefaultCredentials.password) ||
!password.equals(rsaInstanceCredentials.password) ||
!password.equals(aesDefaultCredentials.password) ||
!password.equals(aesInstanceCredentials.password))
{
failure("Password is not the same after encryption and decryption.");
return;
}
System.out.println("Credentials successfully verified for AES and RSA.");
}
// Compares two streams of bytes for exact matching.
private boolean compareBytes(byte[] data, byte[] decryptedData)
{
if (data == null || decryptedData == null)
{
System.out.println("Comparing to null value. Failed !");
return false;
}
if (data.length != decryptedData.length)
{
System.out.println("Data is not the same length as the decrypted bytes!");
return false;
}
for (int i = 0; i < data.length; i++)
if (data[i] != decryptedData[i])
{
System.out.println("Byte comparison is not equal: Byte index " + i + " is not the same : " +
data[i] + " <> " + decryptedData[i]);
return false;
}
System.out.println("Byte comparison successful : data and decrypted bytes are identical.");
return true;
}
// This just generates bytes in an incremental fashion (0-255).
private byte[] generateDataToEncrypt(int length)
{
byte[] data = new byte[length];
for (int i = 0; i < length; i++)
data[i] = TLptsBytesUtil.initByteFromInteger(i % 256);
return data;
}
private void failure(String error)
{
System.out.println();
System.out.println("\n!@#$%^&*() Failed Test : " + error);
failure();
}
private void failure()
{
for (TLptsLog log : TLptsLogger.getLogList(false))
System.out.println(log.getMessage() + " : " + log.getSupportingText() + " : " + log.getExceptionMessage());
fail();
// System.exit(0);
}
}