aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2014-07-21 15:11:59 +0200
committerDominik Schürmann <dominik@dominikschuermann.de>2014-07-21 15:11:59 +0200
commit2f5c73746d2ac8a0394995d2f3cd41dae2e80b7a (patch)
tree7fe90c2f2004de54ecd6ce0706d6b2408149c26d
parent976b232946a7777ce746c10d9a727a8722440df4 (diff)
parentf560bc9317357a755b5862c1eec142b7c4665c0a (diff)
downloadopen-keychain-2f5c73746d2ac8a0394995d2f3cd41dae2e80b7a.tar.gz
open-keychain-2f5c73746d2ac8a0394995d2f3cd41dae2e80b7a.tar.bz2
open-keychain-2f5c73746d2ac8a0394995d2f3cd41dae2e80b7a.zip
Merge branch 'master' into yubikey
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml2
-rw-r--r--OpenKeychain-Test/build.gradle38
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java12
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/tests/UncachedKeyringCanonicalizeTest.java213
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/tests/UncachedKeyringTest.java106
-rw-r--r--OpenKeychain/build.gradle1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java2
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml2
-rw-r--r--README.md20
-rw-r--r--build.gradle5
-rwxr-xr-xinstall-custom-gradle-test-plugin.sh15
-rwxr-xr-xprepare-tests.sh30
-rw-r--r--settings.gradle3
17 files changed, 319 insertions, 145 deletions
diff --git a/.gitignore b/.gitignore
index 1dfe84d5a..68f5b5a9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,9 @@ ant.properties
.gradle
build
gradle.properties
+# this is in here because the prepare-tests thing modifies it, and we DON'T
+# want this to be commited. use git add -f to work on this file.
+settings.gradle
#Maven
target
diff --git a/.travis.yml b/.travis.yml
index fd6e55ea7..ef69eb556 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,7 +12,7 @@ before_install:
# Install required Android components.
#- echo "y" | android update sdk -a --filter build-tools-19.1.0,android-19,platform-tools,extra-android-support,extra-android-m2repository --no-ui --force
- ( sleep 5 && while [ 1 ]; do sleep 1; echo y; done ) | android update sdk --no-ui --all --force --filter build-tools-19.1.0,android-19,platform-tools,extra-android-support,extra-android-m2repository
- - ./install-custom-gradle-test-plugin.sh
+ - ./prepare-tests.sh
install: echo "Installation done"
script:
- gradle assemble -S -q
diff --git a/OpenKeychain-Test/build.gradle b/OpenKeychain-Test/build.gradle
index d795ace3d..a98a79dc1 100644
--- a/OpenKeychain-Test/build.gradle
+++ b/OpenKeychain-Test/build.gradle
@@ -1,5 +1,20 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ // need this for com.novoda:gradle-android-test-plugin:0.9.9-SNAPSHOT below (0.9.3 in repos doesn't work!)
+ // run ./install-custom-gradle-test-plugin.sh to pull the thing into the local repository
+ mavenLocal()
+ }
+
+ dependencies {
+ // NOTE: Always use fixed version codes not dynamic ones, e.g. 0.7.3 instead of 0.7.+, see README for more information
+ classpath 'com.novoda:gradle-android-test-plugin:0.9.9-SNAPSHOT'
+ }
+}
+
apply plugin: 'java'
apply plugin: 'android-test'
+apply plugin: 'jacoco'
dependencies {
testCompile 'junit:junit:4.11'
@@ -31,6 +46,29 @@ android {
projectUnderTest ':OpenKeychain'
}
+jacoco {
+ toolVersion = "0.7.0.201403182114"
+}
+
+coverageSourceDirs = [
+ '../OpenKeychain/src/main/java',
+ '../OpenKeychain/src/gen',
+ '../OpenKeychain/build/source/apt/debug',
+ '../OpenKeychain/build/source/generated/buildConfig/debug',
+ '../OpenKeychain/build/source/generated/r/debug'
+ ]
+
+jacocoTestReport {
+ reports {
+ xml.enabled = true
+ html.destination "${buildDir}/jacocoHtml"
+ }
+ // class R is used, but usage will not be covered, so ignore this class from report
+ classDirectories = fileTree(dir: '../OpenKeychain/build/intermediates/classes/debug/org/sufficientlysecure/keychain', exclude: 'R*.class')
+ additionalSourceDirs = files(coverageSourceDirs)
+ executionData = files('build/jacoco/testDebug.exec')
+}
+
// new workaround to force add custom output dirs for android studio
task addTest {
def file = file(project.name + ".iml")
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
index 398b2393e..3fa668e6e 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java
@@ -21,6 +21,7 @@ import android.content.Context;
import org.spongycastle.util.Arrays;
import org.sufficientlysecure.keychain.pgp.NullProgressable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.OperationResults;
@@ -68,6 +69,11 @@ public class KeyringTestingHelper {
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);
@@ -76,6 +82,7 @@ public class KeyringTestingHelper {
while(it.hasNext()) {
// at the right position, skip the packet
if(i++ == position) {
+ it.next();
continue;
}
// write the old one
@@ -89,6 +96,11 @@ public class KeyringTestingHelper {
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);
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/tests/UncachedKeyringCanonicalizeTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/tests/UncachedKeyringCanonicalizeTest.java
new file mode 100644
index 000000000..6f3cf31b5
--- /dev/null
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/tests/UncachedKeyringCanonicalizeTest.java
@@ -0,0 +1,213 @@
+package org.sufficientlysecure.keychain.tests;
+
+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.Packet;
+import org.spongycastle.bcpg.PacketTags;
+import org.spongycastle.bcpg.UserIDPacket;
+import org.spongycastle.bcpg.sig.KeyFlags;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
+import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
+import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
+import org.sufficientlysecure.keychain.pgp.WrappedSignature;
+import org.sufficientlysecure.keychain.service.OperationResultParcel;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
+import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+@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>();
+ OperationResultParcel.OperationLog log = new OperationResultParcel.OperationLog();
+
+ @BeforeClass
+ public static void setUpOnce() throws Exception {
+ ShadowLog.stream = System.out;
+
+ SaveKeyringParcel parcel = new SaveKeyringParcel();
+ parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
+ Constants.choice.algorithm.rsa, 1024, KeyFlags.CERTIFY_OTHER, null));
+ parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
+ Constants.choice.algorithm.rsa, 1024, KeyFlags.SIGN_DATA, null));
+ parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
+ Constants.choice.algorithm.rsa, 1024, KeyFlags.ENCRYPT_COMMS, null));
+
+ parcel.mAddUserIds.add("twi");
+ parcel.mAddUserIds.add("pink");
+ // passphrase is tested in PgpKeyOperationTest, just use empty here
+ parcel.mNewPassphrase = "";
+ PgpKeyOperation op = new PgpKeyOperation(null);
+
+ OperationResultParcel.OperationLog log = new OperationResultParcel.OperationLog();
+ staticRing = op.createSecretKeyRing(parcel, log, 0);
+
+ Assert.assertNotNull("initial test key creation must succeed", staticRing);
+
+ // just for later reference
+ totalPackets = 9;
+
+ // 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;
+ }
+
+ @Test public void testGeneratedRingStructure() throws Exception {
+
+ Iterator<RawPacket> it = KeyringTestingHelper.parseKeyring(ring.getEncoded());
+
+ Assert.assertEquals("packet #1 should be secret key",
+ PacketTags.SECRET_KEY, it.next().tag);
+
+ Assert.assertEquals("packet #2 should be user id",
+ PacketTags.USER_ID, it.next().tag);
+ Assert.assertEquals("packet #3 should be signature",
+ PacketTags.SIGNATURE, it.next().tag);
+
+ Assert.assertEquals("packet #4 should be user id",
+ PacketTags.USER_ID, it.next().tag);
+ Assert.assertEquals("packet #5 should be signature",
+ PacketTags.SIGNATURE, it.next().tag);
+
+ Assert.assertEquals("packet #6 should be secret subkey",
+ PacketTags.SECRET_SUBKEY, it.next().tag);
+ Assert.assertEquals("packet #7 should be signature",
+ PacketTags.SIGNATURE, it.next().tag);
+
+ Assert.assertEquals("packet #8 should be secret subkey",
+ PacketTags.SECRET_SUBKEY, it.next().tag);
+ Assert.assertEquals("packet #9 should be signature",
+ PacketTags.SIGNATURE, it.next().tag);
+
+ Assert.assertFalse("exactly 9 packets total", it.hasNext());
+
+ Assert.assertArrayEquals("created keyring should be constant through canonicalization",
+ ring.getEncoded(), ring.canonicalize(log, 0).getEncoded());
+
+ }
+
+ @Test public void testBrokenSignature() throws Exception {
+
+ byte[] brokenSig;
+ {
+ UncachedPublicKey masterKey = ring.getPublicKey();
+ WrappedSignature sig = masterKey.getSignaturesForId("twi").next();
+ brokenSig = sig.getEncoded();
+ // break the signature
+ brokenSig[brokenSig.length - 5] += 1;
+ }
+
+ byte[] reng = ring.getEncoded();
+ for(int i = 0; i < totalPackets; i++) {
+
+ byte[] brokenBytes = KeyringTestingHelper.injectPacket(reng, brokenSig, i);
+ Assert.assertEquals("broken ring must be original + injected size",
+ reng.length + brokenSig.length, brokenBytes.length);
+
+ try {
+ UncachedKeyRing brokenRing = UncachedKeyRing.decodeFromData(brokenBytes);
+
+ brokenRing = brokenRing.canonicalize(log, 0);
+ if (brokenRing == null) {
+ System.out.println("ok, canonicalization failed.");
+ continue;
+ }
+
+ Assert.assertArrayEquals("injected bad signature must be gone after canonicalization",
+ ring.getEncoded(), brokenRing.getEncoded());
+
+ } catch (Exception e) {
+ System.out.println("ok, rejected with: " + e.getMessage());
+ }
+ }
+
+ }
+
+ @Test public void testUidSignature() throws Exception {
+
+ UncachedPublicKey masterKey = ring.getPublicKey();
+ final WrappedSignature sig = masterKey.getSignaturesForId("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);
+ modified = modified.canonicalize(log, 0);
+
+ Assert.assertTrue("canonicalized keyring with invalid extra sig must be same as original one",
+ !KeyringTestingHelper.diffKeyrings(
+ ring.getEncoded(), modified.getEncoded(), onlyA, onlyB));
+ }
+
+ // remove user id certificate for one user
+ final UncachedKeyRing base = KeyringTestingHelper.removePacket(ring, 2);
+
+ { // user id without certificate should be removed
+ UncachedKeyRing 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;
+ 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());
+
+ p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(1).buf)).readPacket();
+ 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);
+ modified = modified.canonicalize(log, 0);
+
+ Assert.assertTrue("canonicalized keyring must differ", KeyringTestingHelper.diffKeyrings(
+ ring.getEncoded(), modified.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;
+ 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());
+
+ p = new BCPGInputStream(new ByteArrayInputStream(onlyA.get(1).buf)).readPacket();
+ Assert.assertArrayEquals("second stripped packet must be signature we removed",
+ sig.getEncoded(), onlyA.get(1).buf);
+ }
+
+ }
+
+}
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/tests/UncachedKeyringTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/tests/UncachedKeyringTest.java
deleted file mode 100644
index 66e31c272..000000000
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/tests/UncachedKeyringTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.sufficientlysecure.keychain.tests;
-
-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.Packet;
-import org.spongycastle.bcpg.PacketTags;
-import org.spongycastle.bcpg.UserIDPacket;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
-import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
-import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
-import org.sufficientlysecure.keychain.pgp.WrappedSignature;
-import org.sufficientlysecure.keychain.service.OperationResultParcel;
-import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
-import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
-
-import java.io.ByteArrayInputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-@RunWith(RobolectricTestRunner.class)
-@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
-public class UncachedKeyringTest {
-
- static UncachedKeyRing staticRing;
- UncachedKeyRing ring;
- ArrayList<RawPacket> onlyA = new ArrayList<RawPacket>();
- ArrayList<RawPacket> onlyB = new ArrayList<RawPacket>();
- OperationResultParcel.OperationLog log = new OperationResultParcel.OperationLog();
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- ShadowLog.stream = System.out;
-
- SaveKeyringParcel parcel = new SaveKeyringParcel();
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Constants.choice.algorithm.rsa, 1024, KeyFlags.CERTIFY_OTHER, null));
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Constants.choice.algorithm.rsa, 1024, KeyFlags.SIGN_DATA, null));
- parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
- Constants.choice.algorithm.rsa, 1024, KeyFlags.ENCRYPT_COMMS, null));
-
- parcel.mAddUserIds.add("twi");
- parcel.mAddUserIds.add("pink");
- // passphrase is tested in PgpKeyOperationTest, just use empty here
- parcel.mNewPassphrase = "";
- PgpKeyOperation op = new PgpKeyOperation(null);
-
- OperationResultParcel.OperationLog log = new OperationResultParcel.OperationLog();
- staticRing = op.createSecretKeyRing(parcel, log, 0);
-
- 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;
- }
-
- @Test public void testGeneratedRingStructure() throws Exception {
-
- Iterator<RawPacket> it = KeyringTestingHelper.parseKeyring(ring.getEncoded());
-
- Assert.assertEquals("packet #1 should be secret key",
- PacketTags.SECRET_KEY, it.next().tag);
-
- Assert.assertEquals("packet #2 should be secret key",
- PacketTags.USER_ID, it.next().tag);
- Assert.assertEquals("packet #3 should be secret key",
- PacketTags.SIGNATURE, it.next().tag);
-
- Assert.assertEquals("packet #4 should be secret key",
- PacketTags.USER_ID, it.next().tag);
- Assert.assertEquals("packet #5 should be secret key",
- PacketTags.SIGNATURE, it.next().tag);
-
- Assert.assertEquals("packet #6 should be secret key",
- PacketTags.SECRET_SUBKEY, it.next().tag);
- Assert.assertEquals("packet #7 should be secret key",
- PacketTags.SIGNATURE, it.next().tag);
-
- Assert.assertEquals("packet #8 should be secret key",
- PacketTags.SECRET_SUBKEY, it.next().tag);
- Assert.assertEquals("packet #9 should be secret key",
- PacketTags.SIGNATURE, it.next().tag);
-
- Assert.assertFalse("exactly 9 packets total", it.hasNext());
-
- Assert.assertArrayEquals("created keyring should be constant through canonicalization",
- ring.getEncoded(), ring.canonicalize(log, 0).getEncoded());
-
- }
-
-}
diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle
index c4c8156cd..aa1932c56 100644
--- a/OpenKeychain/build.gradle
+++ b/OpenKeychain/build.gradle
@@ -1,5 +1,4 @@
apply plugin: 'android'
-apply plugin: 'robolectric'
dependencies {
// NOTE: Always use fixed version codes not dynamic ones, e.g. 0.7.3 instead of 0.7.+, see README for more information
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
index bd8a9201e..00f73a5b0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -599,6 +599,7 @@ public class PgpKeyOperation {
log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_ENCODE, indent+1);
return null;
} catch (PGPException e) {
+ Log.e(Constants.TAG, "encountered pgp error while modifying key", e);
log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_PGP, indent+1);
return null;
} catch (SignatureException e) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
index a89cb6bfa..5dc3c598e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
@@ -232,7 +232,7 @@ public class UncachedKeyRing {
PGPPublicKey modified = masterKey;
PGPSignature revocation = null;
- for (PGPSignature zert : new IterableIterator<PGPSignature>(masterKey.getSignatures())) {
+ for (PGPSignature zert : new IterableIterator<PGPSignature>(masterKey.getKeySignatures())) {
int type = zert.getSignatureType();
// Disregard certifications on user ids, we will deal with those later
@@ -241,6 +241,10 @@ public class UncachedKeyRing {
|| type == PGPSignature.CASUAL_CERTIFICATION
|| type == PGPSignature.POSITIVE_CERTIFICATION
|| type == PGPSignature.CERTIFICATION_REVOCATION) {
+ // These should not be here...
+ log.add(LogLevel.WARN, LogType.MSG_KC_REVOKE_BAD_TYPE_UID, indent);
+ modified = PGPPublicKey.removeCertification(modified, zert);
+ badCerts += 1;
continue;
}
WrappedSignature cert = new WrappedSignature(zert);
@@ -432,7 +436,7 @@ public class UncachedKeyRing {
// If no valid certificate (if only a revocation) remains, drop it
if (selfCert == null && revocation == null) {
modified = PGPPublicKey.removeCertification(modified, userId);
- log.add(LogLevel.ERROR, LogType.MSG_KC_UID_REVOKE_DUP,
+ log.add(LogLevel.ERROR, LogType.MSG_KC_UID_REMOVE,
indent, userId);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
index ef5aa8e86..358b1c552 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
@@ -1,8 +1,6 @@
package org.sufficientlysecure.keychain.pgp;
-import org.spongycastle.bcpg.SignatureSubpacketTags;
import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
@@ -11,7 +9,6 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
-import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
index 705d6afaf..89d534df6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
@@ -202,6 +202,7 @@ public class OperationResultParcel implements Parcelable {
MSG_KC_REVOKE_BAD_LOCAL (R.string.msg_kc_revoke_bad_local),
MSG_KC_REVOKE_BAD_TIME (R.string.msg_kc_revoke_bad_time),
MSG_KC_REVOKE_BAD_TYPE (R.string.msg_kc_revoke_bad_type),
+ MSG_KC_REVOKE_BAD_TYPE_UID (R.string.msg_kc_revoke_bad_type_uid),
MSG_KC_REVOKE_BAD (R.string.msg_kc_revoke_bad),
MSG_KC_REVOKE_DUP (R.string.msg_kc_revoke_dup),
MSG_KC_SUB (R.string.msg_kc_sub),
@@ -233,6 +234,7 @@ public class OperationResultParcel implements Parcelable {
MSG_KC_UID_NO_CERT (R.string.msg_kc_uid_no_cert),
MSG_KC_UID_REVOKE_DUP (R.string.msg_kc_uid_revoke_dup),
MSG_KC_UID_REVOKE_OLD (R.string.msg_kc_uid_revoke_old),
+ MSG_KC_UID_REMOVE (R.string.msg_kc_uid_remove),
// keyring consolidation
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index c1c18effe..55ecf3ae0 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -592,6 +592,7 @@
<string name="msg_kc_revoke_bad_local">Removing keyring revocation certificate with "local" flag</string>
<string name="msg_kc_revoke_bad_time">Removing keyring revocation certificate with future timestamp</string>
<string name="msg_kc_revoke_bad_type">Removing master key certificate of unknown type (%s)</string>
+ <string name="msg_kc_revoke_bad_type_uid">Removing user id certification in bad position</string>
<string name="msg_kc_revoke_bad">Removing bad keyring revocation certificate</string>
<string name="msg_kc_revoke_dup">Removing redundant keyring revocation certificate</string>
<string name="msg_kc_sub">Processing subkey %s</string>
@@ -629,6 +630,7 @@
<string name="msg_kc_uid_revoke_dup">Removing redundant revocation certificate for user id "%s"</string>
<string name="msg_kc_uid_revoke_old">Removing outdated revocation certificate for user id "%s"</string>
<string name="msg_kc_uid_no_cert">No valid self-certificate found for user id %s, removing from ring</string>
+ <string name="msg_kc_uid_remove">Removing invalid user id %s</string>
<!-- Keyring merging log entries -->
<string name="msg_mg_public">Merging into public keyring %s</string>
diff --git a/README.md b/README.md
index 4a2fad2ee..230fd2d6f 100644
--- a/README.md
+++ b/README.md
@@ -37,10 +37,13 @@ Expand the Tools directory and select "Android SDK Build-tools (Version 19.1)".
Expand the Extras directory and install "Android Support Repository"
Select everything for the newest SDK Platform (API-Level 19)
4. Export ANDROID_HOME pointing to your Android SDK
-5. Use OpenJDK 7 instead of Oracle JDK (this is required for OpenKeychain's tests based on Bouncy Castle)
-6. Execute ``./install-custom-gradle-test-plugin.sh``
-7. Execute ``./gradlew build``
-8. You can install the app with ``adb install -r OpenKeychain/build/outputs/apk/OpenKeychain-debug-unaligned.apk``
+5. Execute ``./gradlew build``
+6. You can install the app with ``adb install -r OpenKeychain/build/outputs/apk/OpenKeychain-debug-unaligned.apk``
+
+### Run Tests
+1. Use OpenJDK instead of Oracle JDK
+2. Execute ``./prepare-tests.sh``
+3. Execute ``./gradlew build``
### Build API Demo with Gradle
@@ -50,13 +53,10 @@ Select everything for the newest SDK Platform (API-Level 19)
### Development with Android Studio
-I am using the newest [Android Studio](http://developer.android.com/sdk/installing/studio.html) for development. Development with Eclipse is currently not possible because I am using the new [project structure](http://developer.android.com/sdk/installing/studio-tips.html).
+We are using the newest [Android Studio](http://developer.android.com/sdk/installing/studio.html) for development. Development with Eclipse is currently not possible because we are using the new [project structure](http://developer.android.com/sdk/installing/studio-tips.html).
-1. Clone the project from github
-2. From Android Studio: File -> Import Project -> ...
- * Select the cloned top folder if you want to develop on the main project
- * Select the "OpenKeychain-API" folder if you want to develop on the API example
-3. Import project from external model -> choose Gradle
+1. Clone the project from Github
+2. From Android Studio: File -> Import Project -> Select the cloned top folder
## OpenKeychain's API
diff --git a/build.gradle b/build.gradle
index 698b4cd37..05e90eb17 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,16 +1,11 @@
buildscript {
repositories {
mavenCentral()
- // need this for com.novoda:gradle-android-test-plugin:0.9.9-SNAPSHOT below (0.9.3 in repos doesn't work!)
- // run ./install-custom-gradle-test-plugin.sh to pull the thing into the local repository
- mavenLocal()
}
dependencies {
// NOTE: Always use fixed version codes not dynamic ones, e.g. 0.7.3 instead of 0.7.+, see README for more information
classpath 'com.android.tools.build:gradle:0.12.0'
- classpath 'org.robolectric:robolectric-gradle-plugin:0.11.0'
- classpath 'com.novoda:gradle-android-test-plugin:0.9.9-SNAPSHOT'
}
}
diff --git a/install-custom-gradle-test-plugin.sh b/install-custom-gradle-test-plugin.sh
deleted file mode 100755
index 85c13d959..000000000
--- a/install-custom-gradle-test-plugin.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-mkdir temp
-cd temp
-
- git clone https://github.com/nenick/gradle-android-test-plugin.git
- cd gradle-android-test-plugin
-
- echo "rootProject.name = 'gradle-android-test-plugin-parent'" > settings.gradle
- echo "include ':gradle-android-test-plugin'" >> settings.gradle
-
- ./gradlew :gradle-android-test-plugin:install
-
- cd ..
-cd .. \ No newline at end of file
diff --git a/prepare-tests.sh b/prepare-tests.sh
new file mode 100755
index 000000000..027c76f84
--- /dev/null
+++ b/prepare-tests.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This script installs a plugin which is necessary to run OpenKeychain's tests
+# into the local maven repository, then puts a line to include the -Test
+# subproject into settings.gradle
+
+echo "checking jdk runtime.."
+if ! java -version 2>&1 | grep OpenJDK; then
+ echo "tests will only run on openjdk, see readme for details!" >&2
+ return
+fi
+
+tmpdir="$(mktemp -d)"
+(
+ cd "$tmpdir";
+ git clone https://github.com/nenick/gradle-android-test-plugin.git
+ cd gradle-android-test-plugin
+ echo "rootProject.name = 'gradle-android-test-plugin-parent'" > settings.gradle
+ echo "include ':gradle-android-test-plugin'" >> settings.gradle
+ ./gradlew :gradle-android-test-plugin:install
+)
+rm -rf "$tmpdir"
+
+echo -n "ok, adding tests to include list.. "
+if grep OpenKeychain-Test settings.gradle >/dev/null ; then
+ echo " already in."
+else
+ echo "include ':OpenKeychain-Test'" >> settings.gradle
+ echo "ok"
+fi
diff --git a/settings.gradle b/settings.gradle
index d0b2b9954..e134c52a8 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,5 +1,4 @@
include ':OpenKeychain'
-include ':OpenKeychain-Test'
include ':extern:openpgp-api-lib'
include ':extern:openkeychain-api-lib'
include ':extern:html-textview'
@@ -14,4 +13,4 @@ include ':extern:AppMsg:library'
include ':extern:SuperToasts:supertoasts'
include ':extern:minidns'
include ':extern:KeybaseLib:Lib'
-include ':extern:openpgp-card-nfc-lib:library' \ No newline at end of file
+include ':extern:openpgp-card-nfc-lib:library'