start work on encrypt/decrypt test classes

This commit is contained in:
Vincent Breitmoser 2014-09-15 17:21:58 +02:00
parent 1f9bbff58d
commit 9dc22ef510
6 changed files with 134 additions and 138 deletions

View File

@ -42,6 +42,10 @@ dependencies {
} }
} }
test {
exclude '**/*$*'
}
android { android {
projectUnderTest ':OpenKeychain' projectUnderTest ':OpenKeychain'
} }
@ -64,7 +68,7 @@ jacocoTestReport {
html.destination "${buildDir}/jacocoHtml" html.destination "${buildDir}/jacocoHtml"
} }
// class R is used, but usage will not be covered, so ignore this class from report // class R is used, but usage will not be covered, so ignore this class from report
classDirectories = fileTree(dir: '../OpenKeychain/build/intermediates/classes/debug/org/sufficientlysecure/keychain', exclude: 'R*.class') classDirectories = fileTree(dir: '../OpenKeychain/build/intermediates/classes/debug/org/sufficientlysecure/keychain', exclude: [ 'R*.class' ])
additionalSourceDirs = files(coverageSourceDirs) additionalSourceDirs = files(coverageSourceDirs)
executionData = files('build/jacoco/testDebug.exec') executionData = files('build/jacoco/testDebug.exec')
} }

View File

@ -1,53 +0,0 @@
/*
* Copyright (C) Art O Cathain
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package tests;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.*;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.support.PgpVerifyTestingHelper;
@RunWith(RobolectricTestRunner.class)
@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
public class PgpDecryptVerifyTest {
@Test
public void testVerifySuccess() throws Exception {
String testFileName = "/sample.txt";
int expectedSignatureResult = OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED;
int status = new PgpVerifyTestingHelper(Robolectric.application).doTestFile(testFileName);
Assert.assertEquals(expectedSignatureResult, status);
}
@Test
public void testVerifyFailure() throws Exception {
String testFileName = "/sample-altered.txt";
int expectedSignatureResult = OpenPgpSignatureResult.SIGNATURE_ERROR;
int status = new PgpVerifyTestingHelper(Robolectric.application).doTestFile(testFileName);
Assert.assertEquals(expectedSignatureResult, status);
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.pgp;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.*;
import org.robolectric.shadows.ShadowLog;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify.NoSecretKeyException;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify.PassphraseCache;
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt.Builder;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.service.results.SignEncryptResult;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.TestingUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.security.Security;
@RunWith(RobolectricTestRunner.class)
@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
public class PgpEncryptDecryptTest {
String mPassphrase = TestingUtils.genPassphrase(true);
@BeforeClass
public static void setUpOnce() throws Exception {
Security.insertProviderAt(new BouncyCastleProvider(), 1);
ShadowLog.stream = System.out;
}
@Test
public void testSymmetricEncryptDecrypt() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
{
ByteArrayInputStream in = new ByteArrayInputStream("dies ist ein plaintext ☭".getBytes());
InputData data = new InputData(in, in.available());
Builder b = new PgpSignEncrypt.Builder(new ProviderHelper(Robolectric.application), data, out);
b.setSymmetricPassphrase(mPassphrase);
b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
SignEncryptResult result = b.build().execute();
Assert.assertTrue("encryption must succeed", result.success());
}
{
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
InputData data = new InputData(in, in.available());
out.reset();
PgpDecryptVerify.Builder b = new PgpDecryptVerify.Builder(
new ProviderHelper(Robolectric.application),
new DummyPassphraseCache(mPassphrase), data, out);
b.setPassphrase(mPassphrase);
DecryptVerifyResult result = b.build().execute();
Assert.assertTrue("decryption must succeed", result.success());
}
}
static class DummyPassphraseCache implements PassphraseCache {
String mPassphrase;
public DummyPassphraseCache(String passphrase) {
mPassphrase = passphrase;
}
@Override
public String getCachedPassphrase(long masterKeyId) throws NoSecretKeyException {
Assert.assertEquals("requested passphrase must be for symmetric id", 0L, masterKeyId);
return mPassphrase;
}
}
}

View File

@ -50,6 +50,7 @@ import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket; import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
import org.sufficientlysecure.keychain.support.TestDataUtil; import org.sufficientlysecure.keychain.support.TestDataUtil;
import org.sufficientlysecure.keychain.util.ProgressScaler; import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.TestingUtils;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
@ -65,7 +66,7 @@ import java.util.Random;
public class PgpKeyOperationTest { public class PgpKeyOperationTest {
static UncachedKeyRing staticRing; static UncachedKeyRing staticRing;
final static String passphrase = genPassphrase(); final static String passphrase = TestingUtils.genPassphrase();
UncachedKeyRing ring; UncachedKeyRing ring;
PgpKeyOperation op; PgpKeyOperation op;
@ -919,7 +920,7 @@ public class PgpKeyOperationTest {
PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag); PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag);
// modify keyring, change to non-empty passphrase // modify keyring, change to non-empty passphrase
String otherPassphrase = genPassphrase(true); String otherPassphrase = TestingUtils.genPassphrase(true);
parcel.mNewPassphrase = otherPassphrase; parcel.mNewPassphrase = otherPassphrase;
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB, ""); modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB, "");
@ -927,7 +928,7 @@ public class PgpKeyOperationTest {
Assert.assertEquals("extracted packet should be a secret subkey", Assert.assertEquals("extracted packet should be a secret subkey",
PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag); PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag);
String otherPassphrase2 = genPassphrase(true); String otherPassphrase2 = TestingUtils.genPassphrase(true);
parcel.mNewPassphrase = otherPassphrase2; parcel.mNewPassphrase = otherPassphrase2;
{ {
// if we replace a secret key with one without passphrase // if we replace a secret key with one without passphrase
@ -1096,20 +1097,4 @@ public class PgpKeyOperationTest {
} }
private static String genPassphrase() {
return genPassphrase(false);
}
private static String genPassphrase(boolean noEmpty) {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789!@#$%^&*()-_=";
Random r = new Random();
StringBuilder passbuilder = new StringBuilder();
// 20% chance for an empty passphrase
for(int i = 0, j = noEmpty || r.nextInt(10) > 2 ? r.nextInt(20)+1 : 0; i < j; i++) {
passbuilder.append(chars.charAt(r.nextInt(chars.length())));
}
System.out.println("Generated passphrase: '" + passbuilder.toString() + "'");
return passbuilder.toString();
}
} }

View File

@ -1,65 +0,0 @@
package org.sufficientlysecure.keychain.support;
/*
* Copyright (C) Art O Cathain
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
import android.content.Context;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.InputData;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/**
* For functional tests of PgpDecryptVerify
*/
public class PgpVerifyTestingHelper {
private final Context context;
public PgpVerifyTestingHelper(Context robolectricContext) {
this.context = robolectricContext;
}
public int doTestFile(String testFileName) throws Exception {
ProviderHelper providerHelper = new ProviderHelperStub(context);
PgpDecryptVerify.PassphraseCache passphraseCache = new PgpDecryptVerify.PassphraseCache() {
public String getCachedPassphrase(long masterKeyId) {
return "I am a passphrase";
}
};
byte[] sampleInputBytes = TestDataUtil.readFully(getClass().getResourceAsStream(testFileName));
InputStream sampleInput = new ByteArrayInputStream(sampleInputBytes);
InputData data = new InputData(sampleInput, sampleInputBytes.length);
OutputStream outStream = new ByteArrayOutputStream();
PgpDecryptVerify verify = new PgpDecryptVerify.Builder(providerHelper, passphraseCache, data, outStream).build();
DecryptVerifyResult result = verify.execute();
return result.getSignatureResult().getStatus();
}
}

View File

@ -0,0 +1,24 @@
package org.sufficientlysecure.keychain.util;
import java.util.Random;
/**
* Created by valodim on 9/15/14.
*/
public class TestingUtils {
public static String genPassphrase() {
return genPassphrase(false);
}
public static String genPassphrase(boolean noEmpty) {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789!@#$%^&*()-_=";
Random r = new Random();
StringBuilder passbuilder = new StringBuilder();
// 20% chance for an empty passphrase
for(int i = 0, j = noEmpty || r.nextInt(10) > 2 ? r.nextInt(20)+1 : 0; i < j; i++) {
passbuilder.append(chars.charAt(r.nextInt(chars.length())));
}
System.out.println("Generated passphrase: '" + passbuilder.toString() + "'");
return passbuilder.toString();
}
}