package uk.ac.cam.tfmw2.stegdroid;
import imp.javax.sound.sampled.AudioFileFormat.Type;
import imp.javax.sound.sampled.AudioFormat;
import imp.javax.sound.sampled.AudioInputStream;
import imp.javax.sound.sampled.UnsupportedAudioFileException;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;
import uk.ac.cam.tfmw2.stegdroid.EchoStegFile.Complex;
import android.util.Log;
import com.sun.media.sound.WaveFileReader;
import com.sun.media.sound.WaveFileWriter;
public class Tests {
public static boolean complexLogTest(){
// Tests the complex Log function with a couple of known input/output values
EchoStegFile esf = new EchoStegFile();
Complex c = esf.new Complex(1.0f,1.0f);
c.log();
Log.v("complexLogTest","Ln(1+i) = "+c.real+" + "+c.imag+"i");
if(c.real != (float)0.346573590279972654708616060729088284037750067180127627060 || c.imag != (float)0.785398163397448309615660845819875721049292349843776455243 ) return false;
c = esf.new Complex(2.0f,3.0f);
c.log();
Log.v("complexLogTest","Ln(2+3i) = "+c.real+" + "+c.imag+"i");
if(c.real != (float)1.28247467873076836802674372078265930240263397238010355820 || c.imag != (float)0.982793723247329067985710611014666014496877453631628556761 ) return false;
return true;
}
public static boolean bitStreamTest(){
// Tests BitStream with unencrypted data. Turns a String into a BitStream and
// verifies that the output matches the input
String testString1 = "Help! Zombie Gingerbread Men are invading my phone!";
BitStream putIn = new BitStream(testString1);
int[] output = new int[(testString1.length() + 2) * 8];
int i = 0;
while(true){
try {
output[i++] = putIn.getNextBit();
} catch (EndOfBitStreamException e) {
break;
}
}
BitStream takeOut = new BitStream();
i = 0;
boolean finished = false;
while(!finished){
finished = takeOut.setNextBit(output[i++]);
}
String testStringResult1 = takeOut.getString();
Log.v("bitStreamTest","input: "+testString1+" output: "+testStringResult1);
return testString1.equals(testStringResult1);
}
public static boolean bitStreamLongCharsTest(){
// Checks an unencrypted BitStream with multi-byte characters
String testString1 = "���";
BitStream putIn = new BitStream(testString1);
int[] output = new int[(testString1.getBytes().length + 2) * 8];
int i = 0;
while(true){
try {
output[i++] = putIn.getNextBit();
} catch (EndOfBitStreamException e) {
break;
}
}
BitStream takeOut = new BitStream();
i = 0;
boolean finished = false;
while(!finished){
finished = takeOut.setNextBit(output[i++]);
}
String testStringResult1 = takeOut.getString();
Log.v("bitStreamTestLongChars","input: "+testString1+" output: "+testStringResult1);
return testString1.equals(testStringResult1);
}
public static boolean cryptoTest(){
// Confirms that crypto is working correctly, in particular, this
// test will fail if the specified crypto library is not available
// on the device
byte[] input = new String("Test Data").getBytes();
SecretKeySpec key = new SecretKeySpec(BitStream.padKey("TestKey"), "AES");
Cipher cipher;
try {
cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
Log.v("cryptoTest",new String(input));
// encryption pass
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cryptoBytes = new byte[cipher.getOutputSize(input.length)];
int cryptoBytesLength = cipher.update(input, 0, input.length, cryptoBytes, 0);
cryptoBytesLength += cipher.doFinal(cryptoBytes, cryptoBytesLength);
// decryption pass
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedBytes = new byte[cipher.getOutputSize(cryptoBytesLength)];
int actualLength = cipher.update(cryptoBytes, 0, cryptoBytesLength, decryptedBytes, 0);
actualLength += cipher.doFinal(decryptedBytes, actualLength);
Log.v("cryptoTest",new String(decryptedBytes));
Log.v("cryptoTest",actualLength+"");
byte[] outputBytes = new byte[actualLength];
System.arraycopy(decryptedBytes, 0, outputBytes, 0, actualLength);
return (new String(outputBytes).equals("Test Data"));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return false;
} catch (NoSuchProviderException e) {
e.printStackTrace();
return false;
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return false;
} catch (InvalidKeyException e) {
e.printStackTrace();
return false;
} catch (ShortBufferException e) {
e.printStackTrace();
return false;
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
return false;
} catch (BadPaddingException e) {
e.printStackTrace();
return false;
}
}
public static float stegReliabilityTest(String rootDir,String unencodedFilePath){
WaveFileReader wfr = new WaveFileReader();
File waveFile = new File(rootDir + unencodedFilePath);
File saveFile = new File(rootDir + "test.wav");
AudioInputStream stream;
try {
stream = wfr.getAudioInputStream(waveFile);
AudioFormat format = stream.getFormat();
Log.v("stegTest","Format info: "+format.getEncoding().toString()+format.getSampleRate()+" "+format.getSampleSizeInBits()+" "+format.getChannels()+" "+format.getFrameSize()+" "+format.getFrameRate()+" "+(format.isBigEndian() ? "true" : "false"));
int length = (int) (stream.getFrameLength() * format.getFrameSize());
Log.v("stegTest","Encode Length: "+Integer.toString(length));
// read the entire stream
byte[] samples = new byte[length];
DataInputStream dis = new DataInputStream(stream);
try {
// This could be improved by using a ByteBuffer
//TODO
dis.readFully(samples);
} catch (IOException ex) {
//TODO
ex.printStackTrace();
}
String input = "longish string for testing";
BitStream bs = new BitStream(input);
EchoStegFile esf = new EchoStegFile(bs);
//filter the whole thing in one go
byte[] newSamples = esf.embed(samples, 0, length);
ByteArrayInputStream bais = new ByteArrayInputStream(newSamples);
WaveFileWriter wfw = new WaveFileWriter();
AudioInputStream oStream = new AudioInputStream(bais,format,newSamples.length / 2);
wfw.write(oStream, Type.WAVE, saveFile);
//now read in
wfr = new WaveFileReader();
AudioInputStream readStream;
readStream = wfr.getAudioInputStream(saveFile);
//get the format information and initialize buffers
format = readStream.getFormat();
length = (int) (readStream.getFrameLength() * format.getFrameSize());
// read the entire stream
samples = new byte[length];
dis = new DataInputStream(readStream);
try {
dis.readFully(samples);
} catch (IOException ex) {
}
//Set up BitStream, EchoStegFile, Message and String for output
BitStream sbs = new BitStream();
esf = new EchoStegFile();
String result;
//Perform extraction
esf.extract(samples, sbs);
result = sbs.getString();
//compare
BitStream instream = new BitStream(input);
BitStream outstream = new BitStream(result);
int count = 0;
int correct = 0;
while(!instream.endOfBitStream() && !outstream.endOfBitStream()){
try {
if(instream.getNextBit() == outstream.getNextBit()){
correct++;
}
} catch (EndOfBitStreamException e) {
break;
}
count++;
}
float percentage = 100 * (float)correct / (float)count;
return percentage;
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
return 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
public static float vorbisTest(String rootDir,String inputFilePath){
String testFilePath = rootDir + "test.ogg";
String outputFilePath = rootDir + "oggTestOutput.wav";
String input = "longish string for testing";
File inputFile = new File(rootDir + inputFilePath);
Vorbis ve = new Vorbis();
try {
ve.encode(new FileInputStream(inputFile),new File(testFilePath));
File outputFile = new File(outputFilePath);
ve.decode(new FileInputStream(new File(testFilePath)),outputFile);
//extract
WaveFileReader wfr = new WaveFileReader();
AudioInputStream readStream;
readStream = wfr.getAudioInputStream(new File(outputFilePath));
//get the format information and initialize buffers
AudioFormat format = readStream.getFormat();
int length = (int) (readStream.getFrameLength() * format.getFrameSize());
// read the entire stream
byte[] samples = new byte[length];
DataInputStream dis = new DataInputStream(readStream);
try {
dis.readFully(samples);
} catch (IOException ex) {
}
//Set up BitStream, EchoStegFile, Message and String for output
BitStream sbs = new BitStream();
EchoStegFile esf = new EchoStegFile();
String result;
//Perform extraction
esf.extract(samples, sbs);
result = sbs.getString();
//compare
BitStream instream = new BitStream(input);
BitStream outstream = new BitStream(result);
int count = 0;
int correct = 0;
while(!instream.endOfBitStream() && !outstream.endOfBitStream()){
try {
if(instream.getNextBit() == outstream.getNextBit()){
correct++;
}
} catch (EndOfBitStreamException e) {
break;
}
count++;
}
float percentage = 100 * (float)correct / (float)count;
return percentage;
} catch (FileNotFoundException e) {
e.printStackTrace();
return 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
} catch (UnsupportedAudioFileException e){
e.printStackTrace();
return 0;
}
}
}