aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain-Test
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2014-09-17 14:32:14 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2014-09-17 14:32:14 +0200
commita3e7406b3db904267b3ece305a369cfd2ad8583a (patch)
tree4ac8b12b418526652c53ecb53129a79a91c2673f /OpenKeychain-Test
parent27cc92cbefabb1c3a33fd0c8a2acb3da176f2c23 (diff)
downloadopen-keychain-a3e7406b3db904267b3ece305a369cfd2ad8583a.tar.gz
open-keychain-a3e7406b3db904267b3ece305a369cfd2ad8583a.tar.bz2
open-keychain-a3e7406b3db904267b3ece305a369cfd2ad8583a.zip
fix encrypt/decrypt classes
Diffstat (limited to 'OpenKeychain-Test')
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java205
1 files changed, 190 insertions, 15 deletions
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
index 065b76136..cc2eda3bc 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
@@ -18,20 +18,24 @@
package org.sufficientlysecure.keychain.pgp;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.*;
import org.robolectric.shadows.ShadowLog;
+import org.spongycastle.bcpg.sig.KeyFlags;
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.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
+import org.sufficientlysecure.keychain.service.results.EditKeyResult;
import org.sufficientlysecure.keychain.service.results.SignEncryptResult;
import org.sufficientlysecure.keychain.util.InputData;
+import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.TestingUtils;
import java.io.ByteArrayInputStream;
@@ -42,58 +46,229 @@ import java.security.Security;
@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
public class PgpEncryptDecryptTest {
- String mPassphrase = TestingUtils.genPassphrase(true);
+ static String mPassphrase = TestingUtils.genPassphrase(true);
+
+ static UncachedKeyRing mStaticRing1, mStaticRing2;
+ static String mKeyPhrase1 = TestingUtils.genPassphrase(true);
+ static String mKeyPhrase2 = TestingUtils.genPassphrase(true);
@BeforeClass
public static void setUpOnce() throws Exception {
Security.insertProviderAt(new BouncyCastleProvider(), 1);
ShadowLog.stream = System.out;
+
+ PgpKeyOperation op = new PgpKeyOperation(null);
+
+ {
+ SaveKeyringParcel parcel = new SaveKeyringParcel();
+ parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
+ Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
+ parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
+ Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
+ parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
+ Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
+ parcel.mAddUserIds.add("bloom");
+ parcel.mNewPassphrase = mKeyPhrase1;
+
+ EditKeyResult result = op.createSecretKeyRing(parcel);
+ Assert.assertTrue("initial test key creation must succeed", result.success());
+ Assert.assertNotNull("initial test key creation must succeed", result.getRing());
+
+ mStaticRing1 = result.getRing();
+ }
+
+ {
+ SaveKeyringParcel parcel = new SaveKeyringParcel();
+ parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
+ Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
+ parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
+ Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
+ parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
+ Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
+ parcel.mAddUserIds.add("belle");
+ parcel.mNewPassphrase = mKeyPhrase2;
+
+ EditKeyResult result = op.createSecretKeyRing(parcel);
+ Assert.assertTrue("initial test key creation must succeed", result.success());
+ Assert.assertNotNull("initial test key creation must succeed", result.getRing());
+
+ mStaticRing2 = result.getRing();
+ }
+
+ }
+
+ @Before
+ public void setUp() {
+ ProviderHelper providerHelper = new ProviderHelper(Robolectric.application);
+
+ providerHelper.saveSecretKeyRing(mStaticRing1, new ProgressScaler());
+ providerHelper.saveSecretKeyRing(mStaticRing1, new ProgressScaler());
}
@Test
public void testSymmetricEncryptDecrypt() {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
+ String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true);
+ byte[] ciphertext;
- {
- ByteArrayInputStream in = new ByteArrayInputStream("dies ist ein plaintext ☭".getBytes());
+ { // encrypt data with a given passphrase
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(plaintext.getBytes());
InputData data = new InputData(in, in.available());
- Builder b = new PgpSignEncrypt.Builder(new ProviderHelper(Robolectric.application), data, out);
+ Builder b = new PgpSignEncrypt.Builder(
+ new ProviderHelper(Robolectric.application),
+ new DummyPassphraseCache(mPassphrase, 0L),
+ data, out);
b.setSymmetricPassphrase(mPassphrase);
b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
SignEncryptResult result = b.build().execute();
Assert.assertTrue("encryption must succeed", result.success());
+
+ ciphertext = out.toByteArray();
}
- {
- ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
- InputData data = new InputData(in, in.available());
+ { // decryption with same passphrase should yield the same result
- out.reset();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
+ InputData data = new InputData(in, in.available());
PgpDecryptVerify.Builder b = new PgpDecryptVerify.Builder(
new ProviderHelper(Robolectric.application),
- new DummyPassphraseCache(mPassphrase), data, out);
+ new DummyPassphraseCache(mPassphrase, 0L), data, out);
b.setPassphrase(mPassphrase);
DecryptVerifyResult result = b.build().execute();
Assert.assertTrue("decryption must succeed", result.success());
+ Assert.assertArrayEquals("decrypted ciphertext should equal plaintext",
+ out.toByteArray(), plaintext.getBytes());
+ Assert.assertNull("signature should be an error", result.getSignatureResult());
+ }
+
+ { // decryption with a bad passphrase should fail
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
+ InputData data = new InputData(in, in.available());
+
+ PgpDecryptVerify.Builder b = new PgpDecryptVerify.Builder(
+ new ProviderHelper(Robolectric.application),
+ new DummyPassphraseCache(mPassphrase, 0L), data, out);
+ b.setPassphrase(mPassphrase + "x");
+ DecryptVerifyResult result = b.build().execute();
+ Assert.assertFalse("decryption must succeed", result.success());
+ Assert.assertEquals("decrypted plaintext should be empty", 0, out.size());
+ Assert.assertNull("signature should be an error", result.getSignatureResult());
+ }
+
+ { // decryption with an unset passphrase should fail
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
+ InputData data = new InputData(in, in.available());
+
+ PgpDecryptVerify.Builder b = new PgpDecryptVerify.Builder(
+ new ProviderHelper(Robolectric.application),
+ new DummyPassphraseCache(mPassphrase, 0L), data, out);
+ DecryptVerifyResult result = b.build().execute();
+ Assert.assertFalse("decryption must succeed", result.success());
+ Assert.assertEquals("decrypted plaintext should be empty", 0, out.size());
+ Assert.assertNull("signature should be an error", result.getSignatureResult());
+ }
+
+ }
+
+ @Test
+ public void testAsymmetricEncryptDecrypt() {
+
+ String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true);
+ byte[] ciphertext;
+
+ { // encrypt data with a given passphrase
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(plaintext.getBytes());
+
+ InputData data = new InputData(in, in.available());
+ Builder b = new PgpSignEncrypt.Builder(
+ new ProviderHelper(Robolectric.application),
+ new DummyPassphraseCache(mPassphrase, 0L),
+ data, out);
+
+ b.setEncryptionMasterKeyIds(new long[]{ mStaticRing1.getMasterKeyId() });
+ b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
+ SignEncryptResult result = b.build().execute();
+ Assert.assertTrue("encryption must succeed", result.success());
+
+ ciphertext = out.toByteArray();
+ }
+
+ { // decryption with provided passphrase should yield the same result
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
+ InputData data = new InputData(in, in.available());
+ PgpDecryptVerify.Builder b = new PgpDecryptVerify.Builder(
+ new ProviderHelper(Robolectric.application),
+ new DummyPassphraseCache(null, null), data, out);
+ b.setPassphrase(mKeyPhrase1);
+ DecryptVerifyResult result = b.build().execute();
+ Assert.assertTrue("decryption with provided passphrase must succeed", result.success());
+ Assert.assertArrayEquals("decrypted ciphertext with provided passphrase should equal plaintext",
+ out.toByteArray(), plaintext.getBytes());
+ Assert.assertNull("signature be empty", result.getSignatureResult());
+ }
+
+ { // decryption with passphrase cached should succeed
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
+ InputData data = new InputData(in, in.available());
+
+ PgpDecryptVerify.Builder b = new PgpDecryptVerify.Builder(
+ new ProviderHelper(Robolectric.application),
+ new DummyPassphraseCache(mKeyPhrase1, null), data, out);
+ DecryptVerifyResult result = b.build().execute();
+ Assert.assertTrue("decryption with cached passphrase must succeed", result.success());
+ Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext",
+ out.toByteArray(), plaintext.getBytes());
+ Assert.assertNull("signature should be empty", result.getSignatureResult());
+ }
+
+ { // decryption with no passphrase provided should return status pending
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
+ InputData data = new InputData(in, in.available());
+
+ PgpDecryptVerify.Builder b = new PgpDecryptVerify.Builder(
+ new ProviderHelper(Robolectric.application),
+ new DummyPassphraseCache(null, null), data, out);
+ DecryptVerifyResult result = b.build().execute();
+ Assert.assertFalse("decryption with no passphrase must return pending", result.success());
+ Assert.assertTrue("decryption with no passphrase should return pending", result.isPending());
+ Assert.assertEquals("decryption with no passphrase should return pending passphrase",
+ DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE, result.getResult());
}
}
- static class DummyPassphraseCache implements PassphraseCache {
+ static class DummyPassphraseCache implements PassphraseCacheInterface {
String mPassphrase;
- public DummyPassphraseCache(String passphrase) {
+ Long mExpectedId;
+ public DummyPassphraseCache(String passphrase, Long expectedId) {
mPassphrase = passphrase;
+ mExpectedId = expectedId;
}
@Override
public String getCachedPassphrase(long masterKeyId) throws NoSecretKeyException {
- Assert.assertEquals("requested passphrase must be for symmetric id", 0L, masterKeyId);
+ if (mExpectedId != null){
+ Assert.assertEquals("requested passphrase must be for expected id",
+ (long) mExpectedId, masterKeyId);
+ }
return mPassphrase;
}
}