aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain-Test/src/test/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain-Test/src/test/java/org')
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java126
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java121
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java108
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java7
4 files changed, 311 insertions, 51 deletions
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
new file mode 100644
index 000000000..40ade064b
--- /dev/null
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.PromoteKeyResult;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
+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.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 String 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());
+
+ 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 divert-to-card",
+ SecretKeyType.GNU_DUMMY, ring.getSecretKeyType(keyId));
+ }
+ }
+
+ // second attempt should fail
+ result = op.execute(mStaticRing.getMasterKeyId());
+ Assert.assertFalse("promotion of secret key must fail", result.success());
+
+ }
+
+}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
index 008edcda4..d782230c7 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
@@ -22,6 +22,7 @@ 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;
@@ -29,13 +30,12 @@ import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
-import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt.Builder;
+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.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
import org.sufficientlysecure.keychain.util.InputData;
@@ -131,15 +131,17 @@ public class PgpEncryptDecryptTest {
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());
- Builder b = new PgpSignEncrypt.Builder(Robolectric.application,
- new ProviderHelper(Robolectric.application),
- null,
- data, out);
+ PgpSignEncryptInput b = new PgpSignEncryptInput();
b.setSymmetricPassphrase(mPassphrase);
b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
- SignEncryptResult result = b.build().execute();
+
+ PgpSignEncryptResult result = op.execute(b, data, out);
+
Assert.assertTrue("encryption must succeed", result.success());
ciphertext = out.toByteArray();
@@ -161,6 +163,10 @@ public class PgpEncryptDecryptTest {
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
@@ -210,16 +216,15 @@ public class PgpEncryptDecryptTest {
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());
- Builder b = new PgpSignEncrypt.Builder(
- Robolectric.application,
- new ProviderHelper(Robolectric.application),
- null, // new DummyPassphraseCache(mPassphrase, 0L),
- data, out);
+ PgpSignEncryptInput b = new PgpSignEncryptInput();
b.setEncryptionMasterKeyIds(new long[]{ mStaticRing1.getMasterKeyId() });
b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
- SignEncryptResult result = b.build().execute();
+ PgpSignEncryptResult result = op.execute(b, data, out);
Assert.assertTrue("encryption must succeed", result.success());
ciphertext = out.toByteArray();
@@ -239,6 +244,11 @@ public class PgpEncryptDecryptTest {
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());
+
}
// TODO how to test passphrase cache?
@@ -286,19 +296,19 @@ public class PgpEncryptDecryptTest {
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());
- Builder b = new PgpSignEncrypt.Builder(
- Robolectric.application,
- new ProviderHelper(Robolectric.application),
- null, // new DummyPassphraseCache(mPassphrase, 0L),
- data, out);
+ PgpSignEncryptInput b = new PgpSignEncryptInput();
b.setEncryptionMasterKeyIds(new long[] {
mStaticRing1.getMasterKeyId(),
mStaticRing2.getMasterKeyId()
});
b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
- SignEncryptResult result = b.build().execute();
+
+ PgpSignEncryptResult result = op.execute(b, data, out);
Assert.assertTrue("encryption must succeed", result.success());
ciphertext = out.toByteArray();
@@ -318,6 +328,10 @@ public class PgpEncryptDecryptTest {
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 with passphrase cached should succeed for the first key
@@ -375,12 +389,11 @@ public class PgpEncryptDecryptTest {
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());
- Builder b = new PgpSignEncrypt.Builder(
- Robolectric.application,
- new ProviderHelper(Robolectric.application),
- null, // new DummyPassphraseCache(mPassphrase, 0L),
- data, out);
+ PgpSignEncryptInput b = new PgpSignEncryptInput();
b.setEncryptionMasterKeyIds(new long[] {
mStaticRing1.getMasterKeyId(),
@@ -390,7 +403,8 @@ public class PgpEncryptDecryptTest {
b.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1));
b.setSignaturePassphrase(mKeyPhrase1);
b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128);
- SignEncryptResult result = b.build().execute();
+
+ PgpSignEncryptResult result = op.execute(b, data, out);
Assert.assertTrue("encryption must succeed", result.success());
ciphertext = out.toByteArray();
@@ -411,6 +425,10 @@ public class PgpEncryptDecryptTest {
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
@@ -438,6 +456,59 @@ public class PgpEncryptDecryptTest {
}
+ @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());
+ PgpSignEncryptInput b = new PgpSignEncryptInput();
+
+ 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, 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.Builder b = builderWithFakePassphraseCache(data, out, null, null, null);
+ b.setPassphrase(mKeyPhrase1);
+ DecryptVerifyResult result = b.build().execute();
+ 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.Builder builderWithFakePassphraseCache (
InputData data, OutputStream out,
final String passphrase, final Long checkMasterKeyId, final Long checkSubKeyId) {
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
index 3ea88aac6..dd2feb825 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java
@@ -231,7 +231,7 @@ public class PgpKeyOperationTest {
ring.getPublicKey().getCreationTime().after(new Date(new Date().getTime()-1000*120)));
Assert.assertNull("key ring should not expire",
- ring.getPublicKey().getExpiryTime());
+ ring.getPublicKey().getUnsafeExpiryTimeForTesting());
Assert.assertEquals("first (master) key can certify",
KeyFlags.CERTIFY_OTHER, (long) subkeys.get(0).getKeyUsage());
@@ -342,9 +342,9 @@ public class PgpKeyOperationTest {
Assert.assertNotNull("new key is not null", newKey);
Assert.assertNotNull("added key must have an expiry date",
- newKey.getExpiryTime());
+ newKey.getUnsafeExpiryTimeForTesting());
Assert.assertEquals("added key must have expected expiry date",
- expiry, newKey.getExpiryTime().getTime()/1000);
+ 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",
@@ -403,9 +403,9 @@ public class PgpKeyOperationTest {
ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
Assert.assertNotNull("modified key must have an expiry date",
- modified.getPublicKey(keyId).getExpiryTime());
+ modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
Assert.assertEquals("modified key must have expected expiry date",
- expiry, modified.getPublicKey(keyId).getExpiryTime().getTime()/1000);
+ 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());
}
@@ -417,9 +417,9 @@ public class PgpKeyOperationTest {
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
Assert.assertNotNull("modified key must have an expiry date",
- modified.getPublicKey(keyId).getExpiryTime());
+ modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
Assert.assertEquals("modified key must have expected expiry date",
- expiry, modified.getPublicKey(keyId).getExpiryTime().getTime()/1000);
+ 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());
}
@@ -443,9 +443,9 @@ public class PgpKeyOperationTest {
Assert.assertEquals("modified key must have expected flags",
flags, (long) modified.getPublicKey(keyId).getKeyUsage());
Assert.assertNotNull("key must retain its expiry",
- modified.getPublicKey(keyId).getExpiryTime());
+ modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
Assert.assertEquals("key expiry must be unchanged",
- expiry, modified.getPublicKey(keyId).getExpiryTime().getTime()/1000);
+ expiry, modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting().getTime()/1000);
}
{ // expiry of 0 should be "no expiry"
@@ -463,7 +463,7 @@ public class PgpKeyOperationTest {
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).getExpiryTime());
+ Assert.assertNull("key must not expire anymore", modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
}
{ // a past expiry should fail
@@ -517,9 +517,9 @@ public class PgpKeyOperationTest {
PacketTags.SIGNATURE, onlyB.get(1).tag);
Assert.assertNotNull("modified key must have an expiry date",
- modified.getPublicKey().getExpiryTime());
+ modified.getPublicKey().getUnsafeExpiryTimeForTesting());
Assert.assertEquals("modified key must have expected expiry date",
- expiry, modified.getPublicKey().getExpiryTime().getTime() / 1000);
+ expiry, modified.getPublicKey().getUnsafeExpiryTimeForTesting().getTime() / 1000);
Assert.assertEquals("modified key must have same flags as before",
ring.getPublicKey().getKeyUsage(), modified.getPublicKey().getKeyUsage());
}
@@ -531,9 +531,9 @@ public class PgpKeyOperationTest {
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
Assert.assertNotNull("modified key must have an expiry date",
- modified.getPublicKey(keyId).getExpiryTime());
+ modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
Assert.assertEquals("modified key must have expected expiry date",
- expiry, modified.getPublicKey(keyId).getExpiryTime().getTime()/1000);
+ 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());
}
@@ -547,17 +547,29 @@ public class PgpKeyOperationTest {
Assert.assertEquals("modified key must have expected flags",
flags, (long) modified.getPublicKey(keyId).getKeyUsage());
Assert.assertNotNull("key must retain its expiry",
- modified.getPublicKey(keyId).getExpiryTime());
+ modified.getPublicKey(keyId).getUnsafeExpiryTimeForTesting());
Assert.assertEquals("key expiry must be unchanged",
- expiry, modified.getPublicKey(keyId).getExpiryTime().getTime()/1000);
+ 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);
- Assert.assertNull("key must not expire anymore", modified.getPublicKey(keyId).getExpiryTime());
+ // 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...
@@ -609,7 +621,7 @@ public class PgpKeyOperationTest {
ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
Assert.assertTrue("subkey must actually be revoked",
- modified.getPublicKey().isRevoked());
+ modified.getPublicKey().isMaybeRevoked());
}
@@ -653,13 +665,14 @@ public class PgpKeyOperationTest {
ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
Assert.assertTrue("subkey must actually be revoked",
- modified.getPublicKey(keyId).isRevoked());
+ modified.getPublicKey(keyId).isMaybeRevoked());
}
{ // re-add second subkey
parcel.reset();
- parcel.mChangeSubKeys.add(new SubkeyChange(keyId, null, null));
+ // re-certify the revoked subkey
+ parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true));
modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB);
@@ -690,7 +703,7 @@ public class PgpKeyOperationTest {
ring.getMasterKeyId(), ((SignaturePacket) p).getKeyID());
Assert.assertFalse("subkey must no longer be revoked",
- modified.getPublicKey(keyId).isRevoked());
+ modified.getPublicKey(keyId).isMaybeRevoked());
Assert.assertEquals("subkey must have the same usage flags as before",
flags, (long) modified.getPublicKey(keyId).getKeyUsage());
@@ -701,7 +714,7 @@ public class PgpKeyOperationTest {
public void testSubkeyStrip() throws Exception {
long keyId = KeyringTestingHelper.getSubkeyId(ring, 1);
- parcel.mStripSubKeys.add(keyId);
+ parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null));
applyModificationWithChecks(parcel, ring, onlyA, onlyB);
Assert.assertEquals("one extra packet in original", 1, onlyA.size());
@@ -727,7 +740,7 @@ public class PgpKeyOperationTest {
public void testMasterStrip() throws Exception {
long keyId = ring.getMasterKeyId();
- parcel.mStripSubKeys.add(keyId);
+ parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null));
applyModificationWithChecks(parcel, ring, onlyA, onlyB);
Assert.assertEquals("one extra packet in original", 1, onlyA.size());
@@ -746,6 +759,44 @@ public class PgpKeyOperationTest {
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/divert status of subkeys without passphrase
+ parcel.reset();
+ parcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null));
+ modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, null);
+ 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());
+ }
+
+ { // and again, changing to divert-to-card
+ parcel.reset();
+ byte[] serial = new byte[] {
+ 0x6a, 0x6f, 0x6c, 0x6f, 0x73, 0x77, 0x61, 0x67,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ parcel.mChangeSubKeys.add(new SubkeyChange(keyId, false, serial));
+ modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB, null);
+ 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());
+
+ }
}
@@ -1092,6 +1143,17 @@ public class PgpKeyOperationTest {
}
+ @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, parcel, null);
+ Assert.assertFalse("non-restricted operations should fail without passphrase", result.success());
+ }
+
private static UncachedKeyRing applyModificationWithChecks(SaveKeyringParcel parcel,
UncachedKeyRing ring,
ArrayList<RawPacket> onlyA,
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
index e4a1d62ae..171ecc377 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java
@@ -106,8 +106,8 @@ public class ProviderHelperSaveTest {
UncachedKeyRing pub = readRingFromResource("/test-keys/mailvelope_07_no_key_flags.asc");
long keyId = pub.getMasterKeyId();
- Assert.assertNull("key flags should be null",
- pub.canonicalize(new OperationLog(), 0).getPublicKey().getKeyUsage());
+ Assert.assertEquals("key flags should be zero",
+ 0, (long) pub.canonicalize(new OperationLog(), 0).getPublicKey().getKeyUsage());
mProviderHelper.savePublicKeyRing(pub);
@@ -117,7 +117,8 @@ public class ProviderHelperSaveTest {
Assert.assertEquals("master key should be encryption key", keyId, pubRing.getEncryptId());
Assert.assertEquals("master key should be encryption key (cached)", keyId, cachedRing.getEncryptId());
- Assert.assertNull("canonicalized key flags should be null", pubRing.getPublicKey().getKeyUsage());
+ 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());