/*
* Copyright 2009-2014 Brian Pellin.
*
* This file is part of KeePassDroid.
*
* KeePassDroid is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* KeePassDroid is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.keepassdroid.tests.output;
import static org.junit.Assert.assertArrayEquals;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import android.content.res.AssetManager;
import android.test.AndroidTestCase;
import com.keepassdroid.database.PwDatabaseV3Debug;
import com.keepassdroid.database.PwDbHeader;
import com.keepassdroid.database.PwDbHeaderV3;
import com.keepassdroid.database.exception.PwDbOutputException;
import com.keepassdroid.database.save.PwDbHeaderOutputV3;
import com.keepassdroid.database.save.PwDbV3Output;
import com.keepassdroid.database.save.PwDbV3OutputDebug;
import com.keepassdroid.stream.NullOutputStream;
import com.keepassdroid.tests.TestUtil;
import com.keepassdroid.tests.database.TestData;
public class PwManagerOutputTest extends AndroidTestCase {
PwDatabaseV3Debug mPM;
@Override
protected void setUp() throws Exception {
super.setUp();
mPM = TestData.GetTest1(getContext());
}
public void testPlainContent() throws IOException, PwDbOutputException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PwDbV3Output pos = new PwDbV3OutputDebug(mPM, bos, true);
pos.outputPlanGroupAndEntries(bos);
assertTrue("No output", bos.toByteArray().length > 0);
assertArrayEquals("Group and entry output doesn't match.", mPM.postHeader, bos.toByteArray());
}
public void testChecksum() throws NoSuchAlgorithmException, IOException, PwDbOutputException {
//FileOutputStream fos = new FileOutputStream("/dev/null");
NullOutputStream nos = new NullOutputStream();
MessageDigest md = MessageDigest.getInstance("SHA-256");
DigestOutputStream dos = new DigestOutputStream(nos, md);
PwDbV3Output pos = new PwDbV3OutputDebug(mPM, dos, true);
pos.outputPlanGroupAndEntries(dos);
dos.close();
byte[] digest = md.digest();
assertTrue("No output", digest.length > 0);
assertArrayEquals("Hash of groups and entries failed.", mPM.dbHeader.contentsHash, digest);
}
private void assertHeadersEquals(PwDbHeaderV3 expected, PwDbHeaderV3 actual) {
assertEquals("Flags unequal", expected.flags, actual.flags);
assertEquals("Entries unequal", expected.numEntries, actual.numEntries);
assertEquals("Groups unequal", expected.numGroups, actual.numGroups);
assertEquals("Key Rounds unequal", expected.numKeyEncRounds, actual.numKeyEncRounds);
assertEquals("Signature1 unequal", expected.signature1, actual.signature1);
assertEquals("Signature2 unequal", expected.signature2, actual.signature2);
assertTrue("Version incompatible", PwDbHeaderV3.compatibleHeaders(expected.version, actual.version));
assertArrayEquals("Hash unequal", expected.contentsHash, actual.contentsHash);
assertArrayEquals("IV unequal", expected.encryptionIV, actual.encryptionIV);
assertArrayEquals("Seed unequal", expected.masterSeed, actual.masterSeed);
assertArrayEquals("Seed2 unequal", expected.transformSeed, actual.transformSeed);
}
public void testHeader() throws PwDbOutputException, IOException {
ByteArrayOutputStream bActual = new ByteArrayOutputStream();
PwDbV3Output pActual = new PwDbV3OutputDebug(mPM, bActual, true);
PwDbHeaderV3 header = pActual.outputHeader(bActual);
ByteArrayOutputStream bExpected = new ByteArrayOutputStream();
PwDbHeaderOutputV3 outExpected = new PwDbHeaderOutputV3(mPM.dbHeader, bExpected);
outExpected.output();
assertHeadersEquals(mPM.dbHeader, header);
assertTrue("No output", bActual.toByteArray().length > 0);
assertArrayEquals("Header does not match.", bExpected.toByteArray(), bActual.toByteArray());
}
public void testFinalKey() throws PwDbOutputException {
ByteArrayOutputStream bActual = new ByteArrayOutputStream();
PwDbV3Output pActual = new PwDbV3OutputDebug(mPM, bActual, true);
PwDbHeader hActual = pActual.outputHeader(bActual);
byte[] finalKey = pActual.getFinalKey(hActual);
assertArrayEquals("Keys mismatched", mPM.finalKey, finalKey);
}
public void testFullWrite() throws IOException, PwDbOutputException {
AssetManager am = getContext().getAssets();
InputStream is = am.open("test1.kdb");
// Pull file into byte array (for streaming fun)
ByteArrayOutputStream bExpected = new ByteArrayOutputStream();
while (true) {
int data = is.read();
if ( data == -1 ) {
break;
}
bExpected.write(data);
}
ByteArrayOutputStream bActual = new ByteArrayOutputStream();
PwDbV3Output pActual = new PwDbV3OutputDebug(mPM, bActual, true);
pActual.output();
//pActual.close();
FileOutputStream fos = new FileOutputStream(TestUtil.getSdPath("test1_out.kdb"));
fos.write(bActual.toByteArray());
fos.close();
assertArrayEquals("Databases do not match.", bExpected.toByteArray(), bActual.toByteArray());
}
}