package uk.ac.cam.db538.cryptosms.storage;
import java.io.IOException;
import uk.ac.cam.db538.cryptosms.storage.Conversation;
import uk.ac.cam.db538.cryptosms.storage.SessionKeys;
import uk.ac.cam.db538.cryptosms.storage.Storage;
import uk.ac.cam.db538.cryptosms.storage.StorageFileException;
import uk.ac.cam.db538.cryptosms.utils.Charset;
import uk.ac.cam.db538.cryptosms.utils.SimNumber;
import uk.ac.cam.db538.cryptosms.CustomAsserts;
import uk.ac.cam.db538.cryptosms.crypto.Encryption;
import uk.ac.cam.db538.cryptosms.crypto.EncryptionNone;
import uk.ac.cam.db538.cryptosms.crypto.EncryptionInterface.EncryptionException;
import uk.ac.cam.db538.cryptosms.utils.LowLevel;
import junit.framework.TestCase;
public class SessionKeys_Test extends TestCase {
protected void setUp() throws Exception {
super.setUp();
EncryptionNone.initEncryption();
Common.clearStorageFile();
sessionKey_Out = Encryption.getEncryption().generateRandomData(Encryption.SYM_KEY_LENGTH);
sessionKey_In = Encryption.getEncryption().generateRandomData(Encryption.SYM_KEY_LENGTH);
}
protected void tearDown() throws Exception {
super.tearDown();
Common.closeStorageFile();
}
private boolean keysSent = true;
private boolean keysConfirmed = true;
private boolean simSerial = true;
private String simNumber = "+123456789012";
private byte[] sessionKey_Out = null;
private byte lastID_Out = 0x12;
private byte[] sessionKey_In = null;
private byte lastID_In = 0x18;
private long indexParent = 246L;
private long indexPrev = 247L;
private long indexNext = 248L;
private String simNumberLong = "+1234567890126549873sdfsat6ewrt987wet3df1g3s2g1e6r5t46wert4dfsgdfsg";
private String simNumberResult = "+1234567890126549873sdfsat6ewrt9";
private byte flags = (byte) 0xE0;
private void setData(SessionKeys keys, boolean longer) {
keys.setKeysSent(keysSent);
keys.setKeysConfirmed(keysConfirmed);
keys.setSimNumber(new SimNumber((longer) ? simNumberLong : simNumber, simSerial));
keys.setSessionKey_Out(sessionKey_Out);
keys.setNextID_Out(lastID_Out);
keys.setSessionKey_In(sessionKey_In);
keys.setLastID_In(lastID_In);
keys.setIndexParent(indexParent);
keys.setIndexPrev(indexPrev);
keys.setIndexNext(indexNext);
}
private void checkData(SessionKeys keys, boolean longer) {
assertEquals(keysSent, keys.getKeysSent());
assertEquals(keysConfirmed, keys.getKeysConfirmed());
assertEquals(simSerial, keys.getSimNumber().isSerial());
assertEquals((longer) ? simNumberResult : simNumber, keys.getSimNumber().getNumber());
CustomAsserts.assertArrayEquals(keys.getSessionKey_Out(), sessionKey_Out);
assertEquals(lastID_Out, keys.getNextID_Out());
CustomAsserts.assertArrayEquals(keys.getSessionKey_In(), sessionKey_In);
assertEquals(lastID_In, keys.getLastID_In());
assertEquals(indexParent, keys.getIndexParent());
assertEquals(indexPrev, keys.getIndexPrev());
assertEquals(indexNext, keys.getIndexNext());
}
public void testConstruction() throws StorageFileException, IOException {
Conversation conv = Conversation.createConversation();
SessionKeys keys = SessionKeys.createSessionKeys(conv);
assertTrue(Common.checkStructure());
setData(keys, false);
keys.saveToFile();
long index = keys.getEntryIndex();
// force to be re-read
SessionKeys.forceClearCache();
keys = SessionKeys.getSessionKeys(index);
checkData(keys, false);
}
public void testIndices() throws StorageFileException, IOException {
// INDICES OUT OF BOUNDS
Conversation conv = Conversation.createConversation();
SessionKeys keys = SessionKeys.createSessionKeys(conv);
// indexNext
try {
keys.setIndexNext(0x0100000000L);
assertTrue(false);
} catch (IndexOutOfBoundsException ex) {
}
try {
keys.setIndexNext(-1L);
assertTrue(false);
} catch (IndexOutOfBoundsException ex) {
}
}
public void testCreateData() throws StorageFileException, IOException, EncryptionException {
Conversation conv = Conversation.createConversation();
SessionKeys keys = SessionKeys.createSessionKeys(conv);
setData(keys, true);
keys.saveToFile();
// get the generated data
byte[] dataEncrypted = Storage.getStorage().getEntry(keys.getEntryIndex());
// chunk length
assertEquals(dataEncrypted.length, Storage.CHUNK_SIZE);
// decrypt the encoded part
byte[] dataPlain = Encryption.getEncryption().decryptSymmetricWithMasterKey(dataEncrypted);
// check the data
assertEquals(flags, dataPlain[0]);
assertEquals(Charset.fromAscii8(dataPlain, 1, 32), simNumberResult);
CustomAsserts.assertArrayEquals(dataPlain, 33, sessionKey_Out, 0, 32);
assertEquals(lastID_Out, dataPlain[65]);
CustomAsserts.assertArrayEquals(dataPlain, 66, sessionKey_In, 0, 32);
assertEquals(lastID_In, dataPlain[98]);
assertEquals(LowLevel.getUnsignedInt(dataPlain, Storage.ENCRYPTED_ENTRY_SIZE - 12), indexParent);
assertEquals(LowLevel.getUnsignedInt(dataPlain, Storage.ENCRYPTED_ENTRY_SIZE - 8), indexPrev);
assertEquals(LowLevel.getUnsignedInt(dataPlain, Storage.ENCRYPTED_ENTRY_SIZE - 4), indexNext);
}
public void testParseData() throws StorageFileException, IOException, EncryptionException {
Conversation conv = Conversation.createConversation();
SessionKeys keys = SessionKeys.createSessionKeys(conv);
long index = keys.getEntryIndex();
// create plain data
byte[] dataPlain = new byte[Storage.ENCRYPTED_ENTRY_SIZE];
dataPlain[0] = flags;
System.arraycopy(Charset.toAscii8(simNumber, 32), 0, dataPlain, 1, 32);
System.arraycopy(sessionKey_Out, 0, dataPlain, 33, 32);
dataPlain[65] = lastID_Out;
System.arraycopy(sessionKey_In, 0, dataPlain, 66, 32);
dataPlain[98] = lastID_In;
System.arraycopy(LowLevel.getBytesUnsignedInt(indexParent), 0, dataPlain, Storage.ENCRYPTED_ENTRY_SIZE - 12, 4);
System.arraycopy(LowLevel.getBytesUnsignedInt(indexPrev), 0, dataPlain, Storage.ENCRYPTED_ENTRY_SIZE - 8, 4);
System.arraycopy(LowLevel.getBytesUnsignedInt(indexNext), 0, dataPlain, Storage.ENCRYPTED_ENTRY_SIZE - 4, 4);
// encrypt it
byte[] dataEncrypted = Encryption.getEncryption().encryptSymmetricWithMasterKey(dataPlain);
// inject it into the file
Storage.getStorage().setEntry(index, dataEncrypted);
// have it parsed
SessionKeys.forceClearCache();
keys = SessionKeys.getSessionKeys(index);
// check the indices
checkData(keys, false);
}
}