aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2015-06-11 00:05:13 +0200
committerDominik Schürmann <dominik@dominikschuermann.de>2015-06-11 00:05:13 +0200
commitd16b09b2a6be41319b993c27e69b85067a7f1c46 (patch)
tree78deb6554f9bd5f3505adb39bfbbd10e692dab9e /OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain
parent05fcbcae7b816e72363030d499a43e0e6042b320 (diff)
downloadopen-keychain-d16b09b2a6be41319b993c27e69b85067a7f1c46.tar.gz
open-keychain-d16b09b2a6be41319b993c27e69b85067a7f1c46.tar.bz2
open-keychain-d16b09b2a6be41319b993c27e69b85067a7f1c46.zip
Use new officially supported way for local unit tests, many dependencies upgraded for this, temporary disabled separate debug builds
Diffstat (limited to 'OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain')
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java260
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/ExportTest.java224
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java187
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/KeyRingTest.java53
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java585
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java1376
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java764
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java493
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java157
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperKeyringTest.java101
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java251
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringBuilder.java254
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java365
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/ProviderHelperStub.java36
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/TestDataUtil.java142
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/Iso7816TLVTest.java99
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/ParcelableFileCacheTest.java77
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/TestingUtils.java38
18 files changed, 0 insertions, 5462 deletions
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java
deleted file mode 100644
index 130b86908..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.operations;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.ShadowLog;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.sufficientlysecure.keychain.operations.results.CertifyResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
-import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
-import org.sufficientlysecure.keychain.operations.results.ExportResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
-import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
-import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing.IteratorWithIOThrow;
-import org.sufficientlysecure.keychain.pgp.WrappedSignature;
-import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
-import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
-import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
-import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
-import org.sufficientlysecure.keychain.util.InputData;
-import org.sufficientlysecure.keychain.util.Passphrase;
-import org.sufficientlysecure.keychain.util.ProgressScaler;
-import org.sufficientlysecure.keychain.util.TestingUtils;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.security.Security;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Random;
-
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class CertifyOperationTest {
-
- static UncachedKeyRing mStaticRing1, mStaticRing2;
- static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
- static Passphrase mKeyPhrase2 = TestingUtils.genPassphrase(true);
-
- static PrintStream oldShadowStream;
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- Security.insertProviderAt(new BouncyCastleProvider(), 1);
- oldShadowStream = ShadowLog.stream;
- // ShadowLog.stream = System.out;
-
- Random random = new Random();
-
- 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("derp");
- parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
-
- PgpEditKeyResult 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("ditz");
- byte[] uatdata = new byte[random.nextInt(150)+10];
- random.nextBytes(uatdata);
- parcel.mAddUserAttribute.add(
- WrappedUserAttribute.fromSubpacket(random.nextInt(100)+1, uatdata));
-
- parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase2);
-
- PgpEditKeyResult 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() throws Exception {
- ProviderHelper providerHelper = new ProviderHelper(Robolectric.application);
-
- // don't log verbosely here, we're not here to test imports
- ShadowLog.stream = oldShadowStream;
-
- providerHelper.saveSecretKeyRing(mStaticRing1, new ProgressScaler());
- providerHelper.savePublicKeyRing(mStaticRing2.extractPublicKeyRing(), new ProgressScaler());
-
- // ok NOW log verbosely!
- ShadowLog.stream = System.out;
- }
-
- @Test
- public void testSelfCertifyFlag() throws Exception {
-
- CanonicalizedPublicKeyRing ring = new ProviderHelper(Robolectric.application)
- .getCanonicalizedPublicKeyRing(mStaticRing1.getMasterKeyId());
- Assert.assertEquals("secret key must be marked self-certified in database",
- // TODO this should be more correctly be VERIFIED_SELF at some point!
- Certs.VERIFIED_SECRET, ring.getVerified());
-
- }
-
- @Test
- public void testCertifyId() throws Exception {
- CertifyOperation op = new CertifyOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null, null);
-
- {
- CanonicalizedPublicKeyRing ring = new ProviderHelper(Robolectric.application)
- .getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
- Assert.assertEquals("public key must not be marked verified prior to certification",
- Certs.UNVERIFIED, ring.getVerified());
- }
-
- CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId());
- actions.add(new CertifyAction(mStaticRing2.getMasterKeyId(),
- mStaticRing2.getPublicKey().getUnorderedUserIds()));
- CertifyResult result = op.certify(actions, new CryptoInputParcel(mKeyPhrase1), null);
-
- Assert.assertTrue("certification must succeed", result.success());
-
- {
- CanonicalizedPublicKeyRing ring = new ProviderHelper(Robolectric.application)
- .getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
- Assert.assertEquals("new key must be verified now",
- Certs.VERIFIED_SECRET, ring.getVerified());
- }
-
- }
-
- @Test
- public void testCertifyAttribute() throws Exception {
- CertifyOperation op = new CertifyOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null, null);
-
- {
- CanonicalizedPublicKeyRing ring = new ProviderHelper(Robolectric.application)
- .getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
- Assert.assertEquals("public key must not be marked verified prior to certification",
- Certs.UNVERIFIED, ring.getVerified());
- }
-
- CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId());
- actions.add(new CertifyAction(mStaticRing2.getMasterKeyId(), null,
- mStaticRing2.getPublicKey().getUnorderedUserAttributes()));
- CertifyResult result = op.certify(actions, new CryptoInputParcel(mKeyPhrase1), null);
-
- Assert.assertTrue("certification must succeed", result.success());
-
- {
- CanonicalizedPublicKeyRing ring = new ProviderHelper(Robolectric.application)
- .getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
- Assert.assertEquals("new key must be verified now",
- Certs.VERIFIED_SECRET, ring.getVerified());
- }
-
- }
-
-
- @Test
- public void testCertifySelf() throws Exception {
- CertifyOperation op = new CertifyOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null, null);
-
- CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId());
- actions.add(new CertifyAction(mStaticRing1.getMasterKeyId(),
- mStaticRing2.getPublicKey().getUnorderedUserIds()));
-
- CertifyResult result = op.certify(actions, new CryptoInputParcel(mKeyPhrase1), null);
-
- Assert.assertFalse("certification with itself must fail!", result.success());
- Assert.assertTrue("error msg must be about self certification",
- result.getLog().containsType(LogType.MSG_CRT_ERROR_SELF));
- }
-
- @Test
- public void testCertifyNonexistent() throws Exception {
-
- CertifyOperation op = new CertifyOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null, null);
-
- {
- CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId());
- ArrayList<String> uids = new ArrayList<String>();
- uids.add("nonexistent");
- actions.add(new CertifyAction(1234L, uids));
-
- CertifyResult result = op.certify(actions, new CryptoInputParcel(mKeyPhrase1), null);
-
- Assert.assertFalse("certification of nonexistent key must fail", result.success());
- Assert.assertTrue("must contain error msg about not found",
- result.getLog().containsType(LogType.MSG_CRT_WARN_NOT_FOUND));
- }
-
- {
- CertifyActionsParcel actions = new CertifyActionsParcel(1234L);
- actions.add(new CertifyAction(mStaticRing1.getMasterKeyId(),
- mStaticRing2.getPublicKey().getUnorderedUserIds()));
-
- CertifyResult result = op.certify(actions, new CryptoInputParcel(mKeyPhrase1), null);
-
- Assert.assertFalse("certification of nonexistent key must fail", result.success());
- Assert.assertTrue("must contain error msg about not found",
- result.getLog().containsType(LogType.MSG_CRT_ERROR_MASTER_NOT_FOUND));
- }
-
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/ExportTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/ExportTest.java
deleted file mode 100644
index 23ea356c8..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/ExportTest.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * 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.operations;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.ShadowLog;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
-import org.sufficientlysecure.keychain.operations.results.ExportResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing.IteratorWithIOThrow;
-import org.sufficientlysecure.keychain.pgp.WrappedSignature;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
-import org.sufficientlysecure.keychain.util.Passphrase;
-import org.sufficientlysecure.keychain.util.ProgressScaler;
-import org.sufficientlysecure.keychain.util.TestingUtils;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.security.Security;
-import java.util.Iterator;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class ExportTest {
-
- static Passphrase mPassphrase = TestingUtils.genPassphrase(true);
-
- static UncachedKeyRing mStaticRing1, mStaticRing2;
- static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
- static Passphrase mKeyPhrase2 = TestingUtils.genPassphrase(true);
-
- static PrintStream oldShadowStream;
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- Security.insertProviderAt(new BouncyCastleProvider(), 1);
- oldShadowStream = ShadowLog.stream;
- // 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("snips");
- parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
-
- PgpEditKeyResult 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("snails");
- parcel.mNewUnlock = new ChangeUnlockParcel(null, new Passphrase("1234"));
-
- PgpEditKeyResult 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);
-
- // don't log verbosely here, we're not here to test imports
- ShadowLog.stream = oldShadowStream;
-
- providerHelper.saveSecretKeyRing(mStaticRing1, new ProgressScaler());
- providerHelper.saveSecretKeyRing(mStaticRing2, new ProgressScaler());
-
- // ok NOW log verbosely!
- ShadowLog.stream = System.out;
- }
-
- @Test
- public void testExportAll() throws Exception {
- ImportExportOperation op = new ImportExportOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
-
- // make sure there is a local cert (so the later checks that there are none are meaningful)
- Assert.assertTrue("second keyring has local certification", checkForLocal(mStaticRing2));
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ExportResult result = op.exportKeyRings(new OperationLog(), null, false, out);
-
- Assert.assertTrue("export must be a success", result.success());
-
- long masterKeyId1, masterKeyId2;
- if (mStaticRing1.getMasterKeyId() < mStaticRing2.getMasterKeyId()) {
- masterKeyId1 = mStaticRing1.getMasterKeyId();
- masterKeyId2 = mStaticRing2.getMasterKeyId();
- } else {
- masterKeyId2 = mStaticRing1.getMasterKeyId();
- masterKeyId1 = mStaticRing2.getMasterKeyId();
- }
-
- IteratorWithIOThrow<UncachedKeyRing> unc =
- UncachedKeyRing.fromStream(new ByteArrayInputStream(out.toByteArray()));
-
- {
- Assert.assertTrue("export must have two keys (1/2)", unc.hasNext());
- UncachedKeyRing ring = unc.next();
- Assert.assertEquals("first exported key has correct masterkeyid",
- masterKeyId1, ring.getMasterKeyId());
- Assert.assertFalse("first exported key must not be secret", ring.isSecret());
- Assert.assertFalse("there must be no local signatures in an exported keyring",
- checkForLocal(ring));
- }
-
- {
- Assert.assertTrue("export must have two keys (2/2)", unc.hasNext());
- UncachedKeyRing ring = unc.next();
- Assert.assertEquals("second exported key has correct masterkeyid",
- masterKeyId2, ring.getMasterKeyId());
- Assert.assertFalse("second exported key must not be secret", ring.isSecret());
- Assert.assertFalse("there must be no local signatures in an exported keyring",
- checkForLocal(ring));
- }
-
- out = new ByteArrayOutputStream();
- result = op.exportKeyRings(new OperationLog(), null, true, out);
-
- Assert.assertTrue("export must be a success", result.success());
-
- unc = UncachedKeyRing.fromStream(new ByteArrayInputStream(out.toByteArray()));
-
- {
- Assert.assertTrue("export must have four keys (1/4)", unc.hasNext());
- UncachedKeyRing ring = unc.next();
- Assert.assertEquals("1/4 exported key has correct masterkeyid",
- masterKeyId1, ring.getMasterKeyId());
- Assert.assertFalse("1/4 exported key must not be public", ring.isSecret());
- Assert.assertFalse("there must be no local signatures in an exported keyring",
- checkForLocal(ring));
-
- Assert.assertTrue("export must have four keys (2/4)", unc.hasNext());
- ring = unc.next();
- Assert.assertEquals("2/4 exported key has correct masterkeyid",
- masterKeyId1, ring.getMasterKeyId());
- Assert.assertTrue("2/4 exported key must be public", ring.isSecret());
- Assert.assertFalse("there must be no local signatures in an exported keyring",
- checkForLocal(ring));
- }
-
- {
- Assert.assertTrue("export must have four keys (3/4)", unc.hasNext());
- UncachedKeyRing ring = unc.next();
- Assert.assertEquals("3/4 exported key has correct masterkeyid",
- masterKeyId2, ring.getMasterKeyId());
- Assert.assertFalse("3/4 exported key must not be public", ring.isSecret());
- Assert.assertFalse("there must be no local signatures in an exported keyring",
- checkForLocal(ring));
-
- Assert.assertTrue("export must have four keys (4/4)", unc.hasNext());
- ring = unc.next();
- Assert.assertEquals("4/4 exported key has correct masterkeyid",
- masterKeyId2, ring.getMasterKeyId());
- Assert.assertTrue("4/4 exported key must be public", ring.isSecret());
- Assert.assertFalse("there must be no local signatures in an exported keyring",
- checkForLocal(ring));
- }
-
- }
-
- /** This function checks whether or not there are any local signatures in a keyring. */
- private boolean checkForLocal(UncachedKeyRing ring) {
- Iterator<WrappedSignature> sigs = ring.getPublicKey().getSignatures();
- while (sigs.hasNext()) {
- if (sigs.next().isLocal()) {
- return true;
- }
- }
- return false;
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java
deleted file mode 100644
index 2ca904656..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.operations;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.ShadowLog;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.spongycastle.util.encoders.Hex;
-import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
-import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
-import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
-import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
-import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
-import org.sufficientlysecure.keychain.util.Passphrase;
-import org.sufficientlysecure.keychain.util.ProgressScaler;
-import org.sufficientlysecure.keychain.util.TestingUtils;
-
-import java.io.PrintStream;
-import java.security.Security;
-import java.util.Iterator;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class PromoteKeyOperationTest {
-
- static UncachedKeyRing mStaticRing;
- static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
-
- static PrintStream oldShadowStream;
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- Security.insertProviderAt(new BouncyCastleProvider(), 1);
- oldShadowStream = ShadowLog.stream;
- // 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("derp");
- parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
-
- PgpEditKeyResult result = op.createSecretKeyRing(parcel);
- Assert.assertTrue("initial test key creation must succeed", result.success());
- Assert.assertNotNull("initial test key creation must succeed", result.getRing());
-
- mStaticRing = result.getRing();
- }
-
- }
-
- @Before
- public void setUp() throws Exception {
- ProviderHelper providerHelper = new ProviderHelper(Robolectric.application);
-
- // don't log verbosely here, we're not here to test imports
- ShadowLog.stream = oldShadowStream;
-
- providerHelper.savePublicKeyRing(mStaticRing.extractPublicKeyRing(), new ProgressScaler());
-
- // ok NOW log verbosely!
- ShadowLog.stream = System.out;
- }
-
- @Test
- public void testPromote() throws Exception {
- PromoteKeyOperation op = new PromoteKeyOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null, null);
-
- PromoteKeyResult result = op.execute(mStaticRing.getMasterKeyId(), null, null);
-
- Assert.assertTrue("promotion must succeed", result.success());
-
- {
- CachedPublicKeyRing ring = new ProviderHelper(Robolectric.application)
- .getCachedPublicKeyRing(mStaticRing.getMasterKeyId());
- Assert.assertTrue("key must have a secret now", ring.hasAnySecret());
-
- Iterator<UncachedPublicKey> it = mStaticRing.getPublicKeys();
- while (it.hasNext()) {
- long keyId = it.next().getKeyId();
- Assert.assertEquals("all subkeys must be gnu dummy",
- SecretKeyType.GNU_DUMMY, ring.getSecretKeyType(keyId));
- }
- }
-
- }
-
- @Test
- public void testPromoteDivert() throws Exception {
- PromoteKeyOperation op = new PromoteKeyOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null, null);
-
- byte[] aid = Hex.decode("D2760001240102000000012345670000");
-
- PromoteKeyResult result = op.execute(mStaticRing.getMasterKeyId(), aid, null);
-
- Assert.assertTrue("promotion must succeed", result.success());
-
- {
- CanonicalizedSecretKeyRing ring = new ProviderHelper(Robolectric.application)
- .getCanonicalizedSecretKeyRing(mStaticRing.getMasterKeyId());
-
- for (CanonicalizedSecretKey key : ring.secretKeyIterator()) {
- Assert.assertEquals("all subkeys must be divert-to-card",
- SecretKeyType.DIVERT_TO_CARD, key.getSecretKeyType());
- Assert.assertArrayEquals("all subkeys must have correct iv",
- aid, key.getIv());
- }
-
- }
- }
-
- @Test
- public void testPromoteDivertSpecific() throws Exception {
- PromoteKeyOperation op = new PromoteKeyOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null, null);
-
- byte[] aid = Hex.decode("D2760001240102000000012345670000");
-
- // only promote the first, rest stays dummy
- long keyId = KeyringTestingHelper.getSubkeyId(mStaticRing, 1);
-
- PromoteKeyResult result = op.execute(mStaticRing.getMasterKeyId(), aid, new long[] {
- keyId
- });
-
- Assert.assertTrue("promotion must succeed", result.success());
-
- {
- CanonicalizedSecretKeyRing ring = new ProviderHelper(Robolectric.application)
- .getCanonicalizedSecretKeyRing(mStaticRing.getMasterKeyId());
-
- for (CanonicalizedSecretKey key : ring.secretKeyIterator()) {
- if (key.getKeyId() == keyId) {
- Assert.assertEquals("subkey must be divert-to-card",
- SecretKeyType.DIVERT_TO_CARD, key.getSecretKeyType());
- Assert.assertArrayEquals("subkey must have correct iv",
- aid, key.getIv());
- } else {
- Assert.assertEquals("some subkeys must be gnu dummy",
- SecretKeyType.GNU_DUMMY, key.getSecretKeyType());
- }
- }
-
- }
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/KeyRingTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/KeyRingTest.java
deleted file mode 100644
index 6656c5131..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/KeyRingTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class KeyRingTest {
-
- @Test
- public void splitCompleteUserIdShouldReturnAll3Components() throws Exception {
- KeyRing.UserId info = KeyRing.splitUserId("Max Mustermann (this is a comment) <max@example.com>");
- Assert.assertEquals("Max Mustermann", info.name);
- Assert.assertEquals("this is a comment", info.comment);
- Assert.assertEquals("max@example.com", info.email);
- }
-
- @Test
- public void splitUserIdWithAllButCommentShouldReturnNameAndEmail() throws Exception {
- KeyRing.UserId info = KeyRing.splitUserId("Max Mustermann <max@example.com>");
- Assert.assertEquals("Max Mustermann", info.name);
- Assert.assertNull(info.comment);
- Assert.assertEquals("max@example.com", info.email);
- }
-
- @Test
- public void splitUserIdWithAllButEmailShouldReturnNameAndComment() throws Exception {
- KeyRing.UserId info = KeyRing.splitUserId("Max Mustermann (this is a comment)");
- Assert.assertEquals(info.name, "Max Mustermann");
- Assert.assertEquals(info.comment, "this is a comment");
- Assert.assertNull(info.email);
- }
-
-} \ No newline at end of file
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
deleted file mode 100644
index c7ed9fb30..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * 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.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.openintents.openpgp.OpenPgpMetadata;
-import org.openintents.openpgp.OpenPgpSignatureResult;
-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.operations.results.OperationResult.LogType;
-import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
-import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
-import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
-import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
-import org.sufficientlysecure.keychain.util.InputData;
-import org.sufficientlysecure.keychain.util.Passphrase;
-import org.sufficientlysecure.keychain.util.ProgressScaler;
-import org.sufficientlysecure.keychain.util.TestingUtils;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.security.Security;
-import java.util.HashSet;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class PgpEncryptDecryptTest {
-
- static Passphrase mPassphrase = TestingUtils.genPassphrase(true);
-
- static UncachedKeyRing mStaticRing1, mStaticRing2;
- static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
- static Passphrase mKeyPhrase2 = TestingUtils.genPassphrase(true);
-
- static PrintStream oldShadowStream;
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- Security.insertProviderAt(new BouncyCastleProvider(), 1);
- oldShadowStream = ShadowLog.stream;
- // 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.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
-
- PgpEditKeyResult 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.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase2);
-
- PgpEditKeyResult 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);
-
- // don't log verbosely here, we're not here to test imports
- ShadowLog.stream = oldShadowStream;
-
- providerHelper.saveSecretKeyRing(mStaticRing1, new ProgressScaler());
- providerHelper.saveSecretKeyRing(mStaticRing2, new ProgressScaler());
-
- // ok NOW log verbosely!
- ShadowLog.stream = System.out;
- }
-
- @Test
- public void testSymmetricEncryptDecrypt() {
-
- 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());
-
- PgpSignEncryptOperation op = new PgpSignEncryptOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
-
- InputData data = new InputData(in, in.available());
-
- PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel();
- b.setSymmetricPassphrase(mPassphrase);
- b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
-
- PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(), data, out);
-
- Assert.assertTrue("encryption must succeed", result.success());
-
- ciphertext = out.toByteArray();
- }
-
- { // decryption with same passphrase should yield the same result
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- PgpDecryptVerify op = new PgpDecryptVerify(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- input.setAllowSymmetricDecryption(true);
- DecryptVerifyResult result = op.execute(
- input, new CryptoInputParcel(mPassphrase), data, out);
-
- 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());
-
- OpenPgpMetadata metadata = result.getDecryptMetadata();
- Assert.assertEquals("filesize must be correct",
- out.toByteArray().length, metadata.getOriginalSize());
- }
-
- { // decryption with a bad passphrase should fail
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- PgpDecryptVerify op = new PgpDecryptVerify(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- input.setAllowSymmetricDecryption(true);
- DecryptVerifyResult result = op.execute(input,
- new CryptoInputParcel(new Passphrase(new String(mPassphrase.getCharArray()) + "x")),
- data, out);
-
- Assert.assertFalse("decryption must fail", 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 op = new PgpDecryptVerify(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- input.setAllowSymmetricDecryption(true);
- DecryptVerifyResult result = op.execute(input,
- new CryptoInputParcel(), data, out);
-
- Assert.assertFalse("decryption must fail", result.success());
- Assert.assertEquals("decrypted plaintext should be empty", 0, out.size());
- Assert.assertNull("signature should be an error", result.getSignatureResult());
- }
-
- { // decryption if symmetric decryption isn't allowed should fail
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- PgpDecryptVerify op = new PgpDecryptVerify(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- input.setAllowSymmetricDecryption(false);
- DecryptVerifyResult result = op.execute(input,
- new CryptoInputParcel(), data, out);
-
- Assert.assertFalse("decryption must fail", 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 key
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(plaintext.getBytes());
-
- PgpSignEncryptOperation op = new PgpSignEncryptOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
-
- InputData data = new InputData(in, in.available());
- PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
-
- input.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() });
- input.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
- PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(), data, out);
- 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 op = operationWithFakePassphraseCache(null, null, null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
-
- 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());
-
- OpenPgpMetadata metadata = result.getDecryptMetadata();
- Assert.assertEquals("filesize must be correct",
- out.toByteArray().length, metadata.getOriginalSize());
-
- }
-
- { // decryption with passphrase cached should succeed
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- PgpDecryptVerify op = operationWithFakePassphraseCache(
- mKeyPhrase1, mStaticRing1.getMasterKeyId(), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
-
- 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 op = operationWithFakePassphraseCache(
- null, mStaticRing1.getMasterKeyId(), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
-
- 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",
- RequiredInputType.PASSPHRASE, result.getRequiredInputParcel().mType);
- }
-
- }
-
- @Test
- public void testMultiAsymmetricEncryptDecrypt() {
-
- 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());
-
- PgpSignEncryptOperation op = new PgpSignEncryptOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
-
- InputData data = new InputData(in, in.available());
-
- PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel();
- b.setEncryptionMasterKeyIds(new long[] {
- mStaticRing1.getMasterKeyId(),
- mStaticRing2.getMasterKeyId()
- });
- b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
-
- PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(), data, out);
- Assert.assertTrue("encryption must succeed", result.success());
-
- ciphertext = out.toByteArray();
- }
-
- { // decryption with passphrase cached should succeed for the first key
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- PgpDecryptVerify op = operationWithFakePassphraseCache(
- mKeyPhrase1, mStaticRing1.getMasterKeyId(), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
-
- Assert.assertTrue("decryption with cached passphrase must succeed for the first key", result.success());
- Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext",
- out.toByteArray(), plaintext.getBytes());
- Assert.assertNull("signature should be empty", result.getSignatureResult());
-
- OpenPgpMetadata metadata = result.getDecryptMetadata();
- Assert.assertEquals("filesize must be correct",
- out.toByteArray().length, metadata.getOriginalSize());
- }
-
- { // decryption should succeed if key is allowed
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- // allow only the second to decrypt
- HashSet<Long> allowed = new HashSet<>();
- allowed.add(mStaticRing2.getMasterKeyId());
-
- // provide passphrase for the second, and check that the first is never asked for!
- PgpDecryptVerify op = operationWithFakePassphraseCache(
- mKeyPhrase2, mStaticRing2.getMasterKeyId(), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- input.setAllowedKeyIds(allowed);
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
-
- Assert.assertTrue("decryption with cached passphrase must succeed for allowed key", result.success());
- Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext",
- out.toByteArray(), plaintext.getBytes());
- Assert.assertTrue("other key was skipped", result.getLog().containsType(LogType.MSG_DC_ASKIP_NOT_ALLOWED));
- Assert.assertNull("signature should be empty", result.getSignatureResult());
- }
-
- { // decryption should fail if no key is allowed
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- // provide passphrase for the second, and check that the first is never asked for!
- PgpDecryptVerify op = operationWithFakePassphraseCache(
- mKeyPhrase2, mStaticRing2.getMasterKeyId(), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- input.setAllowedKeyIds(new HashSet<Long>());
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
-
- Assert.assertFalse("decryption must fail if no key allowed", result.success());
- Assert.assertEquals("decryption must fail with key disllowed status",
- DecryptVerifyResult.RESULT_KEY_DISALLOWED, result.getResult());
-
- }
-
- { // decryption with passphrase cached should succeed for the other key if first is gone
-
- // delete first key from database
- new ProviderHelper(Robolectric.application).getContentResolver().delete(
- KeyRingData.buildPublicKeyRingUri(mStaticRing1.getMasterKeyId()), null, null
- );
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- PgpDecryptVerify op = operationWithFakePassphraseCache(
- mKeyPhrase2, mStaticRing2.getMasterKeyId(), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
-
- 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());
- }
-
- }
-
- @Test
- public void testMultiAsymmetricSignEncryptDecryptVerify() {
-
- 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());
-
- PgpSignEncryptOperation op = new PgpSignEncryptOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
-
- InputData data = new InputData(in, in.available());
- PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel();
-
- b.setEncryptionMasterKeyIds(new long[] {
- mStaticRing1.getMasterKeyId(),
- mStaticRing2.getMasterKeyId()
- });
- b.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId());
- b.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1));
- b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
-
- PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(mKeyPhrase1), data, out);
- Assert.assertTrue("encryption must succeed", result.success());
-
- ciphertext = out.toByteArray();
- }
-
- { // decryption with passphrase cached should succeed for the first key
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- PgpDecryptVerify op = operationWithFakePassphraseCache(
- mKeyPhrase1, mStaticRing1.getMasterKeyId(), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
-
- Assert.assertTrue("decryption with cached passphrase must succeed for the first key", result.success());
- Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext",
- out.toByteArray(), plaintext.getBytes());
- Assert.assertEquals("signature should be verified and certified",
- OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED, result.getSignatureResult().getStatus());
-
- OpenPgpMetadata metadata = result.getDecryptMetadata();
- Assert.assertEquals("filesize must be correct",
- out.toByteArray().length, metadata.getOriginalSize());
- }
-
- { // decryption with passphrase cached should succeed for the other key if first is gone
-
- // delete first key from database
- new ProviderHelper(Robolectric.application).getContentResolver().delete(
- KeyRingData.buildPublicKeyRingUri(mStaticRing1.getMasterKeyId()), null, null
- );
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
- InputData data = new InputData(in, in.available());
-
- PgpDecryptVerify op = operationWithFakePassphraseCache(
- mKeyPhrase2, mStaticRing2.getMasterKeyId(), null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
-
- 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.assertEquals("signature key should be missing",
- OpenPgpSignatureResult.SIGNATURE_KEY_MISSING,
- result.getSignatureResult().getStatus());
- }
-
- }
-
- @Test
- public void testForeignEncoding() throws Exception {
- String plaintext = "ウィキペディア";
- byte[] plaindata = plaintext.getBytes("iso-2022-jp");
-
- { // some quick sanity checks
- Assert.assertEquals(plaintext, new String(plaindata, "iso-2022-jp"));
- Assert.assertNotEquals(plaintext, new String(plaindata, "utf-8"));
- }
-
- byte[] ciphertext;
- { // encrypt data with a given passphrase
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayInputStream in = new ByteArrayInputStream(plaindata);
-
- PgpSignEncryptOperation op = new PgpSignEncryptOperation(Robolectric.application,
- new ProviderHelper(Robolectric.application), null);
-
- InputData data = new InputData(in, in.available());
- PgpSignEncryptInputParcel b = new PgpSignEncryptInputParcel();
-
- b.setEncryptionMasterKeyIds(new long[] { mStaticRing1.getMasterKeyId() });
- b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
- // this only works with ascii armored output!
- b.setEnableAsciiArmorOutput(true);
- b.setCharset("iso-2022-jp");
- PgpSignEncryptResult result = op.execute(b, new CryptoInputParcel(), data, out);
- 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 op = operationWithFakePassphraseCache(null, null, null);
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
- DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
-
- Assert.assertTrue("decryption with provided passphrase must succeed", result.success());
- Assert.assertArrayEquals("decrypted ciphertext should equal plaintext bytes",
- out.toByteArray(), plaindata);
- Assert.assertEquals("charset should be read correctly",
- "iso-2022-jp", result.getCharset());
- Assert.assertEquals("decrypted ciphertext should equal plaintext",
- new String(out.toByteArray(), result.getCharset()), plaintext);
- Assert.assertNull("signature be empty", result.getSignatureResult());
- }
-
- }
-
- private PgpDecryptVerify operationWithFakePassphraseCache(
- final Passphrase passphrase, final Long checkMasterKeyId, final Long checkSubKeyId) {
-
- return new PgpDecryptVerify(Robolectric.application,
- new ProviderHelper(Robolectric.application), null) {
- @Override
- public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId)
- throws NoSecretKeyException {
- if (checkMasterKeyId != null) {
- Assert.assertEquals("requested passphrase should be for expected master key id",
- (long) checkMasterKeyId, masterKeyId);
- }
- if (checkSubKeyId != null) {
- Assert.assertEquals("requested passphrase should be for expected sub key id",
- (long) checkSubKeyId, subKeyId);
- }
- if (passphrase == null) {
- return null;
- }
- return passphrase;
- }
- };
- }
-} \ No newline at end of file
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java
deleted file mode 100644
index e74b84dfb..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java
+++ /dev/null
@@ -1,1376 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * 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 junit.framework.AssertionFailedError;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.runner.RunWith;
-import org.robolectric.*;
-import org.robolectric.shadows.ShadowLog;
-import org.spongycastle.bcpg.BCPGInputStream;
-import org.spongycastle.bcpg.Packet;
-import org.spongycastle.bcpg.PacketTags;
-import org.spongycastle.bcpg.S2K;
-import org.spongycastle.bcpg.SecretKeyPacket;
-import org.spongycastle.bcpg.SecretSubkeyPacket;
-import org.spongycastle.bcpg.SignaturePacket;
-import org.spongycastle.bcpg.UserAttributePacket;
-import org.spongycastle.bcpg.UserAttributeSubpacket;
-import org.spongycastle.bcpg.UserIDPacket;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.spongycastle.openpgp.PGPSignature;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
-import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
-import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
-import org.sufficientlysecure.keychain.support.KeyringBuilder;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
-import org.sufficientlysecure.keychain.support.TestDataUtil;
-import org.sufficientlysecure.keychain.util.Passphrase;
-import org.sufficientlysecure.keychain.util.ProgressScaler;
-import org.sufficientlysecure.keychain.util.TestingUtils;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.security.Security;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class PgpKeyOperationTest {
-
- static UncachedKeyRing staticRing;
- final static Passphrase passphrase = TestingUtils.genPassphrase();
-
- UncachedKeyRing ring;
- PgpKeyOperation op;
- SaveKeyringParcel parcel;
- ArrayList<RawPacket> onlyA = new ArrayList<RawPacket>();
- ArrayList<RawPacket> onlyB = new ArrayList<RawPacket>();
-
- static CryptoInputParcel cryptoInput;
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- Security.insertProviderAt(new BouncyCastleProvider(), 1);
- ShadowLog.stream = System.out;
-
- 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.RSA, 2048, null, KeyFlags.ENCRYPT_COMMS, 0L));
-
- parcel.mAddUserIds.add("twi");
- parcel.mAddUserIds.add("pink");
-
- {
- int type = 42;
- byte[] data = new byte[] { 0, 1, 2, 3, 4 };
- WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data);
- parcel.mAddUserAttribute.add(uat);
- }
-
- parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
- PgpKeyOperation op = new PgpKeyOperation(null);
-
- PgpEditKeyResult result = op.createSecretKeyRing(parcel);
- Assert.assertTrue("initial test key creation must succeed", result.success());
- Assert.assertNotNull("initial test key creation must succeed", result.getRing());
-
- staticRing = result.getRing();
- staticRing = staticRing.canonicalize(new OperationLog(), 0).getUncachedKeyRing();
-
- // we sleep here for a second, to make sure all new certificates have different timestamps
- Thread.sleep(1000);
-
- cryptoInput = new CryptoInputParcel(new Date(), passphrase);
-
- }
-
- @Before public void setUp() throws Exception {
- // show Log.x messages in system.out
- ShadowLog.stream = System.out;
- ring = staticRing;
-
- // setting up some parameters just to reduce code duplication
- op = new PgpKeyOperation(new ProgressScaler(null, 0, 100, 100));
-
- // set this up, gonna need it more than once
- parcel = new SaveKeyringParcel();
- parcel.mMasterKeyId = ring.getMasterKeyId();
- parcel.mFingerprint = ring.getFingerprint();
-
- }
-
- @Test
- public void createSecretKeyRingTests() {
-
- {
- parcel.reset();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, new Random().nextInt(256)+255, null, KeyFlags.CERTIFY_OTHER, 0L));
- parcel.mAddUserIds.add("shy");
- parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
-
- assertFailure("creating ring with < 512 bytes keysize should fail", parcel,
- LogType.MSG_CR_ERROR_KEYSIZE_512);
- }
-
- {
- parcel.reset();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.ELGAMAL, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
- parcel.mAddUserIds.add("shy");
- parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
-
- assertFailure("creating ring with ElGamal master key should fail", parcel,
- LogType.MSG_CR_ERROR_FLAGS_ELGAMAL);
- }
-
- {
- parcel.reset();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, null));
- parcel.mAddUserIds.add("lotus");
- parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
-
- assertFailure("creating master key with null expiry should fail", parcel,
- LogType.MSG_CR_ERROR_NULL_EXPIRY);
- }
-
- {
- parcel.reset();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
- parcel.mAddUserIds.add("shy");
- parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
-
- assertFailure("creating ring with non-certifying master key should fail", parcel,
- LogType.MSG_CR_ERROR_NO_CERTIFY);
- }
-
- {
- parcel.reset();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
- parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
-
- assertFailure("creating ring without user ids should fail", parcel,
- LogType.MSG_CR_ERROR_NO_USER_ID);
- }
-
- {
- parcel.reset();
- parcel.mAddUserIds.add("shy");
- parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
-
- assertFailure("creating ring with no master key should fail", parcel,
- LogType.MSG_CR_ERROR_NO_MASTER);
- }
-
- }
-
- @Test
- // this is a special case since the flags are in user id certificates rather than
- // subkey binding certificates
- public void testMasterFlags() throws Exception {
- SaveKeyringParcel parcel = new SaveKeyringParcel();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, 0L));
- parcel.mAddUserIds.add("luna");
- ring = assertCreateSuccess("creating ring with master key flags must succeed", parcel);
-
- Assert.assertEquals("the keyring should contain only the master key",
- 1, KeyringTestingHelper.itToList(ring.getPublicKeys()).size());
- Assert.assertEquals("first (master) key must have both flags",
- KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, (long) ring.getPublicKey().getKeyUsage());
-
- }
-
- @Test
- public void testCreatedKey() throws Exception {
-
- // an empty modification should change nothing. this also ensures the keyring
- // is constant through canonicalization.
- // applyModificationWithChecks(parcel, ring, onlyA, onlyB);
-
- Assert.assertNotNull("key creation failed", ring);
-
- Assert.assertNull("primary user id must be empty",
- ring.getPublicKey().getPrimaryUserId());
-
- Assert.assertEquals("number of user ids must be two",
- 2, ring.getPublicKey().getUnorderedUserIds().size());
-
- ArrayList<WrappedUserAttribute> attributes =
- ring.getPublicKey().getUnorderedUserAttributes();
- Assert.assertEquals("number of user attributes must be one",
- 1, attributes.size());
- Assert.assertEquals("user attribute must be correct type",
- 42, attributes.get(0).getType());
- Assert.assertEquals("user attribute must have one subpacket",
- 1, attributes.get(0).getSubpackets().length);
- Assert.assertArrayEquals("user attribute must have correct data",
- new byte[] { 0, 1, 2, 3, 4 }, attributes.get(0).getSubpackets()[0]);
-
- List<UncachedPublicKey> subkeys = KeyringTestingHelper.itToList(ring.getPublicKeys());
- Assert.assertEquals("number of subkeys must be three", 3, subkeys.size());
-
- Assert.assertTrue("key ring should have been created in the last 120 seconds",
- ring.getPublicKey().getCreationTime().after(new Date(new Date().getTime()-1000*120)));
-
- Assert.assertNull("key ring should not expire",
- ring.getPublicKey().getUnsafeExpiryTimeForTesting());
-
- Assert.assertEquals("first (master) key can certify",
- KeyFlags.CERTIFY_OTHER, (long) subkeys.get(0).getKeyUsage());
-
- Assert.assertEquals("second key can sign",
- KeyFlags.SIGN_DATA, (long) subkeys.get(1).getKeyUsage());
- ArrayList<WrappedSignature> sigs = subkeys.get(1).getSignatures().next().getEmbeddedSignatures();
- Assert.assertEquals("signing key signature should have one embedded signature",
- 1, sigs.size());
- Assert.assertEquals("embedded signature should be of primary key binding type",
- PGPSignature.PRIMARYKEY_BINDING, sigs.get(0).getSignatureType());
- Assert.assertEquals("primary key binding signature issuer should be signing subkey",
- subkeys.get(1).getKeyId(), sigs.get(0).getKeyId());
-
- Assert.assertEquals("third key can encrypt",
- KeyFlags.ENCRYPT_COMMS, (long) subkeys.get(2).getKeyUsage());
-
- }
-
- @Test
- public void testBadKeyModification() throws Exception {
-
- {
- SaveKeyringParcel parcel = new SaveKeyringParcel();
- // off by one
- parcel.mMasterKeyId = ring.getMasterKeyId() -1;
- parcel.mFingerprint = ring.getFingerprint();
-
- assertModifyFailure("keyring modification with bad master key id should fail",
- ring, parcel, LogType.MSG_MF_ERROR_KEYID);
- }
-
- {
- SaveKeyringParcel parcel = new SaveKeyringParcel();
- // off by one
- parcel.mMasterKeyId = null;
- parcel.mFingerprint = ring.getFingerprint();
-
- assertModifyFailure("keyring modification with null master key id should fail",
- ring, parcel, LogType.MSG_MF_ERROR_KEYID);
- }
-
- {
- SaveKeyringParcel parcel = new SaveKeyringParcel();
- parcel.mMasterKeyId = ring.getMasterKeyId();
- parcel.mFingerprint = ring.getFingerprint();
- // some byte, off by one
- parcel.mFingerprint[5] += 1;
-
- assertModifyFailure("keyring modification with bad fingerprint should fail",
- ring, parcel, LogType.MSG_MF_ERROR_FINGERPRINT);
- }
-
- {
- SaveKeyringParcel parcel = new SaveKeyringParcel();
- parcel.mMasterKeyId = ring.getMasterKeyId();
- parcel.mFingerprint = null;
-
- assertModifyFailure("keyring modification with null fingerprint should fail",
- ring, parcel, LogType.MSG_MF_ERROR_FINGERPRINT);
- }
-
- {
- Passphrase badphrase = new Passphrase();
- if (badphrase.equals(passphrase)) {
- badphrase = new Passphrase("a");
- }
- parcel.mAddUserIds.add("allure");
-
- assertModifyFailure("keyring modification with bad passphrase should fail",
- ring, parcel, new CryptoInputParcel(badphrase), LogType.MSG_MF_UNLOCK_ERROR);
- }
-
- {
- parcel.reset();
- assertModifyFailure("no-op should fail",
- ring, parcel, cryptoInput, LogType.MSG_MF_ERROR_NOOP);
- }
-
- }
-
- @Test
- public void testSubkeyAdd() throws Exception {
-
- long expiry = new Date().getTime() / 1000 + 159;
- int flags = KeyFlags.SIGN_DATA;
- int bits = 1024 + new Random().nextInt(8);
- parcel.mAddSubKeys.add(new SubkeyAdd(Algorithm.RSA, bits, null, flags, expiry));
-
- UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB);
-
- Assert.assertEquals("no extra packets in original", 0, onlyA.size());
- Assert.assertEquals("exactly two extra packets in modified", 2, onlyB.size());
-
- Packet p;
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("first new packet must be secret subkey", p instanceof SecretSubkeyPacket);
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(1).buf)).readPacket();
- Assert.assertTrue("second new packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("signature type must be subkey binding certificate",
- PGPSignature.SUBKEY_BINDING, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- // get new key from ring. it should be the last one (add a check to make sure?)
- UncachedPublicKey newKey = null;
- {
- Iterator<UncachedPublicKey> it = modified.getPublicKeys();
- while (it.hasNext()) {
- newKey = it.next();
- }
- }
-
- Assert.assertNotNull("new key is not null", newKey);
- Assert.assertNotNull("added key must have an expiry date",
- newKey.getUnsafeExpiryTimeForTesting());
- Assert.assertEquals("added key must have expected expiry date",
- expiry, newKey.getUnsafeExpiryTimeForTesting().getTime()/1000);
- Assert.assertEquals("added key must have expected flags",
- flags, (long) newKey.getKeyUsage());
- Assert.assertEquals("added key must have expected bitsize",
- bits, (int) newKey.getBitStrength());
-
- { // bad keysize should fail
- parcel.reset();
- parcel.mAddSubKeys.add(new SubkeyAdd(
- Algorithm.RSA, new Random().nextInt(512), null, KeyFlags.SIGN_DATA, 0L));
- assertModifyFailure("creating a subkey with keysize < 512 should fail", ring, parcel,
- LogType.MSG_CR_ERROR_KEYSIZE_512);
-
- }
-
- {
- parcel.reset();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, null));
-
- assertModifyFailure("creating master key with null expiry should fail", ring, parcel,
- LogType.MSG_MF_ERROR_NULL_EXPIRY);
- }
-
- { // a past expiry should fail
- parcel.reset();
- parcel.mAddSubKeys.add(new SubkeyAdd(Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA,
- new Date().getTime()/1000-10));
- assertModifyFailure("creating subkey with past expiry date should fail", ring, parcel,
- LogType.MSG_MF_ERROR_PAST_EXPIRY);
- }
-
- }
-
- @Test
- public void testSubkeyModify() throws Exception {
-
- long expiry = new Date().getTime()/1000 + 1024;
- long keyId = KeyringTestingHelper.getSubkeyId(ring, 1);
-
- UncachedKeyRing modified = ring;
- {
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, expiry));
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertEquals("one extra packet in original", 1, onlyA.size());
- Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
-
- Assert.assertEquals("old packet must be signature",
- PacketTags.SIGNATURE, onlyA.get(0).tag);
-
- Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("first new packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("signature type must be subkey binding certificate",
- PGPSignature.SUBKEY_BINDING, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- Assert.assertNotNull("modified key must have an expiry date",
- modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
- Assert.assertEquals("modified key must have expected expiry date",
- expiry, modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting().getTime()/1000);
- Assert.assertEquals("modified key must have same flags as before",
- ring.getPublicKey(keyId).getKeyUsage(), modified.getPublicKey(keyId).getKeyUsage());
- }
-
- { // change expiry
- expiry += 60*60*24;
-
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, expiry));
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertNotNull("modified key must have an expiry date",
- modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
- Assert.assertEquals("modified key must have expected expiry date",
- expiry, modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting().getTime()/1000);
- Assert.assertEquals("modified key must have same flags as before",
- ring.getPublicKey(keyId).getKeyUsage(), modified.getPublicKey(keyId).getKeyUsage());
- }
-
- {
- int flags = KeyFlags.SIGN_DATA | KeyFlags.ENCRYPT_COMMS;
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, flags, null));
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertEquals("old packet must be signature",
- PacketTags.SIGNATURE, onlyA.get(0).tag);
-
- Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("first new packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("signature type must be subkey binding certificate",
- PGPSignature.SUBKEY_BINDING, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- Assert.assertEquals("modified key must have expected flags",
- flags, (long) modified.getPublicKey(keyId).getKeyUsage());
- Assert.assertNotNull("key must retain its expiry",
- modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
- Assert.assertEquals("key expiry must be unchanged",
- expiry, modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting().getTime()/1000);
- }
-
- { // expiry of 0 should be "no expiry"
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, 0L));
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertEquals("old packet must be signature",
- PacketTags.SIGNATURE, onlyA.get(0).tag);
-
- Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("first new packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("signature type must be subkey binding certificate",
- PGPSignature.SUBKEY_BINDING, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- Assert.assertNull("key must not expire anymore", modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
- }
-
- { // a past expiry should fail
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, new Date().getTime()/1000-10));
-
- assertModifyFailure("setting subkey expiry to a past date should fail", ring, parcel,
- LogType.MSG_MF_ERROR_PAST_EXPIRY);
- }
-
- { // modifying nonexistent subkey should fail
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(123, null, null));
-
- assertModifyFailure("modifying non-existent subkey should fail", ring, parcel,
- LogType.MSG_MF_ERROR_SUBKEY_MISSING);
- }
-
- }
-
- @Test
- public void testMasterModify() throws Exception {
-
- long expiry = new Date().getTime()/1000 + 1024;
- long keyId = ring.getMasterKeyId();
-
- UncachedKeyRing modified = ring;
-
- // to make this check less trivial, we add a user id, change the primary one and revoke one
- parcel.mAddUserIds.add("aloe");
- parcel.mChangePrimaryUserId = "aloe";
- parcel.mRevokeUserIds.add("pink");
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- {
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, expiry));
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- // this implies that only the two non-revoked signatures were changed!
- Assert.assertEquals("two extra packets in original", 2, onlyA.size());
- Assert.assertEquals("two extra packets in modified", 2, onlyB.size());
-
- Assert.assertEquals("first original packet must be a signature",
- PacketTags.SIGNATURE, onlyA.get(0).tag);
- Assert.assertEquals("second original packet must be a signature",
- PacketTags.SIGNATURE, onlyA.get(1).tag);
- Assert.assertEquals("first new packet must be signature",
- PacketTags.SIGNATURE, onlyB.get(0).tag);
- Assert.assertEquals("first new packet must be signature",
- PacketTags.SIGNATURE, onlyB.get(1).tag);
-
- Assert.assertNotNull("modified key must have an expiry date",
- modified.getPublicKey().getUnsafeExpiryTimeForTesting());
- Assert.assertEquals("modified key must have expected expiry date",
- expiry, modified.getPublicKey().getUnsafeExpiryTimeForTesting().getTime() / 1000);
- Assert.assertEquals("modified key must have same flags as before",
- ring.getPublicKey().getKeyUsage(), modified.getPublicKey().getKeyUsage());
- }
-
- { // change expiry
- expiry += 60*60*24;
-
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, expiry));
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertNotNull("modified key must have an expiry date",
- modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
- Assert.assertEquals("modified key must have expected expiry date",
- expiry, modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting().getTime() / 1000);
- Assert.assertEquals("modified key must have same flags as before",
- ring.getPublicKey(keyId).getKeyUsage(), modified.getPublicKey(keyId).getKeyUsage());
-
- Date date = modified.canonicalize(new OperationLog(), 0).getPublicKey().getExpiryTime();
- Assert.assertNotNull("modified key must have an expiry date", date);
- Assert.assertEquals("modified key must have expected expiry date",
- expiry, date.getTime() / 1000);
-
- }
-
- {
- int flags = KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA;
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, flags, null));
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertEquals("modified key must have expected flags",
- flags, (long) modified.getPublicKey(keyId).getKeyUsage());
- Assert.assertNotNull("key must retain its expiry",
- modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
- Assert.assertEquals("key expiry must be unchanged",
- expiry, modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting().getTime()/1000);
- }
-
- { // expiry of 0 should be "no expiry"
-
- // even if there is a non-expiring user id while all others are revoked, it doesn't count!
- // for this purpose we revoke one while they still have expiry times
- parcel.reset();
- parcel.mRevokeUserIds.add("aloe");
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, 0L));
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- // for this check, it is relevant that we DON'T use the unsafe one!
- Assert.assertNull("key must not expire anymore",
- modified.canonicalize(new OperationLog(), 0).getPublicKey().getExpiryTime());
- // make sure the unsafe one behaves incorrectly as expected
- Assert.assertNotNull("unsafe expiry must yield wrong result from revoked user id",
- modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
- }
-
- { // if we revoke everything, nothing is left to properly sign...
- parcel.reset();
- parcel.mRevokeUserIds.add("twi");
- parcel.mRevokeUserIds.add("pink");
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, KeyFlags.CERTIFY_OTHER, null));
-
- assertModifyFailure("master key modification with all user ids revoked should fail", ring, parcel,
- LogType.MSG_MF_ERROR_MASTER_NONE);
- }
-
- { // any flag not including CERTIFY_OTHER should fail
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, KeyFlags.SIGN_DATA, null));
-
- assertModifyFailure("setting master key flags without certify should fail", ring, parcel,
- LogType.MSG_MF_ERROR_NO_CERTIFY);
- }
-
- { // a past expiry should fail
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, new Date().getTime()/1000-10));
-
- assertModifyFailure("setting subkey expiry to a past date should fail", ring, parcel,
- LogType.MSG_MF_ERROR_PAST_EXPIRY);
- }
-
- }
-
- @Test
- public void testMasterRevoke() throws Exception {
-
- parcel.reset();
- parcel.mRevokeSubKeys.add(ring.getMasterKeyId());
-
- UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB);
-
- Assert.assertEquals("no extra packets in original", 0, onlyA.size());
- Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size());
-
- Packet p;
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("first new packet must be secret subkey", p instanceof SignaturePacket);
- Assert.assertEquals("signature type must be subkey binding certificate",
- PGPSignature.KEY_REVOCATION, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- Assert.assertTrue("subkey must actually be revoked",
- modified.getPublicKey().isMaybeRevoked());
-
- }
-
- @Test
- public void testSubkeyRevoke() throws Exception {
-
- long keyId = KeyringTestingHelper.getSubkeyId(ring, 1);
- int flags = ring.getPublicKey(keyId).getKeyUsage();
-
- UncachedKeyRing modified;
-
- {
-
- parcel.reset();
- parcel.mRevokeSubKeys.add(123L);
-
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), false, 0);
- UncachedKeyRing otherModified = op.modifySecretKeyRing(secretRing, cryptoInput, parcel).getRing();
-
- Assert.assertNull("revoking a nonexistent subkey should fail", otherModified);
-
- }
-
- { // revoked second subkey
-
- parcel.reset();
- parcel.mRevokeSubKeys.add(keyId);
-
- modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB,
- new CryptoInputParcel(new Date(), passphrase));
-
- Assert.assertEquals("no extra packets in original", 0, onlyA.size());
- Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size());
-
- Packet p;
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("first new packet must be secret subkey", p instanceof SignaturePacket);
- Assert.assertEquals("signature type must be subkey binding certificate",
- PGPSignature.SUBKEY_REVOCATION, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- Assert.assertTrue("subkey must actually be revoked",
- modified.getPublicKey(keyId).isMaybeRevoked());
- }
-
- { // re-add second subkey
-
- parcel.reset();
- // re-certify the revoked subkey
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true));
-
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertEquals("exactly two outdated packets in original", 2, onlyA.size());
- Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size());
-
- Packet p;
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(0).buf)).readPacket();
- Assert.assertTrue("first outdated packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("first outdated signature type must be subkey binding certification",
- PGPSignature.SUBKEY_BINDING, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("first outdated signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(1).buf)).readPacket();
- Assert.assertTrue("second outdated packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("second outdated signature type must be subkey revocation",
- PGPSignature.SUBKEY_REVOCATION, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("second outdated signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("new packet must be signature ", p instanceof SignaturePacket);
- Assert.assertEquals("new signature type must be subkey binding certification",
- PGPSignature.SUBKEY_BINDING, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- Assert.assertFalse("subkey must no longer be revoked",
- modified.getPublicKey(keyId).isMaybeRevoked());
- Assert.assertEquals("subkey must have the same usage flags as before",
- flags, (long) modified.getPublicKey(keyId).getKeyUsage());
-
- }
- }
-
- @Test
- public void testSubkeyStrip() throws Exception {
-
- long keyId = KeyringTestingHelper.getSubkeyId(ring, 1);
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false));
- applyModificationWithChecks(parcel, ring, onlyA, onlyB);
-
- Assert.assertEquals("one extra packet in original", 1, onlyA.size());
- Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
-
- Assert.assertEquals("old packet must be secret subkey",
- PacketTags.SECRET_SUBKEY, onlyA.get(0).tag);
- Assert.assertEquals("new packet must be secret subkey",
- PacketTags.SECRET_SUBKEY, onlyB.get(0).tag);
-
- Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertEquals("new packet should have GNU_DUMMY S2K type",
- S2K.GNU_DUMMY_S2K, ((SecretSubkeyPacket) p).getS2K().getType());
- Assert.assertEquals("new packet should have GNU_DUMMY protection mode 0x1",
- 0x1, ((SecretSubkeyPacket) p).getS2K().getProtectionMode());
- Assert.assertEquals("new packet secret key data should have length zero",
- 0, ((SecretSubkeyPacket) p).getSecretKeyData().length);
- Assert.assertNull("new packet should have no iv data", ((SecretSubkeyPacket) p).getIV());
-
- }
-
- @Test
- public void testMasterStrip() throws Exception {
-
- long keyId = ring.getMasterKeyId();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false));
- applyModificationWithChecks(parcel, ring, onlyA, onlyB);
-
- Assert.assertEquals("one extra packet in original", 1, onlyA.size());
- Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
-
- Assert.assertEquals("old packet must be secret key",
- PacketTags.SECRET_KEY, onlyA.get(0).tag);
- Assert.assertEquals("new packet must be secret key",
- PacketTags.SECRET_KEY, onlyB.get(0).tag);
-
- Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertEquals("new packet should have GNU_DUMMY S2K type",
- S2K.GNU_DUMMY_S2K, ((SecretKeyPacket) p).getS2K().getType());
- Assert.assertEquals("new packet should have GNU_DUMMY protection mode 0x1",
- 0x1, ((SecretKeyPacket) p).getS2K().getProtectionMode());
- Assert.assertEquals("new packet secret key data should have length zero",
- 0, ((SecretKeyPacket) p).getSecretKeyData().length);
- Assert.assertNull("new packet should have no iv data", ((SecretKeyPacket) p).getIV());
- }
-
- @Test
- public void testRestrictedStrip() throws Exception {
-
- long keyId = KeyringTestingHelper.getSubkeyId(ring, 1);
- UncachedKeyRing modified;
-
- { // we should be able to change the stripped status of subkeys without passphrase
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false));
- modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, new CryptoInputParcel());
- Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
- Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertEquals("new packet should have GNU_DUMMY S2K type",
- S2K.GNU_DUMMY_S2K, ((SecretKeyPacket) p).getS2K().getType());
- Assert.assertEquals("new packet should have GNU_DUMMY protection mode stripped",
- S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY, ((SecretKeyPacket) p).getS2K().getProtectionMode());
- }
- }
-
- @Test
- public void testKeyToCard() throws Exception {
-
- UncachedKeyRing modified;
-
- { // keytocard should fail with BAD_NFC_SIZE when presented with the RSA-1024 key
- long keyId = KeyringTestingHelper.getSubkeyId(ring, 0);
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, false, true));
-
- assertModifyFailure("keytocard operation should fail on invalid key size", ring,
- parcel, cryptoInput, LogType.MSG_MF_ERROR_BAD_NFC_SIZE);
- }
-
- { // keytocard should fail with BAD_NFC_ALGO when presented with the DSA-1024 key
- long keyId = KeyringTestingHelper.getSubkeyId(ring, 1);
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, false, true));
-
- assertModifyFailure("keytocard operation should fail on invalid key algorithm", ring,
- parcel, cryptoInput, LogType.MSG_MF_ERROR_BAD_NFC_ALGO);
- }
-
- { // keytocard should return a pending NFC_KEYTOCARD result when presented with the RSA-2048
- // key, and then make key divert-to-card when it gets a serial in the cryptoInputParcel.
- long keyId = KeyringTestingHelper.getSubkeyId(ring, 2);
- parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, false, true));
-
- CanonicalizedSecretKeyRing secretRing =
- new CanonicalizedSecretKeyRing(ring.getEncoded(), false, 0);
- PgpKeyOperation op = new PgpKeyOperation(null);
- PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, parcel);
- Assert.assertTrue("keytocard operation should be pending", result.isPending());
- Assert.assertEquals("required input should be RequiredInputType.NFC_KEYTOCARD",
- result.getRequiredInputParcel().mType, RequiredInputType.NFC_KEYTOCARD);
-
- // Create a cryptoInputParcel that matches what the NFCOperationActivity would return.
- byte[] keyIdBytes = new byte[8];
- ByteBuffer buf = ByteBuffer.wrap(keyIdBytes);
- buf.putLong(keyId).rewind();
- byte[] serial = new byte[] {
- 0x6a, 0x6f, 0x6c, 0x6f, 0x73, 0x77, 0x61, 0x67,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- };
- CryptoInputParcel inputParcel = new CryptoInputParcel();
- inputParcel.addCryptoData(keyIdBytes, serial);
-
- modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, inputParcel);
- Assert.assertEquals("one extra packet in modified", 1, onlyB.size());
- Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertEquals("new packet should have GNU_DUMMY S2K type",
- S2K.GNU_DUMMY_S2K, ((SecretKeyPacket) p).getS2K().getType());
- Assert.assertEquals("new packet should have GNU_DUMMY protection mode divert-to-card",
- S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD, ((SecretKeyPacket) p).getS2K().getProtectionMode());
- Assert.assertArrayEquals("new packet should have correct serial number as iv",
- serial, ((SecretKeyPacket) p).getIV());
-
- }
-
- }
-
- @Test
- public void testUserIdRevoke() throws Exception {
-
- UncachedKeyRing modified;
- String uid = ring.getPublicKey().getUnorderedUserIds().get(1);
-
- { // revoke second user id
-
- parcel.mRevokeUserIds.add(uid);
-
- modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB);
-
- Assert.assertEquals("no extra packets in original", 0, onlyA.size());
- Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size());
-
- Packet p;
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("first new packet must be secret subkey", p instanceof SignaturePacket);
- Assert.assertEquals("signature type must be subkey binding certificate",
- PGPSignature.CERTIFICATION_REVOCATION, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- }
-
- { // re-add second user id
-
- parcel.reset();
- parcel.mChangePrimaryUserId = uid;
-
- assertModifyFailure("setting primary user id to a revoked user id should fail", modified, parcel,
- LogType.MSG_MF_ERROR_REVOKED_PRIMARY);
-
- }
-
- { // re-add second user id
-
- parcel.reset();
- parcel.mAddUserIds.add(uid);
-
- applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertEquals("exactly two outdated packets in original", 2, onlyA.size());
- Assert.assertEquals("exactly one extra packet in modified", 1, onlyB.size());
-
- Packet p;
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(0).buf)).readPacket();
- Assert.assertTrue("first outdated packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("first outdated signature type must be positive certification",
- PGPSignature.POSITIVE_CERTIFICATION, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("first outdated signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(1).buf)).readPacket();
- Assert.assertTrue("second outdated packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("second outdated signature type must be certificate revocation",
- PGPSignature.CERTIFICATION_REVOCATION, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("second outdated signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("new packet must be signature ", p instanceof SignaturePacket);
- Assert.assertEquals("new signature type must be positive certification",
- PGPSignature.POSITIVE_CERTIFICATION, ((SignaturePacket) p).getSignatureType());
- Assert.assertEquals("signature must have been created by master key",
- ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
- }
-
- { // revocation of non-existent user id should fail
- parcel.reset();
- parcel.mRevokeUserIds.add("nonexistent");
-
- assertModifyFailure("revocation of nonexistent user id should fail", modified, parcel,
- LogType.MSG_MF_ERROR_NOEXIST_REVOKE);
- }
-
- }
-
- @Test
- public void testUserIdAdd() throws Exception {
-
- {
- parcel.mAddUserIds.add("");
- assertModifyFailure("adding an empty user id should fail", ring, parcel,
- LogType.MSG_MF_UID_ERROR_EMPTY);
- }
-
- parcel.reset();
- parcel.mAddUserIds.add("rainbow");
-
- UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB);
-
- Assert.assertTrue("keyring must contain added user id",
- modified.getPublicKey().getUnorderedUserIds().contains("rainbow"));
-
- Assert.assertEquals("no extra packets in original", 0, onlyA.size());
- Assert.assertEquals("exactly two extra packets in modified", 2, onlyB.size());
-
- Assert.assertTrue("keyring must contain added user id",
- modified.getPublicKey().getUnorderedUserIds().contains("rainbow"));
-
- Packet p;
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("first new packet must be user id", p instanceof UserIDPacket);
- Assert.assertEquals("user id packet must match added user id",
- "rainbow", ((UserIDPacket) p).getID());
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(1).buf)).readPacket();
- Assert.assertTrue("second new packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("signature type must be positive certification",
- PGPSignature.POSITIVE_CERTIFICATION, ((SignaturePacket) p).getSignatureType());
-
- }
-
- @Test
- public void testUserAttributeAdd() throws Exception {
-
- {
- parcel.mAddUserAttribute.add(WrappedUserAttribute.fromData(new byte[0]));
- assertModifyFailure("adding an empty user attribute should fail", ring, parcel,
- LogType.MSG_MF_UAT_ERROR_EMPTY);
- }
-
- parcel.reset();
-
- Random r = new Random();
- int type = r.nextInt(110)+2; // any type except image attribute, to avoid interpretation of these
- byte[] data = new byte[r.nextInt(2000)];
- new Random().nextBytes(data);
-
- WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data);
- parcel.mAddUserAttribute.add(uat);
-
- UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB);
-
- Assert.assertEquals("no extra packets in original", 0, onlyA.size());
- Assert.assertEquals("exactly two extra packets in modified", 2, onlyB.size());
-
- Assert.assertTrue("keyring must contain added user attribute",
- modified.getPublicKey().getUnorderedUserAttributes().contains(uat));
-
- Packet p;
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("first new packet must be user attribute", p instanceof UserAttributePacket);
- {
- UserAttributeSubpacket[] subpackets = ((UserAttributePacket) p).getSubpackets();
- Assert.assertEquals("user attribute packet must contain one subpacket",
- 1, subpackets.length);
- Assert.assertEquals("user attribute subpacket type must be as specified above",
- type, subpackets[0].getType());
- Assert.assertArrayEquals("user attribute subpacket data must be as specified above",
- data, subpackets[0].getData());
- }
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(1).buf)).readPacket();
- Assert.assertTrue("second new packet must be signature", p instanceof SignaturePacket);
- Assert.assertEquals("signature type must be positive certification",
- PGPSignature.POSITIVE_CERTIFICATION, ((SignaturePacket) p).getSignatureType());
-
- Thread.sleep(1000);
-
- // applying the same modification AGAIN should not add more certifications but drop those
- // as duplicates
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB,
- new CryptoInputParcel(new Date(), passphrase), true, false);
-
- Assert.assertEquals("duplicate modification: one extra packet in original", 1, onlyA.size());
- Assert.assertEquals("duplicate modification: one extra packet in modified", 1, onlyB.size());
-
- p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(0).buf)).readPacket();
- Assert.assertTrue("lost packet must be signature", p instanceof SignaturePacket);
- p = new BCPGInputStream(new ByteArrayInputStream(onlyB.get(0).buf)).readPacket();
- Assert.assertTrue("new packet must be signature", p instanceof SignaturePacket);
-
- }
-
-
- @Test
- public void testUserIdPrimary() throws Exception {
-
- UncachedKeyRing modified = ring;
- String uid = ring.getPublicKey().getUnorderedUserIds().get(1);
-
- { // first part, add new user id which is also primary
- parcel.mAddUserIds.add("jack");
- parcel.mChangePrimaryUserId = "jack";
-
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertEquals("primary user id must be the one added",
- "jack", modified.getPublicKey().getPrimaryUserId());
- }
-
- { // second part, change primary to a different one
- parcel.reset();
- parcel.mChangePrimaryUserId = uid;
-
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
-
- Assert.assertEquals("old keyring must have two outdated certificates", 2, onlyA.size());
- Assert.assertEquals("new keyring must have two new packets", 2, onlyB.size());
-
- Assert.assertEquals("primary user id must be the one changed to",
- "pink", modified.getPublicKey().getPrimaryUserId());
- }
-
- { // third part, change primary to a non-existent one
- parcel.reset();
- //noinspection SpellCheckingInspection
- parcel.mChangePrimaryUserId = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
- if (parcel.mChangePrimaryUserId.equals(passphrase)) {
- parcel.mChangePrimaryUserId += "A";
- }
-
- assertModifyFailure("changing primary user id to a non-existent one should fail",
- ring, parcel, LogType.MSG_MF_ERROR_NOEXIST_PRIMARY);
- }
-
- // check for revoked primary user id already done in revoke test
-
- }
-
- @Test
- public void testPassphraseChange() throws Exception {
-
- // change passphrase to empty
- parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
- // note that canonicalization here necessarily strips the empty notation packet
- UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, cryptoInput);
-
- Assert.assertEquals("exactly three packets should have been modified (the secret keys)",
- 3, onlyB.size());
-
- // remember secret key packet with no passphrase for later
- RawPacket sKeyNoPassphrase = onlyB.get(1);
- Assert.assertEquals("extracted packet should be a secret subkey",
- PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag);
-
- // modify keyring, change to non-empty passphrase
- Passphrase otherPassphrase = TestingUtils.genPassphrase(true);
- CryptoInputParcel otherCryptoInput = new CryptoInputParcel(otherPassphrase);
- parcel.mNewUnlock = new ChangeUnlockParcel(otherPassphrase);
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB,
- new CryptoInputParcel(new Date(), new Passphrase()));
-
- Assert.assertEquals("exactly three packets should have been modified (the secret keys)",
- 3, onlyB.size());
-
- { // quick check to make sure no two secret keys have the same IV
- HashSet<ByteBuffer> ivs = new HashSet<ByteBuffer>();
- for (int i = 0; i < 3; i++) {
- SecretKeyPacket p = (SecretKeyPacket) new BCPGInputStream(
- new ByteArrayInputStream(onlyB.get(i).buf)).readPacket();
- ByteBuffer iv = ByteBuffer.wrap(p.getIV());
- Assert.assertFalse(
- "no two secret keys should have the same s2k iv (slightly non-deterministic!)",
- ivs.contains(iv)
- );
- ivs.add(iv);
- }
- }
-
- RawPacket sKeyWithPassphrase = onlyB.get(1);
- Assert.assertEquals("extracted packet should be a secret subkey",
- PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag);
-
- Passphrase otherPassphrase2 = TestingUtils.genPassphrase(true);
- parcel.mNewUnlock = new ChangeUnlockParcel(otherPassphrase2);
- {
- // if we replace a secret key with one without passphrase
- modified = KeyringTestingHelper.removePacket(modified, sKeyNoPassphrase.position);
- modified = KeyringTestingHelper.injectPacket(modified, sKeyNoPassphrase.buf, sKeyNoPassphrase.position);
-
- // we should still be able to modify it (and change its passphrase) without errors
- PgpKeyOperation op = new PgpKeyOperation(null);
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), false, 0);
- PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, otherCryptoInput, parcel);
- Assert.assertTrue("key modification must succeed", result.success());
- Assert.assertFalse("log must not contain a warning",
- result.getLog().containsWarnings());
- Assert.assertTrue("log must contain an empty passphrase retry notice",
- result.getLog().containsType(LogType.MSG_MF_PASSPHRASE_EMPTY_RETRY));
- modified = result.getRing();
- }
-
- {
- // if we add one subkey with a different passphrase, that should produce a warning but also work
- modified = KeyringTestingHelper.removePacket(modified, sKeyWithPassphrase.position);
- modified = KeyringTestingHelper.injectPacket(modified, sKeyWithPassphrase.buf, sKeyWithPassphrase.position);
-
- PgpKeyOperation op = new PgpKeyOperation(null);
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), false, 0);
- PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(otherPassphrase2), parcel);
- Assert.assertTrue("key modification must succeed", result.success());
- Assert.assertTrue("log must contain a failed passphrase change warning",
- result.getLog().containsType(LogType.MSG_MF_PASSPHRASE_FAIL));
- }
-
- }
-
- @Test
- public void testUnlockPin() throws Exception {
-
- Passphrase pin = new Passphrase("5235125");
-
- // change passphrase to a pin type
- parcel.mNewUnlock = new ChangeUnlockParcel(null, pin);
- UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB);
-
- Assert.assertEquals("exactly three packets should have been added (the secret keys + notation packet)",
- 3, onlyA.size());
- Assert.assertEquals("exactly four packets should have been added (the secret keys + notation packet)",
- 4, onlyB.size());
-
- RawPacket dkSig = onlyB.get(1);
- Assert.assertEquals("second modified packet should be notation data",
- PacketTags.SIGNATURE, dkSig.tag);
-
- // check that notation data contains pin
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(
- modified.getEncoded(), false, 0);
- Assert.assertEquals("secret key type should be 'pin' after this",
- SecretKeyType.PIN,
- secretRing.getSecretKey().getSecretKeyType());
-
- // need to sleep for a sec, so the timestamp changes for notation data
- Thread.sleep(1000);
-
- {
- parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase("phrayse"), null);
- applyModificationWithChecks(parcel, modified, onlyA, onlyB, new CryptoInputParcel(pin), true, false);
-
- Assert.assertEquals("exactly four packets should have been removed (the secret keys + notation packet)",
- 4, onlyA.size());
- Assert.assertEquals("exactly three packets should have been added (no more notation packet)",
- 3, onlyB.size());
- }
-
- }
-
- @Test
- public void testRestricted () throws Exception {
-
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), false, 0);
-
- parcel.mAddUserIds.add("discord");
- PgpKeyOperation op = new PgpKeyOperation(null);
- PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Date()), parcel);
- Assert.assertFalse("non-restricted operations should fail without passphrase", result.success());
- }
-
- private static UncachedKeyRing applyModificationWithChecks(SaveKeyringParcel parcel,
- UncachedKeyRing ring,
- ArrayList<RawPacket> onlyA,
- ArrayList<RawPacket> onlyB) {
- return applyModificationWithChecks(parcel, ring, onlyA, onlyB, cryptoInput, true, true);
- }
-
- private static UncachedKeyRing applyModificationWithChecks(SaveKeyringParcel parcel,
- UncachedKeyRing ring,
- ArrayList<RawPacket> onlyA,
- ArrayList<RawPacket> onlyB,
- CryptoInputParcel cryptoInput) {
- return applyModificationWithChecks(parcel, ring, onlyA, onlyB, cryptoInput, true, true);
- }
-
- // applies a parcel modification while running some integrity checks
- private static UncachedKeyRing applyModificationWithChecks(SaveKeyringParcel parcel,
- UncachedKeyRing ring,
- ArrayList<RawPacket> onlyA,
- ArrayList<RawPacket> onlyB,
- CryptoInputParcel cryptoInput,
- boolean canonicalize,
- boolean constantCanonicalize) {
-
- try {
-
- Assert.assertTrue("modified keyring must be secret", ring.isSecret());
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), false, 0);
-
- PgpKeyOperation op = new PgpKeyOperation(null);
- PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, parcel);
- Assert.assertTrue("key modification must succeed", result.success());
- UncachedKeyRing rawModified = result.getRing();
- Assert.assertNotNull("key modification must not return null", rawModified);
-
- if (!canonicalize) {
- Assert.assertTrue("keyring must differ from original", KeyringTestingHelper.diffKeyrings(
- ring.getEncoded(), rawModified.getEncoded(), onlyA, onlyB));
- return rawModified;
- }
-
- CanonicalizedKeyRing modified = rawModified.canonicalize(new OperationLog(), 0);
- if (constantCanonicalize) {
- Assert.assertTrue("key must be constant through canonicalization",
- !KeyringTestingHelper.diffKeyrings(
- modified.getEncoded(), rawModified.getEncoded(), onlyA, onlyB)
- );
- }
- Assert.assertTrue("keyring must differ from original", KeyringTestingHelper.diffKeyrings(
- ring.getEncoded(), modified.getEncoded(), onlyA, onlyB));
-
- return modified.getUncachedKeyRing();
-
- } catch (IOException e) {
- throw new AssertionFailedError("error during encoding!");
- }
- }
-
- @Test
- public void testVerifySuccess() throws Exception {
-
- UncachedKeyRing expectedKeyRing = KeyringBuilder.correctRing();
- UncachedKeyRing inputKeyRing = KeyringBuilder.ringWithExtraIncorrectSignature();
-
- CanonicalizedKeyRing canonicalized = inputKeyRing.canonicalize(new OperationLog(), 0);
- Assert.assertNotNull("canonicalization must succeed", canonicalized);
-
- ArrayList onlyA = new ArrayList<RawPacket>();
- ArrayList onlyB = new ArrayList<RawPacket>();
- //noinspection unchecked
- Assert.assertTrue("keyrings differ", !KeyringTestingHelper.diffKeyrings(
- expectedKeyRing.getEncoded(), expectedKeyRing.getEncoded(), onlyA, onlyB));
-
- }
-
- /**
- * Just testing my own test code. Should really be using a library for this.
- */
- @Test
- public void testConcat() throws Exception {
- byte[] actual = TestDataUtil.concatAll(new byte[]{1}, new byte[]{2, -2}, new byte[]{5}, new byte[]{3});
- byte[] expected = new byte[]{1,2,-2,5,3};
- Assert.assertEquals(java.util.Arrays.toString(expected), java.util.Arrays.toString(actual));
- }
-
- private void assertFailure(String reason, SaveKeyringParcel parcel, LogType expected) {
-
- PgpEditKeyResult result = op.createSecretKeyRing(parcel);
-
- Assert.assertFalse(reason, result.success());
- Assert.assertNull(reason, result.getRing());
- Assert.assertTrue(reason + "(with correct error)",
- result.getLog().containsType(expected));
-
- }
-
- private void assertModifyFailure(String reason, UncachedKeyRing ring,
- SaveKeyringParcel parcel, CryptoInputParcel cryptoInput, LogType expected)
- throws Exception {
-
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), false, 0);
- PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, parcel);
-
- Assert.assertFalse(reason, result.success());
- Assert.assertNull(reason, result.getRing());
- Assert.assertTrue(reason + "(with correct error)",
- result.getLog().containsType(expected));
-
- }
-
- private void assertModifyFailure(String reason, UncachedKeyRing ring, SaveKeyringParcel parcel,
- LogType expected)
- throws Exception {
-
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), false, 0);
- PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, parcel);
-
- Assert.assertFalse(reason, result.success());
- Assert.assertNull(reason, result.getRing());
- Assert.assertTrue(reason + "(with correct error)",
- result.getLog().containsType(expected));
-
- }
-
- private UncachedKeyRing assertCreateSuccess(String reason, SaveKeyringParcel parcel) {
-
- PgpEditKeyResult result = op.createSecretKeyRing(parcel);
-
- Assert.assertTrue(reason, result.success());
- Assert.assertNotNull(reason, result.getRing());
-
- return result.getRing();
-
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java
deleted file mode 100644
index 2b184c075..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * 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.BeforeClass;
-import org.junit.runner.RunWith;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.Before;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.ShadowLog;
-import org.spongycastle.bcpg.BCPGInputStream;
-import org.spongycastle.bcpg.HashAlgorithmTags;
-import org.spongycastle.bcpg.Packet;
-import org.spongycastle.bcpg.PacketTags;
-import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
-import org.spongycastle.bcpg.UserIDPacket;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.spongycastle.openpgp.PGPPrivateKey;
-import org.spongycastle.openpgp.PGPPublicKey;
-import org.spongycastle.openpgp.PGPSecretKey;
-import org.spongycastle.openpgp.PGPSecretKeyRing;
-import org.spongycastle.openpgp.PGPSignature;
-import org.spongycastle.openpgp.PGPSignatureGenerator;
-import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
-import org.spongycastle.openpgp.PGPUtil;
-import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
-import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
-import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
-import org.spongycastle.openpgp.operator.PGPDigestCalculator;
-import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
-import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
-import org.spongycastle.util.Strings;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
-import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
-import org.sufficientlysecure.keychain.util.Passphrase;
-
-import java.io.ByteArrayInputStream;
-import java.security.Security;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-
-
-/** Tests for the UncachedKeyring.canonicalize method.
- *
- * This is a complex and crypto-relevant method, which takes care of sanitizing keyrings.
- * Test cases are made for all its assertions.
- */
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class UncachedKeyringCanonicalizeTest {
-
- static UncachedKeyRing staticRing;
- static int totalPackets;
- UncachedKeyRing ring;
- ArrayList<RawPacket> onlyA = new ArrayList<RawPacket>();
- ArrayList<RawPacket> onlyB = new ArrayList<RawPacket>();
- OperationResult.OperationLog log = new OperationResult.OperationLog();
- PGPSignatureSubpacketGenerator subHashedPacketsGen;
- PGPSecretKey secretKey;
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- Security.insertProviderAt(new BouncyCastleProvider(), 1);
- ShadowLog.stream = System.out;
-
- 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.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
-
- parcel.mAddUserIds.add("twi");
- parcel.mAddUserIds.add("pink");
- {
- WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(100,
- "sunshine, sunshine, ladybugs awake~".getBytes());
- parcel.mAddUserAttribute.add(uat);
- }
-
- // passphrase is tested in PgpKeyOperationTest, just use empty here
- parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
- PgpKeyOperation op = new PgpKeyOperation(null);
-
- PgpEditKeyResult result = op.createSecretKeyRing(parcel);
- Assert.assertTrue("initial test key creation must succeed", result.success());
- staticRing = result.getRing();
- Assert.assertNotNull("initial test key creation must succeed", staticRing);
-
- staticRing = staticRing.canonicalize(new OperationLog(), 0).getUncachedKeyRing();
-
- // just for later reference
- totalPackets = 11;
-
- // we sleep here for a second, to make sure all new certificates have different timestamps
- Thread.sleep(1000);
- }
-
- @Before public void setUp() throws Exception {
- // show Log.x messages in system.out
- ShadowLog.stream = System.out;
- ring = staticRing;
-
- subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
- secretKey = new PGPSecretKeyRing(ring.getEncoded(), new JcaKeyFingerprintCalculator())
- .getSecretKey();
- }
-
- /** Make sure the assumptions made about the generated ring packet structure are valid. */
- @Test public void testGeneratedRingStructure() throws Exception {
-
- Iterator<RawPacket> it = KeyringTestingHelper.parseKeyring(ring.getEncoded());
-
- Assert.assertEquals("packet #0 should be secret key",
- PacketTags.SECRET_KEY, it.next().tag);
-
- Assert.assertEquals("packet #1 should be user id",
- PacketTags.USER_ID, it.next().tag);
- Assert.assertEquals("packet #2 should be signature",
- PacketTags.SIGNATURE, it.next().tag);
-
- Assert.assertEquals("packet #3 should be user id",
- PacketTags.USER_ID, it.next().tag);
- Assert.assertEquals("packet #4 should be signature",
- PacketTags.SIGNATURE, it.next().tag);
-
- Assert.assertEquals("packet #5 should be user id",
- PacketTags.USER_ATTRIBUTE, it.next().tag);
- Assert.assertEquals("packet #6 should be signature",
- PacketTags.SIGNATURE, it.next().tag);
-
- Assert.assertEquals("packet #7 should be secret subkey",
- PacketTags.SECRET_SUBKEY, it.next().tag);
- Assert.assertEquals("packet #8 should be signature",
- PacketTags.SIGNATURE, it.next().tag);
-
- Assert.assertEquals("packet #9 should be secret subkey",
- PacketTags.SECRET_SUBKEY, it.next().tag);
- Assert.assertEquals("packet #10 should be signature",
- PacketTags.SIGNATURE, it.next().tag);
-
- Assert.assertFalse("exactly 11 packets total", it.hasNext());
-
- Assert.assertArrayEquals("created keyring should be constant through canonicalization",
- ring.getEncoded(), ring.canonicalize(log, 0).getEncoded());
-
- }
-
- @Test public void testUidSignature() throws Exception {
-
- UncachedPublicKey masterKey = ring.getPublicKey();
- final WrappedSignature sig = masterKey.getSignaturesForRawId(Strings.toUTF8ByteArray("twi")).next();
-
- byte[] raw = sig.getEncoded();
- // destroy the signature
- raw[raw.length - 5] += 1;
- final WrappedSignature brokenSig = WrappedSignature.fromBytes(raw);
-
- { // bad certificates get stripped
- UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, brokenSig.getEncoded(), 3);
- CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0);
-
- Assert.assertTrue("canonicalized keyring with invalid extra sig must be same as original one",
- !KeyringTestingHelper.diffKeyrings(
- ring.getEncoded(), canonicalized.getEncoded(), onlyA, onlyB));
- }
-
- // remove user id certificate for one user
- final UncachedKeyRing base = KeyringTestingHelper.removePacket(ring, 2);
-
- { // user id without certificate should be removed
- CanonicalizedKeyRing modified = base.canonicalize(log, 0);
- Assert.assertTrue("canonicalized keyring must differ", KeyringTestingHelper.diffKeyrings(
- ring.getEncoded(), modified.getEncoded(), onlyA, onlyB));
-
- Assert.assertEquals("two packets should be stripped after canonicalization", 2, onlyA.size());
- Assert.assertEquals("no new packets after canonicalization", 0, onlyB.size());
-
- Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(0).buf)).readPacket();
- Assert.assertTrue("first stripped packet must be user id", p instanceof UserIDPacket);
- Assert.assertEquals("missing user id must be the expected one",
- "twi", ((UserIDPacket) p).getID());
-
- Assert.assertArrayEquals("second stripped packet must be signature we removed",
- sig.getEncoded(), onlyA.get(1).buf);
-
- }
-
- { // add error to signature
-
- UncachedKeyRing modified = KeyringTestingHelper.injectPacket(base, brokenSig.getEncoded(), 3);
- CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0);
-
- Assert.assertTrue("canonicalized keyring must differ", KeyringTestingHelper.diffKeyrings(
- ring.getEncoded(), canonicalized.getEncoded(), onlyA, onlyB));
-
- Assert.assertEquals("two packets should be missing after canonicalization", 2, onlyA.size());
- Assert.assertEquals("no new packets after canonicalization", 0, onlyB.size());
-
- Packet p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(0).buf)).readPacket();
- Assert.assertTrue("first stripped packet must be user id", p instanceof UserIDPacket);
- Assert.assertEquals("missing user id must be the expected one",
- "twi", ((UserIDPacket) p).getID());
-
- Assert.assertArrayEquals("second stripped packet must be signature we removed",
- sig.getEncoded(), onlyA.get(1).buf);
- }
-
- }
-
- @Test public void testUidDestroy() throws Exception {
-
- // signature for "twi"
- ring = KeyringTestingHelper.removePacket(ring, 2);
- // signature for "pink"
- ring = KeyringTestingHelper.removePacket(ring, 3);
-
- // canonicalization should fail, because there are no valid uids left
- CanonicalizedKeyRing canonicalized = ring.canonicalize(log, 0);
- Assert.assertNull("canonicalization of keyring with no valid uids should fail", canonicalized);
-
- }
-
- @Test public void testRevocationRedundant() throws Exception {
-
- PGPSignature revocation = forgeSignature(
- secretKey, PGPSignature.KEY_REVOCATION, subHashedPacketsGen, secretKey.getPublicKey());
-
- UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, revocation.getEncoded(), 1);
-
- // try to add the same packet again, it should be rejected in all positions
- injectEverywhere(modified, revocation.getEncoded());
-
- // an older (but different!) revocation should be rejected as well
- subHashedPacketsGen.setSignatureCreationTime(false, new Date(new Date().getTime() -1000*1000));
- revocation = forgeSignature(
- secretKey, PGPSignature.KEY_REVOCATION, subHashedPacketsGen, secretKey.getPublicKey());
-
- injectEverywhere(modified, revocation.getEncoded());
-
- }
-
- @Test public void testUidRedundant() throws Exception {
-
- // an older uid certificate should be rejected
- subHashedPacketsGen.setSignatureCreationTime(false, new Date(new Date().getTime() -1000*1000));
- PGPSignature revocation = forgeSignature(
- secretKey, PGPSignature.DEFAULT_CERTIFICATION, subHashedPacketsGen, "twi", secretKey.getPublicKey());
-
- injectEverywhere(ring, revocation.getEncoded());
-
- }
-
- @Test public void testUidRevocationOutdated() throws Exception {
- // an older uid revocation cert should be rejected
- subHashedPacketsGen.setSignatureCreationTime(false, new Date(new Date().getTime() -1000*1000));
- PGPSignature revocation = forgeSignature(
- secretKey, PGPSignature.CERTIFICATION_REVOCATION, subHashedPacketsGen, "twi", secretKey.getPublicKey());
-
- injectEverywhere(ring, revocation.getEncoded());
-
- }
-
- @Test public void testUidRevocationRedundant() throws Exception {
-
- PGPSignature revocation = forgeSignature(
- secretKey, PGPSignature.CERTIFICATION_REVOCATION, subHashedPacketsGen, "twi", secretKey.getPublicKey());
-
- // add that revocation to the base, and check if the redundant one will be rejected as well
- UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, revocation.getEncoded(), 2);
-
- injectEverywhere(modified, revocation.getEncoded());
-
- // an older (but different!) uid revocation should be rejected as well
- subHashedPacketsGen.setSignatureCreationTime(false, new Date(new Date().getTime() -1000*1000));
- revocation = forgeSignature(
- secretKey, PGPSignature.CERTIFICATION_REVOCATION, subHashedPacketsGen, "twi", secretKey.getPublicKey());
-
- injectEverywhere(modified, revocation.getEncoded());
-
- }
-
- @Test public void testDuplicateUid() throws Exception {
-
- // get subkey packets
- Iterator<RawPacket> it = KeyringTestingHelper.parseKeyring(ring.getEncoded());
- RawPacket uidPacket = KeyringTestingHelper.getNth(it, 3);
- RawPacket uidSig = it.next();
-
- // inject at a second position
- UncachedKeyRing modified = ring;
- modified = KeyringTestingHelper.injectPacket(modified, uidPacket.buf, 5);
- modified = KeyringTestingHelper.injectPacket(modified, uidSig.buf, 6);
-
- // canonicalize, and check if we lose the bad signature
- OperationLog log = new OperationLog();
- CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0);
- Assert.assertNotNull("canonicalization with duplicate user id should succeed", canonicalized);
- Assert.assertTrue("log should contain uid_dup event", log.containsType(LogType.MSG_KC_UID_DUP));
- /* TODO actually test ths, and fix behavior
- Assert.assertTrue("duplicate user id packets should be gone after canonicalization",
- KeyringTestingHelper.diffKeyrings(modified.getEncoded(), canonicalized.getEncoded(),
- onlyA, onlyB)
- );
- Assert.assertEquals("canonicalized keyring should have lost the two duplicate packets",
- 2, onlyA.size());
- Assert.assertTrue("canonicalized keyring should still contain the user id",
- canonicalized.getUnorderedUserIds().contains(new UserIDPacket(uidPacket.buf).getID()));
- */
-
- }
-
- @Test public void testSignatureBroken() throws Exception {
-
- injectEverytype(secretKey, ring, subHashedPacketsGen, true);
-
- }
-
- @Test public void testForeignSignature() throws Exception {
-
- SaveKeyringParcel parcel = new SaveKeyringParcel();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
- parcel.mAddUserIds.add("trix");
- PgpKeyOperation op = new PgpKeyOperation(null);
-
- OperationResult.OperationLog log = new OperationResult.OperationLog();
- UncachedKeyRing foreign = op.createSecretKeyRing(parcel).getRing();
-
- Assert.assertNotNull("initial test key creation must succeed", foreign);
- PGPSecretKey foreignSecretKey =
- new PGPSecretKeyRing(foreign.getEncoded(), new JcaKeyFingerprintCalculator())
- .getSecretKey();
-
- injectEverytype(foreignSecretKey, ring, subHashedPacketsGen);
-
- }
-
- @Test public void testSignatureFuture() throws Exception {
-
- // generate future timestamp (we allow up to one day future timestamps)
- Calendar cal = Calendar.getInstance();
- cal.add(Calendar.DAY_OF_YEAR, 2);
- subHashedPacketsGen.setSignatureCreationTime(false, cal.getTime());
-
- injectEverytype(secretKey, ring, subHashedPacketsGen);
-
- }
-
- @Test public void testSignatureLocal() throws Exception {
-
- // make key local only
- subHashedPacketsGen.setExportable(false, false);
-
- injectEverytype(secretKey, ring, subHashedPacketsGen);
-
- }
-
- @Test public void testSubkeyDestroy() throws Exception {
-
- // signature for second key (first subkey)
- UncachedKeyRing modified = KeyringTestingHelper.removePacket(ring, 8);
-
- // canonicalization should fail, because there are no valid uids left
- CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0);
- Assert.assertTrue("keyring with missing subkey binding sig should differ from intact one after canonicalization",
- KeyringTestingHelper.diffKeyrings(ring.getEncoded(), canonicalized.getEncoded(),
- onlyA, onlyB)
- );
-
- Assert.assertEquals("canonicalized keyring should have two extra packets", 2, onlyA.size());
- Assert.assertEquals("canonicalized keyring should have no extra packets", 0, onlyB.size());
-
- Assert.assertEquals("first missing packet should be the subkey",
- PacketTags.SECRET_SUBKEY, onlyA.get(0).tag);
- Assert.assertEquals("second missing packet should be subkey's signature",
- PacketTags.SIGNATURE, onlyA.get(1).tag);
- Assert.assertEquals("second missing packet should be next to subkey",
- onlyA.get(0).position + 1, onlyA.get(1).position);
-
- }
-
- @Test public void testSubkeyBindingNoPKB() throws Exception {
-
- UncachedPublicKey pKey = KeyringTestingHelper.getNth(ring.getPublicKeys(), 1);
- PGPSignature sig;
-
- subHashedPacketsGen.setKeyFlags(false, KeyFlags.SIGN_DATA);
-
- {
- // forge a (newer) signature, which has the sign flag but no primary key binding sig
- PGPSignatureSubpacketGenerator unhashedSubs = new PGPSignatureSubpacketGenerator();
-
- // just add any random signature, because why not
- unhashedSubs.setEmbeddedSignature(false, forgeSignature(
- secretKey, PGPSignature.POSITIVE_CERTIFICATION, subHashedPacketsGen,
- secretKey.getPublicKey()
- )
- );
-
- sig = forgeSignature(
- secretKey, PGPSignature.SUBKEY_BINDING, subHashedPacketsGen, unhashedSubs,
- secretKey.getPublicKey(), pKey.getPublicKey());
-
- // inject in the right position
- UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sig.getEncoded(), 8);
-
- // canonicalize, and check if we lose the bad signature
- CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0);
- Assert.assertFalse("subkey binding signature should be gone after canonicalization",
- KeyringTestingHelper.diffKeyrings(ring.getEncoded(), canonicalized.getEncoded(),
- onlyA, onlyB)
- );
- }
-
- { // now try one with a /bad/ primary key binding signature
-
- PGPSignatureSubpacketGenerator unhashedSubs = new PGPSignatureSubpacketGenerator();
- // this one is signed by the primary key itself, not the subkey - but it IS primary binding
- unhashedSubs.setEmbeddedSignature(false, forgeSignature(
- secretKey, PGPSignature.PRIMARYKEY_BINDING, subHashedPacketsGen,
- secretKey.getPublicKey(), pKey.getPublicKey()
- )
- );
-
- sig = forgeSignature(
- secretKey, PGPSignature.SUBKEY_BINDING, subHashedPacketsGen, unhashedSubs,
- secretKey.getPublicKey(), pKey.getPublicKey());
-
- // inject in the right position
- UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sig.getEncoded(), 8);
-
- // canonicalize, and check if we lose the bad signature
- CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0);
- Assert.assertFalse("subkey binding signature should be gone after canonicalization",
- KeyringTestingHelper.diffKeyrings(ring.getEncoded(), canonicalized.getEncoded(),
- onlyA, onlyB)
- );
- }
-
- }
-
- @Test public void testSubkeyBindingRedundant() throws Exception {
-
- UncachedPublicKey pKey = KeyringTestingHelper.getNth(ring.getPublicKeys(), 2);
-
- subHashedPacketsGen.setKeyFlags(false, KeyFlags.ENCRYPT_COMMS);
- PGPSignature sig2 = forgeSignature(
- secretKey, PGPSignature.SUBKEY_BINDING, subHashedPacketsGen,
- secretKey.getPublicKey(), pKey.getPublicKey());
-
- subHashedPacketsGen.setSignatureCreationTime(false, new Date(new Date().getTime() -1000*1000));
- PGPSignature sig1 = forgeSignature(
- secretKey, PGPSignature.SUBKEY_REVOCATION, subHashedPacketsGen,
- secretKey.getPublicKey(), pKey.getPublicKey());
-
- subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
- subHashedPacketsGen.setSignatureCreationTime(false, new Date(new Date().getTime() -100*1000));
- PGPSignature sig3 = forgeSignature(
- secretKey, PGPSignature.SUBKEY_BINDING, subHashedPacketsGen,
- secretKey.getPublicKey(), pKey.getPublicKey());
-
- UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sig1.getEncoded(), 10);
- modified = KeyringTestingHelper.injectPacket(modified, sig2.getEncoded(), 11);
- modified = KeyringTestingHelper.injectPacket(modified, sig1.getEncoded(), 12);
- modified = KeyringTestingHelper.injectPacket(modified, sig3.getEncoded(), 13);
-
- // canonicalize, and check if we lose the bad signature
- CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0);
- Assert.assertTrue("subkey binding signature should be gone after canonicalization",
- KeyringTestingHelper.diffKeyrings(modified.getEncoded(), canonicalized.getEncoded(),
- onlyA, onlyB)
- );
-
- Assert.assertEquals("canonicalized keyring should have lost two packets", 3, onlyA.size());
- Assert.assertEquals("canonicalized keyring should have no extra packets", 0, onlyB.size());
-
- Assert.assertEquals("first missing packet should be the subkey",
- PacketTags.SIGNATURE, onlyA.get(0).tag);
- Assert.assertEquals("second missing packet should be a signature",
- PacketTags.SIGNATURE, onlyA.get(1).tag);
- Assert.assertEquals("second missing packet should be a signature",
- PacketTags.SIGNATURE, onlyA.get(2).tag);
-
- }
-
- @Test
- public void testDuplicateSubkey() throws Exception {
-
- { // duplicate subkey
-
- // get subkey packets
- Iterator<RawPacket> it = KeyringTestingHelper.parseKeyring(ring.getEncoded());
- RawPacket subKey = KeyringTestingHelper.getNth(it, 7);
- RawPacket subSig = it.next();
-
- // inject at a second position
- UncachedKeyRing modified = ring;
- modified = KeyringTestingHelper.injectPacket(modified, subKey.buf, 9);
- modified = KeyringTestingHelper.injectPacket(modified, subSig.buf, 10);
-
- // canonicalize, and check if we lose the bad signature
- OperationLog log = new OperationLog();
- CanonicalizedKeyRing canonicalized = modified.canonicalize(log, 0);
- Assert.assertNull("canonicalization with duplicate subkey should fail", canonicalized);
- Assert.assertTrue("log should contain dup_key event", log.containsType(LogType.MSG_KC_ERROR_DUP_KEY));
- }
-
- { // duplicate subkey, which is the same as the master key
-
- // We actually encountered one of these in the wild:
- // https://www.sparkasse-holstein.de/firmenkunden/electronic_banking/secure-e-mail/pdf/Spk_Holstein_PGP_Domain-Zertifikat.asc
-
- CanonicalizedSecretKeyRing canonicalized = (CanonicalizedSecretKeyRing) ring.canonicalize(log, 0);
-
- CanonicalizedSecretKey masterSecretKey = canonicalized.getSecretKey();
- masterSecretKey.unlock(new Passphrase());
- PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
- CryptoInputParcel cryptoInput = new CryptoInputParcel();
- PGPSignature cert = PgpKeyOperation.generateSubkeyBindingSignature(
- PgpKeyOperation.getSignatureGenerator(masterSecretKey.getSecretKey(), cryptoInput),
- cryptoInput.getSignatureTime(),
- masterPublicKey, masterSecretKey.getPrivateKey(), masterSecretKey.getPrivateKey(),
- masterPublicKey, masterSecretKey.getKeyUsage(), 0);
- PGPPublicKey subPubKey = PGPPublicKey.addSubkeyBindingCertification(masterPublicKey, cert);
-
- PGPSecretKey sKey;
- {
- // Build key encrypter and decrypter based on passphrase
- PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder()
- .build().get(HashAlgorithmTags.SHA256);
- PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
- SymmetricKeyAlgorithmTags.AES_256, encryptorHashCalc, 10)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
-
- // NOTE: only SHA1 is supported for key checksum calculations.
- PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
- .build().get(HashAlgorithmTags.SHA1);
- sKey = new PGPSecretKey(masterSecretKey.getPrivateKey(), subPubKey, sha1Calc, false, keyEncryptor);
- }
-
- UncachedKeyRing modified = KeyringTestingHelper.injectPacket(ring, sKey.getEncoded(), 7);
-
- // canonicalize, and check if we lose the bad signature
- OperationLog log = new OperationLog();
- CanonicalizedKeyRing result = modified.canonicalize(log, 0);
- Assert.assertNull("canonicalization with duplicate subkey (from master) should fail", result);
- Assert.assertTrue("log should contain dup_key event", log.containsType(LogType.MSG_KC_ERROR_DUP_KEY));
- }
-
- }
-
- private static final int[] sigtypes_direct = new int[] {
- PGPSignature.KEY_REVOCATION,
- PGPSignature.DIRECT_KEY,
- };
- private static final int[] sigtypes_uid = new int[] {
- PGPSignature.DEFAULT_CERTIFICATION,
- PGPSignature.NO_CERTIFICATION,
- PGPSignature.CASUAL_CERTIFICATION,
- PGPSignature.POSITIVE_CERTIFICATION,
- PGPSignature.CERTIFICATION_REVOCATION,
- };
- private static final int[] sigtypes_subkey = new int[] {
- PGPSignature.SUBKEY_BINDING,
- PGPSignature.PRIMARYKEY_BINDING,
- PGPSignature.SUBKEY_REVOCATION,
- };
-
- private static void injectEverytype(PGPSecretKey secretKey,
- UncachedKeyRing ring,
- PGPSignatureSubpacketGenerator subHashedPacketsGen)
- throws Exception {
- injectEverytype(secretKey, ring, subHashedPacketsGen, false);
- }
-
- private static void injectEverytype(PGPSecretKey secretKey,
- UncachedKeyRing ring,
- PGPSignatureSubpacketGenerator subHashedPacketsGen,
- boolean breakSig)
- throws Exception {
-
- for (int sigtype : sigtypes_direct) {
- PGPSignature sig = forgeSignature(
- secretKey, sigtype, subHashedPacketsGen, secretKey.getPublicKey());
- byte[] encoded = sig.getEncoded();
- if (breakSig) {
- encoded[encoded.length-10] += 1;
- }
- injectEverywhere(ring, encoded);
- }
-
- for (int sigtype : sigtypes_uid) {
- PGPSignature sig = forgeSignature(
- secretKey, sigtype, subHashedPacketsGen, "twi", secretKey.getPublicKey());
-
- byte[] encoded = sig.getEncoded();
- if (breakSig) {
- encoded[encoded.length-10] += 1;
- }
- injectEverywhere(ring, encoded);
- }
-
- for (int sigtype : sigtypes_subkey) {
- PGPSignature sig = forgeSignature(
- secretKey, sigtype, subHashedPacketsGen,
- secretKey.getPublicKey(), secretKey.getPublicKey());
-
- byte[] encoded = sig.getEncoded();
- if (breakSig) {
- encoded[encoded.length-10] += 1;
- }
- injectEverywhere(ring, encoded);
- }
-
- }
-
- private static void injectEverywhere(UncachedKeyRing ring, byte[] packet) throws Exception {
-
- OperationResult.OperationLog log = new OperationResult.OperationLog();
-
- byte[] encodedRing = ring.getEncoded();
-
- for(int i = 0; i < totalPackets; i++) {
-
- byte[] brokenEncoded = KeyringTestingHelper.injectPacket(encodedRing, packet, i);
-
- try {
-
- UncachedKeyRing brokenRing = UncachedKeyRing.decodeFromData(brokenEncoded);
-
- CanonicalizedKeyRing canonicalized = brokenRing.canonicalize(log, 0);
- if (canonicalized == null) {
- System.out.println("ok, canonicalization failed.");
- continue;
- }
-
- Assert.assertArrayEquals("injected bad signature must be gone after canonicalization",
- ring.getEncoded(), canonicalized.getEncoded());
-
- } catch (Exception e) {
- System.out.println("ok, rejected with: " + e.getMessage());
- }
- }
-
- }
-
- private static PGPSignature forgeSignature(PGPSecretKey key, int type,
- PGPSignatureSubpacketGenerator subpackets,
- PGPPublicKey publicKey)
- throws Exception {
-
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
- PGPPrivateKey privateKey = key.extractPrivateKey(keyDecryptor);
-
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- publicKey.getAlgorithm(), PGPUtil.SHA1)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
-
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
- sGen.setHashedSubpackets(subpackets.generate());
- sGen.init(type, privateKey);
- return sGen.generateCertification(publicKey);
-
- }
-
- private static PGPSignature forgeSignature(PGPSecretKey key, int type,
- PGPSignatureSubpacketGenerator subpackets,
- String userId, PGPPublicKey publicKey)
- throws Exception {
-
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
- PGPPrivateKey privateKey = key.extractPrivateKey(keyDecryptor);
-
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- publicKey.getAlgorithm(), PGPUtil.SHA1)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
-
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
- sGen.setHashedSubpackets(subpackets.generate());
- sGen.init(type, privateKey);
- return sGen.generateCertification(userId, publicKey);
-
- }
-
- private static PGPSignature forgeSignature(PGPSecretKey key, int type,
- PGPSignatureSubpacketGenerator subpackets,
- PGPPublicKey publicKey, PGPPublicKey signedKey)
- throws Exception {
-
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
- PGPPrivateKey privateKey = key.extractPrivateKey(keyDecryptor);
-
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- publicKey.getAlgorithm(), PGPUtil.SHA1)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
-
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
- sGen.setHashedSubpackets(subpackets.generate());
- sGen.init(type, privateKey);
- return sGen.generateCertification(publicKey, signedKey);
-
- }
-
- private static PGPSignature forgeSignature(PGPSecretKey key, int type,
- PGPSignatureSubpacketGenerator hashedSubs,
- PGPSignatureSubpacketGenerator unhashedSubs,
- PGPPublicKey publicKey, PGPPublicKey signedKey)
- throws Exception {
-
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
- PGPPrivateKey privateKey = key.extractPrivateKey(keyDecryptor);
-
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- publicKey.getAlgorithm(), PGPUtil.SHA1)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
-
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
- sGen.setHashedSubpackets(hashedSubs.generate());
- sGen.setUnhashedSubpackets(unhashedSubs.generate());
- sGen.init(type, privateKey);
- return sGen.generateCertification(publicKey, signedKey);
-
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java
deleted file mode 100644
index 755a0b00d..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * 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.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.ShadowLog;
-import org.spongycastle.bcpg.BCPGInputStream;
-import org.spongycastle.bcpg.PacketTags;
-import org.spongycastle.bcpg.S2K;
-import org.spongycastle.bcpg.SecretKeyPacket;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.spongycastle.util.Strings;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation.PgpCertifyResult;
-import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
-import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
-import org.sufficientlysecure.keychain.util.Passphrase;
-import org.sufficientlysecure.keychain.util.ProgressScaler;
-
-import java.io.ByteArrayInputStream;
-import java.security.Security;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Random;
-
-/** Tests for the UncachedKeyring.merge method.
- *
- * This is another complex, crypto-related method. It merges information from one keyring into
- * another, keeping information from the base (ie, called object) keyring in case of conflicts.
- * The types of keys may be Public or Secret and can be mixed, For mixed types the result type
- * will be the same as the base keyring.
- *
- * Test cases:
- * - Merging keyrings with different masterKeyIds should fail
- * - Merging a key with itself should be a no-operation
- * - Merging a key with an extra revocation certificate, it should have that certificate
- * - Merging a key with an extra user id, it should have that extra user id and its certificates
- * - Merging a key with an extra user id certificate, it should have that certificate
- * - Merging a key with an extra subkey, it should have that subkey
- * - Merging a key with an extra subkey certificate, it should have that certificate
- * - All of the above operations should work regardless of the key types. This means in particular
- * that for new subkeys, an equivalent subkey of the proper type must be generated.
- * - In case of two secret keys with the same id but different S2K, the key of the base keyring
- * should be preferred (TODO or should it?)
- *
- * Note that the merge operation does not care about certificate validity, a bad certificate or
- * packet will be copied regardless. Filtering out bad packets is done with canonicalization.
- *
- */
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class UncachedKeyringMergeTest {
-
- static UncachedKeyRing staticRingA, staticRingB;
- UncachedKeyRing ringA, ringB;
- ArrayList<RawPacket> onlyA = new ArrayList<RawPacket>();
- ArrayList<RawPacket> onlyB = new ArrayList<RawPacket>();
- OperationResult.OperationLog log = new OperationResult.OperationLog();
- PgpKeyOperation op;
- SaveKeyringParcel parcel;
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- Security.insertProviderAt(new BouncyCastleProvider(), 1);
- ShadowLog.stream = System.out;
-
- {
- 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.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
-
- parcel.mAddUserIds.add("twi");
- parcel.mAddUserIds.add("pink");
- {
- WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(100,
- "sunshine, sunshine, ladybugs awake~".getBytes());
- parcel.mAddUserAttribute.add(uat);
- }
-
- // passphrase is tested in PgpKeyOperationTest, just use empty here
- parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
- PgpKeyOperation op = new PgpKeyOperation(null);
-
- OperationResult.OperationLog log = new OperationResult.OperationLog();
-
- PgpEditKeyResult result = op.createSecretKeyRing(parcel);
- staticRingA = result.getRing();
- staticRingA = staticRingA.canonicalize(new OperationLog(), 0).getUncachedKeyRing();
- }
-
- {
- SaveKeyringParcel parcel = new SaveKeyringParcel();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
-
- parcel.mAddUserIds.add("shy");
- // passphrase is tested in PgpKeyOperationTest, just use empty here
- parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
- PgpKeyOperation op = new PgpKeyOperation(null);
-
- OperationResult.OperationLog log = new OperationResult.OperationLog();
- PgpEditKeyResult result = op.createSecretKeyRing(parcel);
- staticRingB = result.getRing();
- staticRingB = staticRingB.canonicalize(new OperationLog(), 0).getUncachedKeyRing();
- }
-
- Assert.assertNotNull("initial test key creation must succeed", staticRingA);
- Assert.assertNotNull("initial test key creation must succeed", staticRingB);
-
- // we sleep here for a second, to make sure all new certificates have different timestamps
- Thread.sleep(1000);
- }
-
- @Before
- public void setUp() throws Exception {
- // show Log.x messages in system.out
- ShadowLog.stream = System.out;
- ringA = staticRingA;
- ringB = staticRingB;
-
- // setting up some parameters just to reduce code duplication
- op = new PgpKeyOperation(new ProgressScaler(null, 0, 100, 100));
-
- // set this up, gonna need it more than once
- parcel = new SaveKeyringParcel();
- parcel.mMasterKeyId = ringA.getMasterKeyId();
- parcel.mFingerprint = ringA.getFingerprint();
- }
-
- public void testSelfNoOp() throws Exception {
-
- UncachedKeyRing merged = mergeWithChecks(ringA, ringA, null);
- Assert.assertArrayEquals("keyring merged with itself must be identical",
- ringA.getEncoded(), merged.getEncoded()
- );
-
- }
-
- @Test
- public void testDifferentMasterKeyIds() throws Exception {
-
- Assert.assertNotEquals("generated key ids must be different",
- ringA.getMasterKeyId(), ringB.getMasterKeyId());
-
- Assert.assertNull("merging keys with differing key ids must fail",
- ringA.merge(ringB, log, 0));
- Assert.assertNull("merging keys with differing key ids must fail",
- ringB.merge(ringA, log, 0));
-
- }
-
- @Test
- public void testAddedUserId() throws Exception {
-
- UncachedKeyRing modifiedA, modifiedB; {
- CanonicalizedSecretKeyRing secretRing =
- new CanonicalizedSecretKeyRing(ringA.getEncoded(), false, 0);
-
- parcel.reset();
- parcel.mAddUserIds.add("flim");
- modifiedA = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Passphrase()), parcel).getRing();
-
- parcel.reset();
- parcel.mAddUserIds.add("flam");
- modifiedB = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Passphrase()), parcel).getRing();
- }
-
- { // merge A into base
- UncachedKeyRing merged = mergeWithChecks(ringA, modifiedA);
-
- Assert.assertEquals("merged keyring must have lost no packets", 0, onlyA.size());
- Assert.assertEquals("merged keyring must have gained two packets", 2, onlyB.size());
- Assert.assertTrue("merged keyring must contain new user id",
- merged.getPublicKey().getUnorderedUserIds().contains("flim"));
- }
-
- { // merge A into B
- UncachedKeyRing merged = mergeWithChecks(modifiedA, modifiedB, ringA);
-
- Assert.assertEquals("merged keyring must have lost no packets", 0, onlyA.size());
- Assert.assertEquals("merged keyring must have gained four packets", 4, onlyB.size());
- Assert.assertTrue("merged keyring must contain first new user id",
- merged.getPublicKey().getUnorderedUserIds().contains("flim"));
- Assert.assertTrue("merged keyring must contain second new user id",
- merged.getPublicKey().getUnorderedUserIds().contains("flam"));
-
- }
-
- }
-
- @Test
- public void testAddedSubkeyId() throws Exception {
-
- UncachedKeyRing modifiedA, modifiedB;
- long subKeyIdA, subKeyIdB;
- {
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ringA.getEncoded(), false, 0);
-
- parcel.reset();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
- modifiedA = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Passphrase()), parcel).getRing();
- modifiedB = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Passphrase()), parcel).getRing();
-
- subKeyIdA = KeyringTestingHelper.getSubkeyId(modifiedA, 2);
- subKeyIdB = KeyringTestingHelper.getSubkeyId(modifiedB, 2);
-
- }
-
- {
- UncachedKeyRing merged = mergeWithChecks(ringA, modifiedA);
-
- Assert.assertEquals("merged keyring must have lost no packets", 0, onlyA.size());
- Assert.assertEquals("merged keyring must have gained two packets", 2, onlyB.size());
-
- long mergedKeyId = KeyringTestingHelper.getSubkeyId(merged, 2);
- Assert.assertEquals("merged keyring must contain the new subkey", subKeyIdA, mergedKeyId);
- }
-
- {
- UncachedKeyRing merged = mergeWithChecks(modifiedA, modifiedB, ringA);
-
- Assert.assertEquals("merged keyring must have lost no packets", 0, onlyA.size());
- Assert.assertEquals("merged keyring must have gained four packets", 4, onlyB.size());
-
- Iterator<UncachedPublicKey> it = merged.getPublicKeys();
- it.next(); it.next();
- Assert.assertEquals("merged keyring must contain the new subkey",
- subKeyIdA, it.next().getKeyId());
- Assert.assertEquals("merged keyring must contain both new subkeys",
- subKeyIdB, it.next().getKeyId());
- }
-
- }
-
- @Test
- public void testAddedKeySignature() throws Exception {
-
- final UncachedKeyRing modified; {
- parcel.reset();
- parcel.mRevokeSubKeys.add(KeyringTestingHelper.getSubkeyId(ringA, 1));
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(
- ringA.getEncoded(), false, 0);
- modified = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Passphrase()), parcel).getRing();
- }
-
- {
- UncachedKeyRing merged = ringA.merge(modified, log, 0);
- Assert.assertNotNull("merge must succeed", merged);
- Assert.assertFalse(
- "merging keyring with extra signatures into its base should yield that same keyring",
- KeyringTestingHelper.diffKeyrings(merged.getEncoded(), modified.getEncoded(), onlyA, onlyB)
- );
- }
-
- }
-
- @Test
- public void testAddedUserIdSignature() throws Exception {
-
- final UncachedKeyRing pubRing = ringA.extractPublicKeyRing();
-
- final UncachedKeyRing modified; {
- CanonicalizedPublicKeyRing publicRing = new CanonicalizedPublicKeyRing(
- pubRing.getEncoded(), 0);
-
- CanonicalizedSecretKey secretKey = new CanonicalizedSecretKeyRing(
- ringB.getEncoded(), false, 0).getSecretKey();
- secretKey.unlock(new Passphrase());
- PgpCertifyOperation op = new PgpCertifyOperation();
- CertifyAction action = new CertifyAction(pubRing.getMasterKeyId(), publicRing.getPublicKey().getUnorderedUserIds());
- // sign all user ids
- PgpCertifyResult result = op.certify(secretKey, publicRing, new OperationLog(), 0, action, null, new Date());
- Assert.assertTrue("certification must succeed", result.success());
- Assert.assertNotNull("certification must yield result", result.getCertifiedRing());
- modified = result.getCertifiedRing();
- }
-
- {
- UncachedKeyRing merged = ringA.merge(modified, log, 0);
- Assert.assertNotNull("merge must succeed", merged);
- Assert.assertArrayEquals("foreign signatures should not be merged into secret key",
- ringA.getEncoded(), merged.getEncoded()
- );
- }
-
- {
- byte[] sig = KeyringTestingHelper.getNth(
- modified.getPublicKey().getSignaturesForRawId(Strings.toUTF8ByteArray("twi")), 1).getEncoded();
-
- // inject the (foreign!) signature into subkey signature position
- UncachedKeyRing moreModified = KeyringTestingHelper.injectPacket(modified, sig, 1);
-
- UncachedKeyRing merged = ringA.merge(moreModified, log, 0);
- Assert.assertNotNull("merge must succeed", merged);
- Assert.assertArrayEquals("foreign signatures should not be merged into secret key",
- ringA.getEncoded(), merged.getEncoded()
- );
-
- merged = pubRing.merge(moreModified, log, 0);
- Assert.assertNotNull("merge must succeed", merged);
- Assert.assertTrue(
- "merged keyring should contain new signature",
- KeyringTestingHelper.diffKeyrings(pubRing.getEncoded(), merged.getEncoded(), onlyA, onlyB)
- );
- Assert.assertEquals("merged keyring should be missing no packets", 0, onlyA.size());
- Assert.assertEquals("merged keyring should contain exactly two more packets", 2, onlyB.size());
- Assert.assertEquals("first added packet should be a signature",
- PacketTags.SIGNATURE, onlyB.get(0).tag);
- Assert.assertEquals("first added packet should be in the position we injected it at",
- 1, onlyB.get(0).position);
- Assert.assertEquals("second added packet should be a signature",
- PacketTags.SIGNATURE, onlyB.get(1).tag);
-
- }
-
- {
- UncachedKeyRing merged = pubRing.merge(modified, log, 0);
- Assert.assertNotNull("merge must succeed", merged);
- Assert.assertFalse(
- "merging keyring with extra signatures into its base should yield that same keyring",
- KeyringTestingHelper.diffKeyrings(merged.getEncoded(), modified.getEncoded(), onlyA, onlyB)
- );
- }
- }
-
- @Test
- public void testAddedUserAttributeSignature() throws Exception {
-
- final UncachedKeyRing modified; {
- parcel.reset();
-
- Random r = new Random();
- int type = r.nextInt(110)+1;
- byte[] data = new byte[r.nextInt(2000)];
- new Random().nextBytes(data);
-
- WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data);
- parcel.mAddUserAttribute.add(uat);
-
- CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(
- ringA.getEncoded(), false, 0);
- modified = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Passphrase()), parcel).getRing();
- }
-
- {
- UncachedKeyRing merged = ringA.merge(modified, log, 0);
- Assert.assertNotNull("merge must succeed", merged);
- Assert.assertFalse(
- "merging keyring with extra user attribute into its base should yield that same keyring",
- KeyringTestingHelper.diffKeyrings(merged.getEncoded(), modified.getEncoded(), onlyA, onlyB)
- );
- }
-
- }
-
- private UncachedKeyRing mergeWithChecks(UncachedKeyRing a, UncachedKeyRing b)
- throws Exception {
- return mergeWithChecks(a, b, a);
- }
-
- private UncachedKeyRing mergeWithChecks(UncachedKeyRing a, UncachedKeyRing b,
- UncachedKeyRing base)
- throws Exception {
-
- Assert.assertTrue("merging keyring must be secret type", a.isSecret());
- Assert.assertTrue("merged keyring must be secret type", b.isSecret());
-
- final UncachedKeyRing resultA;
- UncachedKeyRing resultB;
-
- { // sec + sec
- resultA = a.merge(b, log, 0);
- Assert.assertNotNull("merge must succeed as sec(a)+sec(b)", resultA);
-
- resultB = b.merge(a, log, 0);
- Assert.assertNotNull("merge must succeed as sec(b)+sec(a)", resultB);
-
- // check commutativity, if requested
- Assert.assertFalse("result of merge must be commutative",
- KeyringTestingHelper.diffKeyrings(
- resultA.getEncoded(), resultB.getEncoded(), onlyA, onlyB)
- );
- }
-
- final UncachedKeyRing pubA = a.extractPublicKeyRing();
- final UncachedKeyRing pubB = b.extractPublicKeyRing();
-
- { // sec + pub
-
- // this one is special, because GNU_DUMMY keys might be generated!
-
- resultB = a.merge(pubB, log, 0);
- Assert.assertNotNull("merge must succeed as sec(a)+pub(b)", resultA);
-
- // these MAY diff
- KeyringTestingHelper.diffKeyrings(resultA.getEncoded(), resultB.getEncoded(),
- onlyA, onlyB);
-
- Assert.assertEquals("sec(a)+pub(b): results must have equal number of packets",
- onlyA.size(), onlyB.size());
-
- for (int i = 0; i < onlyA.size(); i++) {
- Assert.assertEquals("sec(a)+pub(c): old packet must be secret subkey",
- PacketTags.SECRET_SUBKEY, onlyA.get(i).tag);
- Assert.assertEquals("sec(a)+pub(c): new packet must be dummy secret subkey",
- PacketTags.SECRET_SUBKEY, onlyB.get(i).tag);
-
- SecretKeyPacket pA = (SecretKeyPacket) new BCPGInputStream(new ByteArrayInputStream(onlyA.get(i).buf)).readPacket();
- SecretKeyPacket pB = (SecretKeyPacket) new BCPGInputStream(new ByteArrayInputStream(onlyB.get(i).buf)).readPacket();
-
- Assert.assertArrayEquals("sec(a)+pub(c): both packets must have equal pubkey parts",
- pA.getPublicKeyPacket().getEncoded(), pB.getPublicKeyPacket().getEncoded()
- );
-
- Assert.assertEquals("sec(a)+pub(c): new packet should have GNU_DUMMY S2K type",
- S2K.GNU_DUMMY_S2K, pB.getS2K().getType());
- Assert.assertEquals("sec(a)+pub(c): new packet should have GNU_DUMMY protection mode 0x1",
- 0x1, pB.getS2K().getProtectionMode());
- Assert.assertEquals("sec(a)+pub(c): new packet secret key data should have length zero",
- 0, pB.getSecretKeyData().length);
- Assert.assertNull("sec(a)+pub(c): new packet should have no iv data", pB.getIV());
-
- }
-
- }
-
- { // pub + sec, and pub + pub
- final UncachedKeyRing pubResult = resultA.extractPublicKeyRing();
-
- resultB = pubA.merge(b, log, 0);
- Assert.assertNotNull("merge must succeed as pub(a)+sec(b)", resultA);
-
- Assert.assertFalse("result of pub(a)+sec(b) must be same as pub(sec(a)+sec(b))",
- KeyringTestingHelper.diffKeyrings(
- pubResult.getEncoded(), resultB.getEncoded(), onlyA, onlyB)
- );
-
- resultB = pubA.merge(pubB, log, 0);
- Assert.assertNotNull("merge must succeed as pub(a)+pub(b)", resultA);
-
- Assert.assertFalse("result of pub(a)+pub(b) must be same as pub(sec(a)+sec(b))",
- KeyringTestingHelper.diffKeyrings(
- pubResult.getEncoded(), resultB.getEncoded(), onlyA, onlyB)
- );
-
- }
-
- if (base != null) {
- // set up onlyA and onlyB to be a diff to the base
- Assert.assertTrue("merged keyring must differ from base",
- KeyringTestingHelper.diffKeyrings(
- base.getEncoded(), resultA.getEncoded(), onlyA, onlyB)
- );
- }
-
- return resultA;
-
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java
deleted file mode 100644
index a6159de4e..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * 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.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.ShadowLog;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing.IteratorWithIOThrow;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
-import org.sufficientlysecure.keychain.util.Passphrase;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Random;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class UncachedKeyringTest {
-
- static UncachedKeyRing staticRing, staticPubRing;
- UncachedKeyRing ring, pubRing;
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- ShadowLog.stream = System.out;
-
- 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.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Algorithm.RSA, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
-
- parcel.mAddUserIds.add("twi");
- parcel.mAddUserIds.add("pink");
- {
- Random r = new Random();
- int type = r.nextInt(110)+1;
- byte[] data = new byte[r.nextInt(2000)];
- new Random().nextBytes(data);
-
- WrappedUserAttribute uat = WrappedUserAttribute.fromSubpacket(type, data);
- parcel.mAddUserAttribute.add(uat);
- }
- // passphrase is tested in PgpKeyOperationTest, just use empty here
- parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
- PgpKeyOperation op = new PgpKeyOperation(null);
-
- PgpEditKeyResult result = op.createSecretKeyRing(parcel);
- staticRing = result.getRing();
- staticPubRing = staticRing.extractPublicKeyRing();
-
- Assert.assertNotNull("initial test key creation must succeed", staticRing);
-
- // we sleep here for a second, to make sure all new certificates have different timestamps
- Thread.sleep(1000);
- }
-
-
- @Before
- public void setUp() throws Exception {
- // show Log.x messages in system.out
- ShadowLog.stream = System.out;
- ring = staticRing;
- pubRing = staticPubRing;
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void testPublicKeyItRemove() throws Exception {
- Iterator<UncachedPublicKey> it = ring.getPublicKeys();
- it.remove();
- }
-
- @Test(expected = PgpGeneralException.class)
- public void testDecodeFromEmpty() throws Exception {
- UncachedKeyRing.decodeFromData(new byte[0]);
- }
-
- @Test
- public void testArmorIdentity() throws Exception {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ring.encodeArmored(out, "OpenKeychain");
-
- Assert.assertArrayEquals("armor encoded and decoded ring should be identical to original",
- ring.getEncoded(),
- UncachedKeyRing.decodeFromData(out.toByteArray()).getEncoded());
- }
-
- @Test(expected = PgpGeneralException.class)
- public void testDecodeEncodeMulti() throws Exception {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- // encode secret and public ring in here
- ring.encodeArmored(out, "OpenKeychain");
- pubRing.encodeArmored(out, "OpenKeychain");
-
- IteratorWithIOThrow<UncachedKeyRing> it =
- UncachedKeyRing.fromStream(new ByteArrayInputStream(out.toByteArray()));
- Assert.assertTrue("there should be two rings in the stream", it.hasNext());
- Assert.assertArrayEquals("first ring should be the first we put in",
- ring.getEncoded(), it.next().getEncoded());
- Assert.assertTrue("there should be two rings in the stream", it.hasNext());
- Assert.assertArrayEquals("second ring should be the second we put in",
- pubRing.getEncoded(), it.next().getEncoded());
- Assert.assertFalse("there should be two rings in the stream", it.hasNext());
-
- // this should fail with PgpGeneralException, since it expects exactly one ring
- UncachedKeyRing.decodeFromData(out.toByteArray());
- }
-
- @Test(expected = RuntimeException.class)
- public void testPublicExtractPublic() throws Exception {
- // can't do this, either!
- pubRing.extractPublicKeyRing();
- }
-
- @Test(expected = IOException.class)
- public void testBrokenVersionCert() throws Throwable {
- // this is a test for one of the patches we use on top of stock bouncycastle, which
- // returns an IOException rather than a RuntimeException in case of a bad certificate
- // version byte
- readRingFromResource("/test-keys/broken_cert_version.asc");
- }
-
- UncachedKeyRing readRingFromResource(String name) throws Throwable {
- return UncachedKeyRing.fromStream(UncachedKeyringTest.class.getResourceAsStream(name)).next();
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperKeyringTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperKeyringTest.java
deleted file mode 100644
index b0f47af29..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperKeyringTest.java
+++ /dev/null
@@ -1,101 +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 org.sufficientlysecure.keychain.provider;
-
-import java.util.Collections;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.ArrayList;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.*;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class ProviderHelperKeyringTest {
-
- @Test
- public void testSavePublicKeyring() throws Exception {
- Assert.assertTrue(new KeyringTestingHelper(Robolectric.application).addKeyring(Collections.singleton(
- "/public-key-for-sample.blob"
- )));
- }
-
- // @Test
- public void testSavePublicKeyringRsa() throws Exception {
- Assert.assertTrue(new KeyringTestingHelper(Robolectric.application).addKeyring(prependResourcePath(Arrays.asList(
- "000001-006.public_key",
- "000002-013.user_id",
- "000003-002.sig",
- "000004-012.ring_trust",
- "000005-002.sig",
- "000006-012.ring_trust",
- "000007-002.sig",
- "000008-012.ring_trust",
- "000009-002.sig",
- "000010-012.ring_trust",
- "000011-002.sig",
- "000012-012.ring_trust",
- "000013-014.public_subkey",
- "000014-002.sig",
- "000015-012.ring_trust"
- ))));
- }
-
- // @Test
- public void testSavePublicKeyringDsa() throws Exception {
- Assert.assertTrue(new KeyringTestingHelper(Robolectric.application).addKeyring(prependResourcePath(Arrays.asList(
- "000016-006.public_key",
- "000017-002.sig",
- "000018-012.ring_trust",
- "000019-013.user_id",
- "000020-002.sig",
- "000021-012.ring_trust",
- "000022-002.sig",
- "000023-012.ring_trust",
- "000024-014.public_subkey",
- "000025-002.sig",
- "000026-012.ring_trust"
- ))));
- }
-
- // @Test
- public void testSavePublicKeyringDsa2() throws Exception {
- Assert.assertTrue(new KeyringTestingHelper(Robolectric.application).addKeyring(prependResourcePath(Arrays.asList(
- "000027-006.public_key",
- "000028-002.sig",
- "000029-012.ring_trust",
- "000030-013.user_id",
- "000031-002.sig",
- "000032-012.ring_trust",
- "000033-002.sig",
- "000034-012.ring_trust"
- ))));
- }
-
- private static Collection<String> prependResourcePath(Collection<String> files) {
- Collection<String> prependedFiles = new ArrayList<String>();
- for (String file: files) {
- prependedFiles.add("/OpenPGP-Haskell/tests/data/" + file);
- }
- return prependedFiles;
- }
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java
deleted file mode 100644
index 171ecc377..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * 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.provider;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.ShadowLog;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.util.encoders.Hex;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
-import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
-import org.sufficientlysecure.keychain.util.IterableIterator;
-import org.sufficientlysecure.keychain.util.ProgressScaler;
-
-import java.util.Arrays;
-import java.util.Iterator;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class ProviderHelperSaveTest {
-
- ProviderHelper mProviderHelper = new ProviderHelper(Robolectric.application);
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- ShadowLog.stream = System.out;
- }
-
- @Test public void testImportCooperPair() throws Exception {
-
- // insert two keys with same long key id, make sure the second one gets rejected either way!
- UncachedKeyRing first =
- readRingFromResource("/test-keys/cooperpair/9E669861368BCA0BE42DAF7DDDA252EBB8EBE1AF.asc");
- UncachedKeyRing second =
- readRingFromResource("/test-keys/cooperpair/A55120427374F3F7AA5F1166DDA252EBB8EBE1AF.asc");
-
- SaveKeyringResult result;
-
- // insert both keys, second should fail
- result = new ProviderHelper(Robolectric.application).savePublicKeyRing(first);
- Assert.assertTrue("first keyring import should succeed", result.success());
- result = new ProviderHelper(Robolectric.application).savePublicKeyRing(second);
- Assert.assertFalse("second keyring import should fail", result.success());
-
- new KeychainDatabase(Robolectric.application).clearDatabase();
-
- // and the other way around
- result = new ProviderHelper(Robolectric.application).savePublicKeyRing(second);
- Assert.assertTrue("first keyring import should succeed", result.success());
- result = new ProviderHelper(Robolectric.application).savePublicKeyRing(first);
- Assert.assertFalse("second keyring import should fail", result.success());
-
- }
-
- @Test public void testImportSymantec() throws Exception {
-
- // symantec pgp desktop exports secret keys without self certificates. we don't support
- // those on their own, but if they are imported together with their public key (or if
- // the public key is already known), the self certs info will be merged in as a special
- // case.
- UncachedKeyRing seckey =
- readRingFromResource("/test-keys/symantec_secret.asc");
- UncachedKeyRing pubkey =
- readRingFromResource("/test-keys/symantec_public.asc");
-
- SaveKeyringResult result;
-
- // insert secret, this should fail because of missing self-cert
- result = new ProviderHelper(Robolectric.application).saveSecretKeyRing(seckey, new ProgressScaler());
- Assert.assertFalse("secret keyring import before pubring import should fail", result.success());
-
- // insert pubkey, then seckey - both should succeed
- result = new ProviderHelper(Robolectric.application).savePublicKeyRing(pubkey);
- Assert.assertTrue("public keyring import should succeed", result.success());
- result = new ProviderHelper(Robolectric.application).saveSecretKeyRing(seckey, new ProgressScaler());
- Assert.assertTrue("secret keyring import after pubring import should succeed", result.success());
-
- }
-
- @Test public void testImportNoFlagKey() throws Exception {
-
- UncachedKeyRing pub = readRingFromResource("/test-keys/mailvelope_07_no_key_flags.asc");
- long keyId = pub.getMasterKeyId();
- Assert.assertEquals("key flags should be zero",
- 0, (long) pub.canonicalize(new OperationLog(), 0).getPublicKey().getKeyUsage());
-
- mProviderHelper.savePublicKeyRing(pub);
-
- CachedPublicKeyRing cachedRing = mProviderHelper.getCachedPublicKeyRing(keyId);
- CanonicalizedPublicKeyRing pubRing = mProviderHelper.getCanonicalizedPublicKeyRing(keyId);
-
- Assert.assertEquals("master key should be encryption key", keyId, pubRing.getEncryptId());
- Assert.assertEquals("master key should be encryption key (cached)", keyId, cachedRing.getEncryptId());
-
- Assert.assertEquals("canonicalized key flags should be zero",
- 0, (long) pubRing.getPublicKey().getKeyUsage());
- Assert.assertTrue("master key should be able to certify", pubRing.getPublicKey().canCertify());
- Assert.assertTrue("master key should be allowed to sign", pubRing.getPublicKey().canSign());
- Assert.assertTrue("master key should be able to encrypt", pubRing.getPublicKey().canEncrypt());
-
- }
-
- @Test public void testImportDivertToCard() throws Exception {
-
- UncachedKeyRing sec = readRingFromResource("/test-keys/divert_to_card_sec.asc");
- long keyId = sec.getMasterKeyId();
-
- SaveKeyringResult result;
-
- result = mProviderHelper.saveSecretKeyRing(sec, new ProgressScaler());
- Assert.assertTrue("import of secret keyring should succeed", result.success());
-
- // make sure both the CanonicalizedSecretKeyRing as well as the CachedPublicKeyRing correctly
- // indicate the secret key type
- CachedPublicKeyRing cachedRing = mProviderHelper.getCachedPublicKeyRing(keyId);
- CanonicalizedSecretKeyRing secRing = mProviderHelper.getCanonicalizedSecretKeyRing(keyId);
-
- Iterator<CanonicalizedSecretKey> it = secRing.secretKeyIterator().iterator();
-
- { // first subkey
- Assert.assertTrue("keyring should have 3 subkeys (1)", it.hasNext());
- CanonicalizedSecretKey key = it.next();
- Assert.assertEquals("first subkey should be of type sign+certify",
- KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, (int) key.getKeyUsage());
- Assert.assertEquals("first subkey should be divert-to-card",
- SecretKeyType.DIVERT_TO_CARD, key.getSecretKeyType());
- Assert.assertTrue("canCertify() should be true", key.canCertify());
- Assert.assertTrue("canSign() should be true", key.canSign());
-
- // cached
- Assert.assertEquals("all subkeys from CachedPublicKeyRing should be divert-to-key",
- SecretKeyType.DIVERT_TO_CARD, cachedRing.getSecretKeyType(key.getKeyId()));
- }
-
- { // second subkey
- Assert.assertTrue("keyring should have 3 subkeys (2)", it.hasNext());
- CanonicalizedSecretKey key = it.next();
- Assert.assertEquals("second subkey should be of type authenticate",
- KeyFlags.AUTHENTICATION, (int) key.getKeyUsage());
- Assert.assertEquals("second subkey should be divert-to-card",
- SecretKeyType.DIVERT_TO_CARD, key.getSecretKeyType());
- Assert.assertTrue("canAuthenticate() should be true", key.canAuthenticate());
-
- // cached
- Assert.assertEquals("all subkeys from CachedPublicKeyRing should be divert-to-key",
- SecretKeyType.DIVERT_TO_CARD, cachedRing.getSecretKeyType(key.getKeyId()));
- }
-
- { // third subkey
- Assert.assertTrue("keyring should have 3 subkeys (3)", it.hasNext());
- CanonicalizedSecretKey key = it.next();
- Assert.assertEquals("first subkey should be of type encrypt (both types)",
- KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, (int) key.getKeyUsage());
- Assert.assertEquals("third subkey should be divert-to-card",
- SecretKeyType.DIVERT_TO_CARD, key.getSecretKeyType());
- Assert.assertTrue("canEncrypt() should be true", key.canEncrypt());
-
- // cached
- Assert.assertEquals("all subkeys from CachedPublicKeyRing should be divert-to-key",
- SecretKeyType.DIVERT_TO_CARD, cachedRing.getSecretKeyType(key.getKeyId()));
- }
-
- Assert.assertFalse("keyring should have 3 subkeys (4)", it.hasNext());
-
- }
-
- @Test public void testImportBadEncodedUserId() throws Exception {
-
- UncachedKeyRing key = readRingFromResource("/test-keys/bad_user_id_encoding.asc");
- long keyId = key.getMasterKeyId();
-
- SaveKeyringResult result;
-
- result = mProviderHelper.savePublicKeyRing(key, new ProgressScaler());
- Assert.assertTrue("import of keyring should succeed", result.success());
-
- CanonicalizedPublicKeyRing ring = mProviderHelper.getCanonicalizedPublicKeyRing(keyId);
- boolean found = false;
- byte[] badUserId = Hex.decode("436c61757320467261656e6b656c203c436c6175732e4672e46e6b656c4068616c696661782e727774682d61616368656e2e64653e");
- for (byte[] rawUserId : new IterableIterator<byte[]>(
- ring.getUnorderedRawUserIds().iterator())) {
- if (Arrays.equals(rawUserId, badUserId)) {
- found = true;
- }
- }
-
- Assert.assertTrue("import of the badly encoded user id should succeed", found);
- }
-
- @Test
- /** Tests a master key which may sign, but is stripped. In this case, if there is a different
- * subkey available which can sign, that one should be selected.
- */
- public void testImportStrippedFlags() throws Exception {
-
- UncachedKeyRing key = readRingFromResource("/test-keys/stripped_flags.asc");
- long masterKeyId = key.getMasterKeyId();
-
- SaveKeyringResult result;
-
- result = mProviderHelper.saveSecretKeyRing(key, new ProgressScaler());
- Assert.assertTrue("import of keyring should succeed", result.success());
-
- long signId;
- {
- CanonicalizedSecretKeyRing ring = mProviderHelper.getCanonicalizedSecretKeyRing(masterKeyId);
- Assert.assertTrue("master key should have sign flag", ring.getPublicKey().canSign());
- Assert.assertTrue("master key should have encrypt flag", ring.getPublicKey().canEncrypt());
-
- signId = ring.getSecretSignId();
- Assert.assertNotEquals("encrypt id should not be 0", 0, signId);
- Assert.assertNotEquals("encrypt key should be different from master key", masterKeyId, signId);
- }
-
- {
- CachedPublicKeyRing ring = mProviderHelper.getCachedPublicKeyRing(masterKeyId);
- Assert.assertEquals("signing key should be same id cached as uncached", signId, ring.getSecretSignId());
- }
-
- }
-
- UncachedKeyRing readRingFromResource(String name) throws Exception {
- return UncachedKeyRing.fromStream(ProviderHelperSaveTest.class.getResourceAsStream(name)).next();
- }
-
-} \ No newline at end of file
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringBuilder.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringBuilder.java
deleted file mode 100644
index 94193bbcb..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringBuilder.java
+++ /dev/null
@@ -1,254 +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 org.sufficientlysecure.keychain.support;
-
-import org.spongycastle.bcpg.CompressionAlgorithmTags;
-import org.spongycastle.bcpg.ContainedPacket;
-import org.spongycastle.bcpg.HashAlgorithmTags;
-import org.spongycastle.bcpg.MPInteger;
-import org.spongycastle.bcpg.PublicKeyAlgorithmTags;
-import org.spongycastle.bcpg.PublicKeyPacket;
-import org.spongycastle.bcpg.PublicSubkeyPacket;
-import org.spongycastle.bcpg.RSAPublicBCPGKey;
-import org.spongycastle.bcpg.SignaturePacket;
-import org.spongycastle.bcpg.SignatureSubpacket;
-import org.spongycastle.bcpg.SignatureSubpacketInputStream;
-import org.spongycastle.bcpg.SignatureSubpacketTags;
-import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
-import org.spongycastle.bcpg.UserIDPacket;
-import org.spongycastle.bcpg.sig.Features;
-import org.spongycastle.bcpg.sig.IssuerKeyID;
-import org.spongycastle.bcpg.sig.KeyExpirationTime;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.bcpg.sig.PreferredAlgorithms;
-import org.spongycastle.bcpg.sig.SignatureCreationTime;
-import org.spongycastle.openpgp.PGPSignature;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Helps create correct and incorrect keyrings for tests.
- *
- * The original "correct" keyring was generated by GnuPG.
- */
-public class KeyringBuilder {
-
-
- private static final BigInteger PUBLIC_KEY_MODULUS = new BigInteger(
- "cbab78d90d5f2cc0c54dd3c3953005a1e6b521f1ffa5465a102648bf7b91ec72" +
- "f9c180759301587878caeb73332156209f81ca5b3b94309d96110f6972cfc56a" +
- "37fd6279f61d71f19b8f64b288e338299dce133520f5b9b4253e6f4ba31ca36a" +
- "fd87c2081b15f0b283e9350e370e181a23d31379101f17a23ae9192250db6540" +
- "2e9cab2a275bc5867563227b197c8b136c832a94325b680e144ed864fb00b9b8" +
- "b07e13f37b40d5ac27dae63cd6a470a7b40fa3c7479b5b43e634850cc680b177" +
- "8dd6b1b51856f36c3520f258f104db2f96b31a53dd74f708ccfcefccbe420a90" +
- "1c37f1f477a6a4b15f5ecbbfd93311a647bcc3f5f81c59dfe7252e3cd3be6e27"
- , 16
- );
-
- private static final BigInteger PUBLIC_SUBKEY_MODULUS = new BigInteger(
- "e8e2e2a33102649f19f8a07486fb076a1406ca888d72ae05d28f0ef372b5408e" +
- "45132c69f6e5cb6a79bb8aed84634196731393a82d53e0ddd42f28f92cc15850" +
- "8ce3b7ca1a9830502745aee774f86987993df984781f47c4a2910f95cf4c950c" +
- "c4c6cccdc134ad408a0c5418b5e360c9781a8434d366053ea6338b975fae88f9" +
- "383a10a90e7b2caa9ddb95708aa9d8a90246e29b04dbd6136613085c9a287315" +
- "c6e9c7ff4012defc1713875e3ff6073333a1c93d7cd75ebeaaf16b8b853d96ba" +
- "7003258779e8d2f70f1bc0bcd3ef91d7a9ccd8e225579b2d6fcae32799b0a6c0" +
- "e7305fc65dc4edc849c6130a0d669c90c193b1e746c812510f9d600a208be4a5"
- , 16
- );
-
- private static final Date SIGNATURE_DATE = new Date(1404566755000L);
-
- private static final BigInteger EXPONENT = BigInteger.valueOf(0x010001);
-
- private static final String USER_ID_STRING = "OpenKeychain User (NOT A REAL KEY) <openkeychain@example.com>";
-
- public static final BigInteger CORRECT_SIGNATURE = new BigInteger(
- "b065c071d3439d5610eb22e5b4df9e42ed78b8c94f487389e4fc98e8a75a043f" +
- "14bf57d591811e8e7db2d31967022d2ee64372829183ec51d0e20c42d7a1e519" +
- "e9fa22cd9db90f0fd7094fd093b78be2c0db62022193517404d749152c71edc6" +
- "fd48af3416038d8842608ecddebbb11c5823a4321d2029b8993cb017fa8e5ad7" +
- "8a9a618672d0217c4b34002f1a4a7625a514b6a86475e573cb87c64d7069658e" +
- "627f2617874007a28d525e0f87d93ca7b15ad10dbdf10251e542afb8f9b16cbf" +
- "7bebdb5fe7e867325a44e59cad0991cb239b1c859882e2ebb041b80e5cdc3b40" +
- "ed259a8a27d63869754c0881ccdcb50f0564fecdc6966be4a4b87a3507a9d9be"
- , 16
- );
- public static final BigInteger CORRECT_SUBKEY_SIGNATURE = new BigInteger(
- "9c40543e646cfa6d3d1863d91a4e8f1421d0616ddb3187505df75fbbb6c59dd5" +
- "3136b866f246a0320e793cb142c55c8e0e521d1e8d9ab864650f10690f5f1429" +
- "2eb8402a3b1f82c01079d12f5c57c43fce524a530e6f49f6f87d984e26db67a2" +
- "d469386dac87553c50147ebb6c2edd9248325405f737b815253beedaaba4f5c9" +
- "3acd5d07fe6522ceda1027932d849e3ec4d316422cd43ea6e506f643936ab0be" +
- "8246e546bb90d9a83613185047566864ffe894946477e939725171e0e15710b2" +
- "089f78752a9cb572f5907323f1b62f14cb07671aeb02e6d7178f185467624ec5" +
- "74e4a73c439a12edba200a4832106767366a1e6f63da0a42d593fa3914deee2b"
- , 16
- );
- public static final BigInteger KEY_ID = BigInteger.valueOf(0x15130BCF071AE6BFL);
-
- public static UncachedKeyRing correctRing() {
- return convertToKeyring(correctKeyringPackets());
- }
-
- public static UncachedKeyRing ringWithExtraIncorrectSignature() {
- List<ContainedPacket> packets = correctKeyringPackets();
- SignaturePacket incorrectSignaturePacket = createSignaturePacket(CORRECT_SIGNATURE.subtract(BigInteger.ONE));
- packets.add(2, incorrectSignaturePacket);
- return convertToKeyring(packets);
- }
-
- private static UncachedKeyRing convertToKeyring(List<ContainedPacket> packets) {
- try {
- return UncachedKeyRing.decodeFromData(TestDataUtil.concatAll(packets));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private static List<ContainedPacket> correctKeyringPackets() {
- PublicKeyPacket publicKey = createPgpPublicKey(PUBLIC_KEY_MODULUS);
- UserIDPacket userId = createUserId(USER_ID_STRING);
- SignaturePacket signaturePacket = createSignaturePacket(CORRECT_SIGNATURE);
- PublicKeyPacket subKey = createPgpPublicSubKey(PUBLIC_SUBKEY_MODULUS);
- SignaturePacket subKeySignaturePacket = createSubkeySignaturePacket();
-
- return new ArrayList<ContainedPacket>(Arrays.asList(
- publicKey,
- userId,
- signaturePacket,
- subKey,
- subKeySignaturePacket
- ));
- }
-
- private static SignaturePacket createSignaturePacket(BigInteger signature) {
- MPInteger[] signatureArray = new MPInteger[]{
- new MPInteger(signature)
- };
-
- int signatureType = PGPSignature.POSITIVE_CERTIFICATION;
- int keyAlgorithm = SignaturePacket.RSA_GENERAL;
- int hashAlgorithm = HashAlgorithmTags.SHA1;
-
- SignatureSubpacket[] hashedData = new SignatureSubpacket[]{
- new SignatureCreationTime(false, SIGNATURE_DATE),
- new KeyFlags(false, KeyFlags.CERTIFY_OTHER + KeyFlags.SIGN_DATA),
- new KeyExpirationTime(false, TimeUnit.DAYS.toSeconds(2)),
- new PreferredAlgorithms(SignatureSubpacketTags.PREFERRED_SYM_ALGS, false, new int[]{
- SymmetricKeyAlgorithmTags.AES_256,
- SymmetricKeyAlgorithmTags.AES_192,
- SymmetricKeyAlgorithmTags.AES_128,
- SymmetricKeyAlgorithmTags.CAST5,
- SymmetricKeyAlgorithmTags.TRIPLE_DES
- }),
- new PreferredAlgorithms(SignatureSubpacketTags.PREFERRED_HASH_ALGS, false, new int[]{
- HashAlgorithmTags.SHA256,
- HashAlgorithmTags.SHA1,
- HashAlgorithmTags.SHA384,
- HashAlgorithmTags.SHA512,
- HashAlgorithmTags.SHA224
- }),
- new PreferredAlgorithms(SignatureSubpacketTags.PREFERRED_COMP_ALGS, false, new int[]{
- CompressionAlgorithmTags.ZLIB,
- CompressionAlgorithmTags.BZIP2,
- CompressionAlgorithmTags.ZIP
- }),
- new Features(false, Features.FEATURE_MODIFICATION_DETECTION),
- createPreferencesSignatureSubpacket()
- };
- SignatureSubpacket[] unhashedData = new SignatureSubpacket[]{
- new IssuerKeyID(false, KEY_ID.toByteArray())
- };
- byte[] fingerPrint = new BigInteger("522c", 16).toByteArray();
-
- return new SignaturePacket(signatureType,
- KEY_ID.longValue(),
- keyAlgorithm,
- hashAlgorithm,
- hashedData,
- unhashedData,
- fingerPrint,
- signatureArray);
- }
-
- /**
- * There is no Preferences subpacket in BouncyCastle, so we have
- * to create one manually.
- */
- private static SignatureSubpacket createPreferencesSignatureSubpacket() {
- SignatureSubpacket prefs;
- try {
- prefs = new SignatureSubpacketInputStream(new ByteArrayInputStream(
- new byte[]{2, SignatureSubpacketTags.KEY_SERVER_PREFS, (byte) 0x80})
- ).readPacket();
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
- return prefs;
- }
-
- private static SignaturePacket createSubkeySignaturePacket() {
- int signatureType = PGPSignature.SUBKEY_BINDING;
- int keyAlgorithm = SignaturePacket.RSA_GENERAL;
- int hashAlgorithm = HashAlgorithmTags.SHA1;
-
- SignatureSubpacket[] hashedData = new SignatureSubpacket[]{
- new SignatureCreationTime(false, SIGNATURE_DATE),
- new KeyFlags(false, KeyFlags.ENCRYPT_COMMS + KeyFlags.ENCRYPT_STORAGE),
- new KeyExpirationTime(false, TimeUnit.DAYS.toSeconds(2)),
- };
- SignatureSubpacket[] unhashedData = new SignatureSubpacket[]{
- new IssuerKeyID(false, KEY_ID.toByteArray())
- };
- byte[] fingerPrint = new BigInteger("234a", 16).toByteArray();
- MPInteger[] signature = new MPInteger[]{
- new MPInteger(CORRECT_SUBKEY_SIGNATURE)
- };
- return new SignaturePacket(signatureType,
- KEY_ID.longValue(),
- keyAlgorithm,
- hashAlgorithm,
- hashedData,
- unhashedData,
- fingerPrint,
- signature);
- }
-
- private static PublicKeyPacket createPgpPublicKey(BigInteger modulus) {
- return new PublicKeyPacket(PublicKeyAlgorithmTags.RSA_GENERAL, SIGNATURE_DATE, new RSAPublicBCPGKey(modulus, EXPONENT));
- }
-
- private static PublicKeyPacket createPgpPublicSubKey(BigInteger modulus) {
- return new PublicSubkeyPacket(PublicKeyAlgorithmTags.RSA_GENERAL, SIGNATURE_DATE, new RSAPublicBCPGKey(modulus, EXPONENT));
- }
-
- private static UserIDPacket createUserId(String userId) {
- return new UserIDPacket(userId);
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java
deleted file mode 100644
index 4ac994c99..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) Art O Cathain
- * 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.support;
-
-import android.content.Context;
-
-import org.spongycastle.util.Arrays;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
-import org.sufficientlysecure.keychain.util.ProgressScaler;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-
-/** Helper methods for keyring tests. */
-public class KeyringTestingHelper {
-
- private final Context context;
-
- public KeyringTestingHelper(Context robolectricContext) {
- this.context = robolectricContext;
- }
-
- public boolean addKeyring(Collection<String> blobFiles) throws Exception {
-
- ProviderHelper providerHelper = new ProviderHelper(context);
-
- byte[] data = TestDataUtil.readAllFully(blobFiles);
- UncachedKeyRing ring = UncachedKeyRing.decodeFromData(data);
- long masterKeyId = ring.getMasterKeyId();
-
- // Should throw an exception; key is not yet saved
- retrieveKeyAndExpectNotFound(providerHelper, masterKeyId);
-
- SaveKeyringResult saveKeyringResult = providerHelper.savePublicKeyRing(ring, new ProgressScaler());
-
- boolean saveSuccess = saveKeyringResult.success();
-
- // Now re-retrieve the saved key. Should not throw an exception.
- providerHelper.getCanonicalizedPublicKeyRing(masterKeyId);
-
- // A different ID should still fail
- retrieveKeyAndExpectNotFound(providerHelper, masterKeyId - 1);
-
- return saveSuccess;
- }
-
- public static UncachedKeyRing removePacket(UncachedKeyRing ring, int position)
- throws IOException, PgpGeneralException {
- return UncachedKeyRing.decodeFromData(removePacket(ring.getEncoded(), position));
- }
-
- public static byte[] removePacket(byte[] ring, int position) throws IOException {
- Iterator<RawPacket> it = parseKeyring(ring);
- ByteArrayOutputStream out = new ByteArrayOutputStream(ring.length);
-
- int i = 0;
- while(it.hasNext()) {
- // at the right position, skip the packet
- if(i++ == position) {
- it.next();
- continue;
- }
- // write the old one
- out.write(it.next().buf);
- }
-
- if (i <= position) {
- throw new IndexOutOfBoundsException("injection index did not not occur in stream!");
- }
-
- return out.toByteArray();
- }
-
- public static UncachedKeyRing injectPacket(UncachedKeyRing ring, byte[] inject, int position)
- throws IOException, PgpGeneralException {
- return UncachedKeyRing.decodeFromData(injectPacket(ring.getEncoded(), inject, position));
- }
-
- public static byte[] injectPacket(byte[] ring, byte[] inject, int position) throws IOException {
-
- Iterator<RawPacket> it = parseKeyring(ring);
- ByteArrayOutputStream out = new ByteArrayOutputStream(ring.length + inject.length);
-
- int i = 0;
- while(it.hasNext()) {
- // at the right position, inject the new packet
- if(i++ == position) {
- out.write(inject);
- }
- // write the old one
- out.write(it.next().buf);
- }
-
- if (i <= position) {
- throw new IndexOutOfBoundsException("injection index did not not occur in stream!");
- }
-
- return out.toByteArray();
-
- }
-
- /** This class contains a single pgp packet, together with information about its position
- * in the keyring and its packet tag.
- */
- public static class RawPacket {
- public int position;
-
- // packet tag for convenience, this can also be read from the header
- public int tag;
-
- public int headerLength, length;
- // this buf includes the header, so its length is headerLength + length!
- public byte[] buf;
-
- @Override
- public boolean equals(Object other) {
- return other instanceof RawPacket && Arrays.areEqual(this.buf, ((RawPacket) other).buf);
- }
-
- @Override
- public int hashCode() {
- return Arrays.hashCode(buf);
- }
- }
-
- /** A comparator which compares RawPackets by their position */
- public static final Comparator<RawPacket> packetOrder = new Comparator<RawPacket>() {
- public int compare(RawPacket left, RawPacket right) {
- return Integer.compare(left.position, right.position);
- }
- };
-
- /** Diff two keyrings, returning packets only present in one keyring in its associated List.
- *
- * Packets in the returned lists are annotated and ordered by their original order of appearance
- * in their origin keyrings.
- *
- * @return true if keyrings differ in at least one packet
- */
- public static boolean diffKeyrings(byte[] ringA, byte[] ringB,
- List<RawPacket> onlyA, List<RawPacket> onlyB)
- throws IOException {
- Iterator<RawPacket> streamA = parseKeyring(ringA);
- Iterator<RawPacket> streamB = parseKeyring(ringB);
-
- HashSet<RawPacket> a = new HashSet<RawPacket>(), b = new HashSet<RawPacket>();
-
- RawPacket p;
- int pos = 0;
- while(true) {
- p = streamA.next();
- if (p == null) {
- break;
- }
- p.position = pos++;
- a.add(p);
- }
- pos = 0;
- while(true) {
- p = streamB.next();
- if (p == null) {
- break;
- }
- p.position = pos++;
- b.add(p);
- }
-
- onlyA.clear();
- onlyB.clear();
-
- onlyA.addAll(a);
- onlyA.removeAll(b);
- onlyB.addAll(b);
- onlyB.removeAll(a);
-
- Collections.sort(onlyA, packetOrder);
- Collections.sort(onlyB, packetOrder);
-
- return !onlyA.isEmpty() || !onlyB.isEmpty();
- }
-
- /** Creates an iterator of RawPackets over a binary keyring. */
- public static Iterator<RawPacket> parseKeyring(byte[] ring) {
-
- final InputStream stream = new ByteArrayInputStream(ring);
-
- return new Iterator<RawPacket>() {
- RawPacket next;
-
- @Override
- public boolean hasNext() {
- if (next == null) try {
- next = readPacket(stream);
- } catch (IOException e) {
- return false;
- }
- return next != null;
- }
-
- @Override
- public RawPacket next() {
- if (!hasNext()) {
- return null;
- }
- try {
- return next;
- } finally {
- next = null;
- }
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
-
- }
-
- /** Read a single (raw) pgp packet from an input stream.
- *
- * Note that the RawPacket.position field is NOT set here!
- *
- * Variable length packets are not handled here. we don't use those in our test classes, and
- * otherwise rely on BouncyCastle's own unit tests to handle those correctly.
- */
- private static RawPacket readPacket(InputStream in) throws IOException {
-
- // save here. this is tag + length, max 6 bytes
- in.mark(6);
-
- int hdr = in.read();
- int headerLength = 1;
-
- if (hdr < 0) {
- return null;
- }
-
- if ((hdr & 0x80) == 0) {
- throw new IOException("invalid header encountered");
- }
-
- boolean newPacket = (hdr & 0x40) != 0;
- int tag;
- int bodyLen;
-
- if (newPacket) {
- tag = hdr & 0x3f;
-
- int l = in.read();
- headerLength += 1;
-
- if (l < 192) {
- bodyLen = l;
- } else if (l <= 223) {
- int b = in.read();
- headerLength += 1;
-
- bodyLen = ((l - 192) << 8) + (b) + 192;
- } else if (l == 255) {
- bodyLen = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
- headerLength += 4;
- } else {
- // bodyLen = 1 << (l & 0x1f);
- throw new IOException("no support for partial bodies in test classes");
- }
- } else {
- int lengthType = hdr & 0x3;
-
- tag = (hdr & 0x3f) >> 2;
-
- switch (lengthType) {
- case 0:
- bodyLen = in.read();
- headerLength += 1;
- break;
- case 1:
- bodyLen = (in.read() << 8) | in.read();
- headerLength += 2;
- break;
- case 2:
- bodyLen = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
- headerLength += 4;
- break;
- case 3:
- // bodyLen = 1 << (l & 0x1f);
- throw new IOException("no support for partial bodies in test classes");
- default:
- throw new IOException("unknown length type encountered");
- }
- }
-
- in.reset();
-
- // read the entire packet INCLUDING the header here
- byte[] buf = new byte[headerLength+bodyLen];
- if (in.read(buf) != headerLength+bodyLen) {
- throw new IOException("read length mismatch!");
- }
- RawPacket p = new RawPacket();
- p.tag = tag;
- p.headerLength = headerLength;
- p.length = bodyLen;
- p.buf = buf;
- return p;
-
- }
-
- public static <E> E getNth(Iterator<E> it, int position) {
- while(position-- > 0) {
- it.next();
- }
- return it.next();
- }
-
- public static long getSubkeyId(UncachedKeyRing ring, int position) {
- return getNth(ring.getPublicKeys(), position).getKeyId();
- }
-
- private void retrieveKeyAndExpectNotFound(ProviderHelper providerHelper, long masterKeyId) {
- try {
- providerHelper.getCanonicalizedPublicKeyRing(masterKeyId);
- throw new AssertionError("Was expecting the previous call to fail!");
- } catch (ProviderHelper.NotFoundException expectedException) {
- // good
- }
- }
-
- public static <E> List<E> itToList(Iterator<E> it) {
- List<E> result = new ArrayList<E>();
- while(it.hasNext()) {
- result.add(it.next());
- }
- return result;
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/ProviderHelperStub.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/ProviderHelperStub.java
deleted file mode 100644
index 0573f07fb..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/ProviderHelperStub.java
+++ /dev/null
@@ -1,36 +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 org.sufficientlysecure.keychain.support;
-
-import android.content.Context;
-import android.net.Uri;
-
-import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-
-class ProviderHelperStub extends ProviderHelper {
- public ProviderHelperStub(Context context) {
- super(context);
- }
-
- @Override
- public CanonicalizedPublicKeyRing getCanonicalizedPublicKeyRing(Uri id) throws NotFoundException {
- byte[] data = TestDataUtil.readFully(getClass().getResourceAsStream("/public-key-for-sample.blob"));
- return new CanonicalizedPublicKeyRing(data, 0);
- }
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/TestDataUtil.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/TestDataUtil.java
deleted file mode 100644
index f2b3c0996..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/TestDataUtil.java
+++ /dev/null
@@ -1,142 +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 org.sufficientlysecure.keychain.support;
-
-import org.spongycastle.bcpg.ContainedPacket;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collection;
-import java.util.Iterator;
-
-/**
- * Misc support functions. Would just use Guava / Apache Commons but
- * avoiding extra dependencies.
- */
-public class TestDataUtil {
- public static byte[] readFully(InputStream input) {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- appendToOutput(input, output);
- return output.toByteArray();
- }
-
- public static void appendToOutput(InputStream input, OutputStream output) {
- byte[] buffer = new byte[8192];
- int bytesRead;
- try {
- while ((bytesRead = input.read(buffer)) != -1) {
- output.write(buffer, 0, bytesRead);
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- public static byte[] readAllFully(Collection<String> inputResources) {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
-
- for (String inputResource : inputResources) {
- appendToOutput(getResourceAsStream(inputResource), output);
- }
- return output.toByteArray();
- }
-
- public static InputStream getResourceAsStream(String resourceName) {
- return TestDataUtil.class.getResourceAsStream(resourceName);
- }
-
- /**
- * Null-safe equivalent of {@code a.equals(b)}.
- */
- public static boolean equals(Object a, Object b) {
- return (a == null) ? (b == null) : a.equals(b);
- }
-
- public static <T> boolean iterEquals(Iterator<T> a, Iterator<T> b, EqualityChecker<T> comparator) {
- while (a.hasNext()) {
- T aObject = a.next();
- if (!b.hasNext()) {
- return false;
- }
- T bObject = b.next();
- if (!comparator.areEquals(aObject, bObject)) {
- return false;
- }
- }
-
- if (b.hasNext()) {
- return false;
- }
-
- return true;
- }
-
-
- public static <T> boolean iterEquals(Iterator<T> a, Iterator<T> b) {
- return iterEquals(a, b, new EqualityChecker<T>() {
- @Override
- public boolean areEquals(T lhs, T rhs) {
- return TestDataUtil.equals(lhs, rhs);
- }
- });
- }
-
- public static interface EqualityChecker<T> {
- public boolean areEquals(T lhs, T rhs);
- }
-
-
- public static byte[] concatAll(java.util.List<ContainedPacket> packets) {
- byte[][] byteArrays = new byte[packets.size()][];
- try {
- for (int i = 0; i < packets.size(); i++) {
- byteArrays[i] = packets.get(i).getEncoded();
- }
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
-
- return concatAll(byteArrays);
- }
-
- public static byte[] concatAll(byte[]... byteArrays) {
- if (byteArrays.length == 1) {
- return byteArrays[0];
- } else if (byteArrays.length == 2) {
- return concat(byteArrays[0], byteArrays[1]);
- } else {
- byte[] first = concat(byteArrays[0], byteArrays[1]);
- byte[][] remainingArrays = new byte[byteArrays.length - 1][];
- remainingArrays[0] = first;
- System.arraycopy(byteArrays, 2, remainingArrays, 1, byteArrays.length - 2);
- return concatAll(remainingArrays);
- }
- }
-
- private static byte[] concat(byte[] a, byte[] b) {
- int aLen = a.length;
- int bLen = b.length;
- byte[] c = new byte[aLen + bLen];
- System.arraycopy(a, 0, c, 0, aLen);
- System.arraycopy(b, 0, c, aLen, bLen);
- return c;
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/Iso7816TLVTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/Iso7816TLVTest.java
deleted file mode 100644
index fccecc3cc..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/Iso7816TLVTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.util;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.ShadowLog;
-import org.spongycastle.util.encoders.Hex;
-import org.sufficientlysecure.keychain.util.Iso7816TLV.Iso7816CompositeTLV;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class Iso7816TLVTest {
-
- @Before
- public void setUp() throws Exception {
- ShadowLog.stream = System.out;
- }
-
- @Test
- public void testDecode() throws Exception {
-
- // this is an Application Related Data packet, received from my Yubikey
- String input = "6e81dd4f10d27600012401020000000000000100005f520f0073000080000000000000000000007300c00af00000ff04c000ff00ffc106010800001103c206010800001103c306010800001103c407007f7f7f030303c53c1efdb4845ca242ca6977fddb1f788094fd3b430af1114c28a08d8c5afda81191cc50ca9bf51bc99fe8e6ca03a9d4d40e7b5925cd154813df381655b2c63c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd0c5423590e5423590e5423590e9000";
- byte[] data = Hex.decode(input);
-
- Iso7816TLV tlv = Iso7816TLV.readSingle(data, true);
- Assert.assertNotNull("tlv parse must succeed", tlv);
-
- Assert.assertEquals("top packet must be 'application related data' tag", 0x6e, tlv.mT);
- Assert.assertEquals("length must be correct", 221, tlv.mL);
-
- Assert.assertTrue("top packet must be composite", tlv instanceof Iso7816CompositeTLV);
-
- Iso7816CompositeTLV ctlv = (Iso7816CompositeTLV) tlv;
-
- Assert.assertEquals("top packet must have 11 sub packets", 11, ctlv.mSubs.length);
-
- Assert.assertEquals("sub packet #1 must have expected tag", 0x4f, ctlv.mSubs[0].mT);
- Assert.assertEquals("sub packet #1 must have expected length", 16, ctlv.mSubs[0].mL);
-
- Assert.assertEquals("sub packet #2 must have expected tag", 0x5f52, ctlv.mSubs[1].mT);
- Assert.assertEquals("sub packet #2 must have expected length", 15, ctlv.mSubs[1].mL);
-
- Assert.assertEquals("sub packet #3 must have expected tag", 0x73, ctlv.mSubs[2].mT);
- Assert.assertEquals("sub packet #3 must have expected length", 0, ctlv.mSubs[2].mL);
- Assert.assertTrue("sub packet #3 muse be composite", ctlv.mSubs[2] instanceof Iso7816CompositeTLV);
-
- Assert.assertEquals("sub packet #4 must have expected tag", 0xc0, ctlv.mSubs[3].mT);
- Assert.assertEquals("sub packet #4 must have expected length", 10, ctlv.mSubs[3].mL);
-
- Assert.assertEquals("sub packet #5 must have expected tag", 0xc1, ctlv.mSubs[4].mT);
- Assert.assertEquals("sub packet #5 must have expected length", 6, ctlv.mSubs[4].mL);
-
- Assert.assertEquals("sub packet #6 must have expected tag", 0xc2, ctlv.mSubs[5].mT);
- Assert.assertEquals("sub packet #6 must have expected length", 6, ctlv.mSubs[5].mL);
-
- Assert.assertEquals("sub packet #7 must have expected tag", 0xc3, ctlv.mSubs[6].mT);
- Assert.assertEquals("sub packet #7 must have expected length", 6, ctlv.mSubs[6].mL);
-
- Assert.assertEquals("sub packet #8 must have expected tag", 0xc4, ctlv.mSubs[7].mT);
- Assert.assertEquals("sub packet #8 must have expected length", 7, ctlv.mSubs[7].mL);
-
- Assert.assertEquals("sub packet #9 must have expected tag", 0xc5, ctlv.mSubs[8].mT);
- Assert.assertEquals("sub packet #9 must have expected length", 60, ctlv.mSubs[8].mL);
-
- {
- // this is my pubkey fingerprint
- String fingerprint = "1efdb4845ca242ca6977fddb1f788094fd3b430a";
- byte[] V1 = new byte[20];
- System.arraycopy(ctlv.mSubs[8].mV, 0, V1, 0, 20);
- Assert.assertArrayEquals("fingerprint must match", V1, Hex.decode(fingerprint));
- }
-
- Assert.assertEquals("sub packet #10 must have expected tag", 0xc6, ctlv.mSubs[9].mT);
- Assert.assertEquals("sub packet #10 must have expected length", 60, ctlv.mSubs[9].mL);
-
- Assert.assertEquals("sub packet #11 must have expected tag", 0xcd, ctlv.mSubs[10].mT);
- Assert.assertEquals("sub packet #11 must have expected length", 12, ctlv.mSubs[10].mL);
-
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/ParcelableFileCacheTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/ParcelableFileCacheTest.java
deleted file mode 100644
index 7a48d226f..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/ParcelableFileCacheTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- * 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.util;
-
-import android.os.Bundle;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.shadows.ShadowLog;
-import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class ParcelableFileCacheTest {
-
- @Before
- public void setUp() throws Exception {
- ShadowLog.stream = System.out;
- }
-
- @Test
- public void testInputOutput() throws Exception {
-
- ParcelableFileCache<Bundle> cache = new ParcelableFileCache<Bundle>(Robolectric.application, "test.pcl");
-
- ArrayList<Bundle> list = new ArrayList<Bundle>();
-
- for (int i = 0; i < 50; i++) {
- Bundle b = new Bundle();
- b.putInt("key1", i);
- b.putString("key2", Integer.toString(i));
- list.add(b);
- }
-
- // write to cache file
- cache.writeCache(list.size(), list.iterator());
-
- // read back
- IteratorWithSize<Bundle> it = cache.readCache();
-
- Assert.assertEquals("number of entries must be correct", list.size(), it.getSize());
-
- while (it.hasNext()) {
- Bundle b = it.next();
- Assert.assertEquals("input values should be equal to output values",
- b.getInt("key1"), b.getInt("key1"));
- Assert.assertEquals("input values should be equal to output values",
- b.getString("key2"), b.getString("key2"));
- }
-
- }
-
-}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/TestingUtils.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/TestingUtils.java
deleted file mode 100644
index 1d7952464..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/TestingUtils.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.util;
-
-import java.util.Random;
-
-public class TestingUtils {
- public static Passphrase genPassphrase() {
- return genPassphrase(false);
- }
-
- public static Passphrase 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 new Passphrase(passbuilder.toString());
- }
-}