ditch keybase

This commit is contained in:
Vincent Breitmoser 2019-11-15 11:47:46 +01:00
parent 5e0a17b966
commit d3e48db520
35 changed files with 41 additions and 1344 deletions

4
.gitmodules vendored
View File

@ -2,10 +2,6 @@
path = extern/openpgp-api-lib
url = https://github.com/open-keychain/openpgp-api.git
ignore = dirty
[submodule "extern/KeybaseLib"]
path = extern/KeybaseLib
url = https://github.com/open-keychain/KeybaseLib.git
ignore = dirty
[submodule "extern/minidns"]
path = extern/minidns
url = https://github.com/open-keychain/minidns.git

View File

@ -61,7 +61,6 @@ dependencies {
implementation project(':extern:bouncycastle:pg')
implementation project(':extern:bouncycastle:prov')
implementation project(':extern:minidns')
implementation project(':KeybaseLib')
implementation project(':extern:MaterialChipsInput')
implementation "android.arch.work:work-runtime:1.0.0-alpha02"

View File

@ -1,38 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIGmzCCBIOgAwIBAgIJAPzhpcIBaOeNMA0GCSqGSIb3DQEBBQUAMIGPMQswCQYD
VQQGEwJVUzELMAkGA1UECBMCTlkxETAPBgNVBAcTCE5ldyBZb3JrMRQwEgYDVQQK
EwtLZXliYXNlIExMQzEXMBUGA1UECxMOQ2VydCBBdXRob3JpdHkxEzARBgNVBAMT
CmtleWJhc2UuaW8xHDAaBgkqhkiG9w0BCQEWDWNhQGtleWJhc2UuaW8wHhcNMTQw
MTAyMTY0MjMzWhcNMjMxMjMxMTY0MjMzWjCBjzELMAkGA1UEBhMCVVMxCzAJBgNV
BAgTAk5ZMREwDwYDVQQHEwhOZXcgWW9yazEUMBIGA1UEChMLS2V5YmFzZSBMTEMx
FzAVBgNVBAsTDkNlcnQgQXV0aG9yaXR5MRMwEQYDVQQDEwprZXliYXNlLmlvMRww
GgYJKoZIhvcNAQkBFg1jYUBrZXliYXNlLmlvMIICIjANBgkqhkiG9w0BAQEFAAOC
Ag8AMIICCgKCAgEA3sLA6ZG8uOvmlFvFLVIOURmcQrZyMFKbVu9/TeDiemls3w3/
JzVTduD+7KiUi9R7QcCW/V1ZpReTfunm7rfACiJ1fpIkjSQrgsvKDLghIzxIS5FM
I8utet5p6QtuJhaAwmmXn8xX05FvqWNbrcXRdpL4goFdigPsFK2xhTUiWatLMste
oShI7+zmrgkx75LeLMD0bL2uOf87JjOzbY8x2sUIZLGwPoATyG8WS38ey6KkJxRj
AhG3p+OTYEjYSrsAtQA6ImbeDpfSHKOB8HF3nVp//Eb4HEiEsWwBRbQXvAWh3DYL
GukFW0wiO0HVCoWY+bHL/Mqa0NdRGOlLsbL4Z4pLrhqKgSDU8umX9YuNRRaB0P5n
TkzyU6axHqzq990Gep/I62bjsBdYYp+DjSPK43mXRrfWJl2NTcl8xKAyfsOW+9hQ
9vwK0tpSicNxfYuUZs0BhfjSZ/Tc6Z1ERdgUYRiXTtohl+SRA2IgZMloHCllVMNj
EjXhguvHgLAOrcuyhVBupiUQGUHQvkMsr1Uz8VPNDFOJedwucRU2AaR881bknnSb
ds9+zNLsvUFV+BK7Qdnt/WkFpYL78rGwY47msi9Ooddx6fPyeg3qkJGM6cwn/boy
w9lQeleYDq8kyJdixIAxtAskNzRPJ4nDu2izTfByQoM8epwAWboc/gNFObMCAwEA
AaOB9zCB9DAdBgNVHQ4EFgQURqpATOw1gVVrzlqqFKbkfaKXvwowgcQGA1UdIwSB
vDCBuYAURqpATOw1gVVrzlqqFKbkfaKXvwqhgZWkgZIwgY8xCzAJBgNVBAYTAlVT
MQswCQYDVQQIEwJOWTERMA8GA1UEBxMITmV3IFlvcmsxFDASBgNVBAoTC0tleWJh
c2UgTExDMRcwFQYDVQQLEw5DZXJ0IEF1dGhvcml0eTETMBEGA1UEAxMKa2V5YmFz
ZS5pbzEcMBoGCSqGSIb3DQEJARYNY2FAa2V5YmFzZS5pb4IJAPzhpcIBaOeNMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggIBAA3Z5FIhulYghMuHdcHYTYWc
7xT5WD4hXQ0WALZs4p5Y+b2Af54o6v1wUE1Au97FORq5CsFXX/kGl/JzzTimeucn
YJwGuXMpilrlHCBAL5/lSQjA7qbYIolQ3SB9ON+LYuF1jKB9k8SqNp7qzucxT3tO
b8ZMDEPNsseC7NE2uwNtcW3yrTh6WZnSqg/jwswiWjHYDdG7U8FjMYlRol3wPux2
PizGbSgiR+ztI2OthxtxNWMrT9XKxNQTpcxOXnLuhiSwqH8PoY17ecP8VPpaa0K6
zym0zSkbroqydazaxcXRk3eSlc02Ktk7HzRzuqQQXhRMkxVnHbFHgGsz03L533pm
mlIEgBMggZkHwNvs1LR7f3v2McdKulDH7Mv8yyfguuQ5Jxxt7RJhUuqSudbEhoaM
6jAJwBkMFxsV2YnyFEd3eZ/qBYPf7TYHhyzmHW6WkSypGqSnXd4gYpJ8o7LxSf4F
inLjxRD+H9Xn1UVXWLM0gaBB7zZcXd2zjMpRsWgezf5IR5vyakJsc7fxzgor3Qeq
Ri6LvdEkhhFVl5rHMQBwNOPngySrq8cs/ikTLTfQVTYXXA4Ba1YyiMOlfaR1LhKw
If1AkUV0tfCTNRZ01EotKSK77+o+k214n+BAu+7mO+9B5Kb7lMFQcuWCHXKYB2Md
cT7Yh09F0QpFUd0ymEfv
-----END CERTIFICATE-----

View File

@ -132,7 +132,6 @@ public final class Constants {
public static final String FIRST_TIME_APP = "firstTimeApp";
public static final String CACHED_CONSOLIDATE = "cachedConsolidate";
public static final String SEARCH_KEYSERVER = "search_keyserver_pref";
public static final String SEARCH_KEYBASE = "search_keybase_pref";
public static final String SEARCH_WEB_KEY_DIRECTORY = "search_wkd_pref";
public static final String USE_NUMKEYPAD_FOR_SECURITY_TOKEN_PIN = "useNumKeypadForYubikeyPin";
public static final String ENCRYPT_FILENAMES = "encryptFilenames";
@ -154,7 +153,6 @@ public final class Constants {
public static final String ENABLE_WIFI_SYNC_ONLY = "enableWifiSyncOnly";
public static final String SYNC_WORK_UUID = "syncWorkUuid";
// other settings
public static final String EXPERIMENTAL_ENABLE_KEYBASE = "experimentalEnableKeybase";
public static final String EXPERIMENTAL_USB_ALLOW_UNTESTED = "experimentalUsbAllowUntested";
public static final String EXPERIMENTAL_SMARTPGP_VERIFY_AUTHORITY = "smartpgp_authorities_pref";
public static final String EXPERIMENTAL_SMARTPGP_AUTHORITIES = "smartpgp_authorities";
@ -178,9 +176,9 @@ public final class Constants {
// we generally only track booleans. never snoop around in the user's string settings!!
public static final List<String> ANALYTICS_PREFS = Arrays.asList(USE_NORMAL_PROXY, USE_TOR_PROXY,
SYNC_CONTACTS, SYNC_KEYSERVER, ENABLE_WIFI_SYNC_ONLY, EXPERIMENTAL_ENABLE_KEYBASE,
SYNC_CONTACTS, SYNC_KEYSERVER, ENABLE_WIFI_SYNC_ONLY,
EXPERIMENTAL_USB_ALLOW_UNTESTED,
PASSPHRASE_CACHE_SUBS, SEARCH_KEYSERVER, SEARCH_KEYBASE, SEARCH_WEB_KEY_DIRECTORY,
PASSPHRASE_CACHE_SUBS, SEARCH_KEYSERVER, SEARCH_WEB_KEY_DIRECTORY,
TEXT_USE_COMPRESSION, TEXT_SELF_ENCRYPT, FILE_USE_COMPRESSION, FILE_SELF_ENCRYPT, USE_ARMOR,
USE_NUMKEYPAD_FOR_SECURITY_TOKEN_PIN, ENCRYPT_FILENAMES);
}

View File

@ -102,7 +102,6 @@ public class KeychainApplication extends Application {
TlsCertificatePinning.addPinnedCertificate("keys.openpgp.org", getAssets(), "LetsEncryptCA.cer");
TlsCertificatePinning.addPinnedCertificate("hkps.pool.sks-keyservers.net", getAssets(), "hkps.pool.sks-keyservers.net.CA.cer");
TlsCertificatePinning.addPinnedCertificate("pgp.mit.edu", getAssets(), "pgp.mit.edu.cer");
TlsCertificatePinning.addPinnedCertificate("api.keybase.io", getAssets(), "api.keybase.io.CA.cer");
TlsCertificatePinning.addPinnedCertificate("keyserver.ubuntu.com", getAssets(), "LetsEncryptCA.cer");
KeyserverSyncManager.updateKeyserverSyncScheduleAsync(this, false);

View File

@ -45,9 +45,6 @@ public class CloudSearch {
if (cloudPrefs.isKeyserverEnabled()) {
servers.add(HkpKeyserverClient.fromHkpKeyserverAddress(cloudPrefs.getKeyserver()));
}
if (cloudPrefs.isKeybaseEnabled()) {
servers.add(KeybaseKeyserverClient.getInstance());
}
if (cloudPrefs.isFacebookEnabled()) {
servers.add(FacebookKeyserverClient.getInstance());
}

View File

@ -77,14 +77,8 @@ public class ImportKeysList extends ArrayList<ImportKeysListEntry> {
if (incoming.getKeyserver() != null) {
existing.setKeyserver(incoming.getKeyserver());
// Mail addresses returned by HKP servers are preferred over keybase.io IDs
existing.setPrimaryUserId(incoming.getPrimaryUserId());
modified = true;
} else if (incoming.getKeybaseName() != null) {
// to work properly, Keybase-sourced/Facebook-sourced entries need to pass along the
// identifying name/id
existing.setKeybaseName(incoming.getKeybaseName());
modified = true;
} else if (incoming.getFbUsername() != null) {
existing.setFbUsername(incoming.getFbUsername());

View File

@ -17,6 +17,18 @@
package org.sufficientlysecure.keychain.keyimport;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
@ -27,18 +39,6 @@ import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class ImportKeysListEntry implements Serializable, Parcelable {
private static final long serialVersionUID = -7797972103284992662L;
@ -64,7 +64,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
private UserId mPrimaryUserId;
private HkpKeyserverAddress mKeyserver;
private String mKeybaseName;
private String mFbUsername;
private String mQuery;
@ -197,14 +196,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
mKeyserver = keyserver;
}
public String getKeybaseName() {
return mKeybaseName;
}
public void setKeybaseName(String keybaseName) {
mKeybaseName = keybaseName;
}
public String getFbUsername() {
return mFbUsername;
}
@ -257,20 +248,11 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
return modified;
}
public ArrayList<String> getKeybaseUserIds() {
ArrayList<String> keybaseUserIds = new ArrayList<>();
for (String s : mUserIds) {
if (s.contains(":"))
keybaseUserIds.add(s);
}
return keybaseUserIds;
}
/**
* Constructor for later querying from keyserver
*/
public ImportKeysListEntry() {
// keys from keyserver are always public keys; from keybase too
// keys from keyserver are always public keys
mSecretKey = false;
mUserIds = new ArrayList<>();
@ -339,20 +321,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
private void sortMergedUserIds() {
mSortedUserIds = new ArrayList<>(mMergedUserIds.entrySet());
Collections.sort(mSortedUserIds, new Comparator<Map.Entry<String, HashSet<String>>>() {
@Override
public int compare(Map.Entry<String, HashSet<String>> entry1,
Map.Entry<String, HashSet<String>> entry2) {
// sort keybase UserIds after non-Keybase
boolean e1IsKeybase = entry1.getKey().contains(":");
boolean e2IsKeybase = entry2.getKey().contains(":");
if (e1IsKeybase != e2IsKeybase) {
return (e1IsKeybase) ? 1 : -1;
}
return entry1.getKey().compareTo(entry2.getKey());
}
});
Collections.sort(mSortedUserIds,
(entry1, entry2) -> entry1.getKey().compareTo(entry2.getKey()));
}
@Override
@ -377,7 +347,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
dest.writeString(mAlgorithm);
dest.writeByte((byte) (mSecretKey ? 1 : 0));
dest.writeParcelable(mKeyserver, flags);
dest.writeString(mKeybaseName);
dest.writeString(mFbUsername);
}
@ -400,7 +369,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
vr.mAlgorithm = source.readString();
vr.mSecretKey = source.readByte() == 1;
vr.mKeyserver = source.readParcelable(HkpKeyserverAddress.class.getClassLoader());
vr.mKeybaseName = source.readString();
vr.mFbUsername = source.readString();
return vr;

View File

@ -1,121 +0,0 @@
/*
* Copyright (C) 2017 Schürmann & Breitmoser GbR
*
* 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.keyimport;
import com.textuality.keybase.lib.KeybaseException;
import com.textuality.keybase.lib.KeybaseQuery;
import com.textuality.keybase.lib.Match;
import com.textuality.keybase.lib.User;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.network.OkHttpKeybaseClient;
import org.sufficientlysecure.keychain.util.ParcelableProxy;
import timber.log.Timber;
import java.util.ArrayList;
import java.util.List;
public class KeybaseKeyserverClient implements KeyserverClient {
public static KeybaseKeyserverClient getInstance() {
return new KeybaseKeyserverClient();
}
private KeybaseKeyserverClient() { }
@Override
public ArrayList<ImportKeysListEntry> search(String query, ParcelableProxy proxy) throws QueryFailedException,
QueryNeedsRepairException {
ArrayList<ImportKeysListEntry> results = new ArrayList<>();
if (query.startsWith("0x")) {
// cut off "0x" if a user is searching for a key id
query = query.substring(2);
}
if (query.isEmpty()) {
throw new QueryTooShortException();
}
try {
KeybaseQuery keybaseQuery = new KeybaseQuery(new OkHttpKeybaseClient());
keybaseQuery.setProxy(proxy.getProxy());
Iterable<Match> matches = keybaseQuery.search(query);
for (Match match : matches) {
results.add(makeEntry(match, query));
}
} catch (KeybaseException e) {
Timber.e(e, "keybase result parsing error");
throw new QueryFailedException("Unexpected structure in keybase search result: " + e.getMessage());
}
return results;
}
private ImportKeysListEntry makeEntry(Match match, String query) throws KeybaseException {
final ImportKeysListEntry entry = new ImportKeysListEntry();
entry.setQuery(query);
entry.setRevoked(false); // keybase doesnt say anything about revoked keys
String username = match.getUsername();
String fullName = match.getFullName();
String fingerprint = match.getFingerprint();
entry.setFingerprint(KeyFormattingUtils.convertFingerprintHexFingerprint(fingerprint));
entry.setKeyIdHex("0x" + match.getKeyID());
// so we can query for the keybase id directly, and to identify the location from which the
// key is to be retrieved
entry.setKeybaseName(username);
final int bitStrength = match.getBitStrength();
entry.setBitStrength(bitStrength);
final int algorithmId = match.getAlgorithmId();
entry.setAlgorithm(KeyFormattingUtils.getAlgorithmInfo(algorithmId, bitStrength, null));
ArrayList<String> userIds = new ArrayList<>();
String name = "<keybase.io/" + username + ">";
if (fullName != null) {
name = fullName + " " + name;
}
userIds.add(name);
List<String> proofLabels = match.getProofLabels();
for (String proofLabel : proofLabels) {
userIds.add(proofLabel);
}
entry.setUserIds(userIds);
entry.setPrimaryUserId(name);
return entry;
}
@Override
public String get(String id, ParcelableProxy proxy) throws QueryFailedException {
try {
KeybaseQuery keybaseQuery = new KeybaseQuery(new OkHttpKeybaseClient());
keybaseQuery.setProxy(proxy.getProxy());
return User.keyForUsername(keybaseQuery, id);
} catch (KeybaseException e) {
throw new QueryFailedException(e.getMessage());
}
}
@Override
public void add(String armoredKey, ParcelableProxy proxy) throws AddKeyException {
throw new AddKeyException();
}
}

View File

@ -26,7 +26,7 @@ import com.google.auto.value.AutoValue;
/**
* This class is a parcelable representation of either a keyring as raw data,
* or a (unique) reference to one as a fingerprint, keyid, or keybase name.
* or a (unique) reference to one as a fingerprint, or keyid.
*/
@AutoValue
public abstract class ParcelableKeyRing implements Parcelable {
@ -41,16 +41,14 @@ public abstract class ParcelableKeyRing implements Parcelable {
@Nullable
public abstract String getKeyIdHex();
@Nullable
public abstract String getKeybaseName();
@Nullable
public abstract String getFbUsername();
public static ParcelableKeyRing createFromEncodedBytes(byte[] bytes) {
return new AutoValue_ParcelableKeyRing(bytes, null, null, null, null);
return new AutoValue_ParcelableKeyRing(bytes, null, null, null);
}
public static ParcelableKeyRing createFromReference(
byte[] expectedFingerprint, String keyIdHex, String keybaseName, String fbUsername) {
return new AutoValue_ParcelableKeyRing(null, expectedFingerprint, keyIdHex, keybaseName, fbUsername);
byte[] expectedFingerprint, String keyIdHex, String fbUsername) {
return new AutoValue_ParcelableKeyRing(null, expectedFingerprint, keyIdHex, fbUsername);
}
}

View File

@ -51,8 +51,7 @@ public class ImportKeysListCloudLoader
*
* @param loaderState state containing the string to search on servers for (if it is a
* fingerprint, will enforce fingerprint check) and the keyserver to
* search on (whether to search on the keyserver, and whether to search
* keybase.io)
* search on (whether to search on the keyserver)
* @param parcelableProxy explicit proxy to use. If null, will retrieve from preferences
*/
public ImportKeysListCloudLoader(Context context, CloudLoaderState loaderState,
@ -84,7 +83,7 @@ public class ImportKeysListCloudLoader
for (ImportKeysListEntry e : mEntryList) {
if (e.getParcelableKeyRing() == null) {
e.setParcelableKeyRing(ParcelableKeyRing.createFromReference(e.getFingerprint(), e.getKeyIdHex(),
e.getKeybaseName(), e.getFbUsername()));
e.getFbUsername()));
}
}

View File

@ -1,55 +0,0 @@
/*
* Copyright (C) 2017 Schürmann & Breitmoser GbR
*
* 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.network;
import java.io.IOException;
import java.net.Proxy;
import java.net.URL;
import com.textuality.keybase.lib.KeybaseUrlConnectionClient;
import okhttp3.OkHttpClient;
import okhttp3.Request;
/**
* Wrapper for Keybase Lib
*/
public class OkHttpKeybaseClient implements KeybaseUrlConnectionClient {
@Override
public Response getUrlResponse(URL url, Proxy proxy, boolean isKeybase) throws IOException {
OkHttpClient client;
if (proxy != null) {
client = OkHttpClientFactory.getClientPinnedIfAvailable(url, proxy);
} else {
client = OkHttpClientFactory.getSimpleClient();
}
Request request = new Request.Builder()
.url(url).build();
okhttp3.Response okResponse = client.newCall(request).execute();
return new Response(okResponse.body().byteStream(), okResponse.code(), okResponse.message(), okResponse.headers().toMultimap());
}
@Override
public String getKeybaseBaseUrl() {
return "https://api.keybase.io/";
}
}

View File

@ -41,7 +41,6 @@ import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
import org.sufficientlysecure.keychain.keyimport.FacebookKeyserverClient;
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverClient;
import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserverClient;
import org.sufficientlysecure.keychain.keyimport.KeyserverClient;
import org.sufficientlysecure.keychain.keyimport.KeyserverClient.QueryNotFoundException;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
@ -76,8 +75,7 @@ import timber.log.Timber;
* all steps for this import.
* For the import operation, the only valid source is an Iterator of
* ParcelableKeyRing, each of which must contain either a single
* keyring encoded as bytes, or a unique reference to a keyring
* on keyservers and/or keybase.io.
* keyring encoded as bytes, or a unique reference to a keyring on keyservers.
* It is important to note that public keys should generally be imported before
* secret keys, because some implementations (notably Symantec PGP Desktop) do
* not include self certificates for user ids in the secret keyring. The import
@ -93,7 +91,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
private final KeyMetadataDao keyMetadataDao;
private FacebookKeyserverClient facebookServer;
private KeybaseKeyserverClient keybaseServer;
public ImportOperation(Context context, KeyWritableRepository databaseInteractor, Progressable progressable) {
super(context, databaseInteractor, progressable);
@ -355,14 +352,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
}
}
boolean hasKeybaseName = entry.getKeybaseName() != null;
if (hasKeybaseName) {
UncachedKeyRing keybaseKey = fetchKeyFromKeybase(proxy, log, entry);
if (keybaseKey != null) {
key = mergeKeysOrUseEither(log, 3, key, keybaseKey);
}
}
boolean hasFacebookName = entry.getFbUsername() != null;
if (hasFacebookName) {
UncachedKeyRing facebookKey = fetchKeyFromFacebook(proxy, log, entry);
@ -414,32 +403,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
}
}
private UncachedKeyRing fetchKeyFromKeybase(@NonNull ParcelableProxy proxy, OperationLog log, ParcelableKeyRing entry)
throws PgpGeneralException, IOException {
if (keybaseServer == null) {
keybaseServer = KeybaseKeyserverClient.getInstance();
}
try {
log.add(LogType.MSG_IMPORT_FETCH_KEYBASE, 2, entry.getKeybaseName());
byte[] data = keybaseServer.get(entry.getKeybaseName(), proxy).getBytes();
UncachedKeyRing keybaseKey = UncachedKeyRing.decodeFromData(data);
if (keybaseKey != null) {
log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER_OK, 3);
} else {
log.add(LogType.MSG_IMPORT_FETCH_ERROR_DECODE, 3);
}
return keybaseKey;
} catch (KeyserverClient.QueryFailedException e) {
// download failed, too bad. just proceed
Timber.e(e, "query failed");
log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER, 3, e.getMessage());
return null;
}
}
private UncachedKeyRing fetchKeyFromFacebook(@NonNull ParcelableProxy proxy, OperationLog log, ParcelableKeyRing entry)
throws PgpGeneralException, IOException {
if (facebookServer == null) {

View File

@ -72,7 +72,7 @@ public class KeySyncOperation extends BaseReadWriteOperation<KeySyncParcel> {
ArrayList<ParcelableKeyRing> result = new ArrayList<>(staleKeyFingerprints.size());
for (byte[] fingerprint : staleKeyFingerprints) {
Timber.d("Keyserver sync: Updating %s", KeyFormattingUtils.beautifyKeyId(fingerprint));
result.add(ParcelableKeyRing.createFromReference(fingerprint, null, null, null));
result.add(ParcelableKeyRing.createFromReference(fingerprint, null, null));
}
return result;
}

View File

@ -1,188 +0,0 @@
/*
* Copyright (C) 2017 Schürmann & Breitmoser GbR
*
* 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 java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.support.annotation.NonNull;
import com.textuality.keybase.lib.KeybaseQuery;
import com.textuality.keybase.lib.Proof;
import com.textuality.keybase.lib.prover.Prover;
import de.measite.minidns.Client;
import de.measite.minidns.DNSMessage;
import de.measite.minidns.Question;
import de.measite.minidns.Record;
import de.measite.minidns.record.Data;
import de.measite.minidns.record.TXT;
import org.bouncycastle.openpgp.PGPUtil;
import org.json.JSONObject;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.network.OkHttpKeybaseClient;
import org.sufficientlysecure.keychain.network.orbot.OrbotHelper;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.KeybaseVerificationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
import org.sufficientlysecure.keychain.service.KeybaseVerificationParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Preferences;
public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificationParcel> {
public KeybaseVerificationOperation(Context context, KeyWritableRepository databaseInteractor,
Progressable progressable) {
super(context, databaseInteractor, progressable);
}
@NonNull
@Override
public KeybaseVerificationResult execute(KeybaseVerificationParcel keybaseInput,
CryptoInputParcel cryptoInput) {
Proxy proxy;
if (cryptoInput.getParcelableProxy() == null) {
// explicit proxy not set
if (!OrbotHelper.isOrbotInRequiredState(mContext)) {
return new KeybaseVerificationResult(null,
RequiredInputParcel.createOrbotRequiredOperation(), cryptoInput);
}
proxy = Preferences.getPreferences(mContext).getParcelableProxy().getProxy();
} else {
proxy = cryptoInput.getParcelableProxy().getProxy();
}
String requiredFingerprint = keybaseInput.mRequiredFingerprint;
OperationResult.OperationLog log = new OperationResult.OperationLog();
log.add(OperationResult.LogType.MSG_KEYBASE_VERIFICATION, 0, requiredFingerprint);
try {
KeybaseQuery keybaseQuery = new KeybaseQuery(new OkHttpKeybaseClient());
keybaseQuery.setProxy(proxy);
String keybaseProof = keybaseInput.mKeybaseProof;
Proof proof = new Proof(new JSONObject(keybaseProof));
mProgressable.setProgress(R.string.keybase_message_fetching_data, 0, 100);
Prover prover = Prover.findProverFor(proof);
if (prover == null) {
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_NO_PROVER, 1,
proof.getPrettyName());
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
if (!prover.fetchProofData(keybaseQuery)) {
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_FETCH_PROOF, 1);
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
if (!prover.checkFingerprint(requiredFingerprint)) {
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_FINGERPRINT_MISMATCH, 1);
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
String domain = prover.dnsTxtCheckRequired();
if (domain != null) {
DNSMessage dnsQuery = new Client().query(new Question(domain, Record.TYPE.TXT));
if (dnsQuery == null) {
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_DNS_FAIL, 1);
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_SPECIFIC, 2,
getFlattenedProverLog(prover));
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
Record[] records = dnsQuery.getAnswers();
List<List<byte[]>> extents = new ArrayList<>();
for (Record r : records) {
Data d = r.getPayload();
if (d instanceof TXT) {
extents.add(((TXT) d).getExtents());
}
}
if (!prover.checkDnsTxt(extents)) {
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_SPECIFIC, 1,
getFlattenedProverLog(prover));
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
}
byte[] messageBytes = prover.getPgpMessage().getBytes();
if (prover.rawMessageCheckRequired()) {
InputStream messageByteStream = PGPUtil.getDecoderStream(new
ByteArrayInputStream
(messageBytes));
if (!prover.checkRawMessageBytes(messageByteStream)) {
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_SPECIFIC, 1,
getFlattenedProverLog(prover));
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
}
PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(mContext, mKeyRepository, mProgressable);
PgpDecryptVerifyInputParcel input = PgpDecryptVerifyInputParcel.builder()
.setInputBytes(messageBytes)
.build();
DecryptVerifyResult decryptVerifyResult = op.execute(input, CryptoInputParcel.createCryptoInputParcel());
if (!decryptVerifyResult.success()) {
log.add(decryptVerifyResult, 1);
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
long verifyingKeyId = decryptVerifyResult.getSignatureResult().getKeyId();
byte[] verifyingFingerprint = mKeyRepository.getFingerprintByKeyId(verifyingKeyId);
if (!requiredFingerprint.equals(KeyFormattingUtils.convertFingerprintToHex(verifyingFingerprint))) {
log.add(LogType.MSG_KEYBASE_ERROR_FINGERPRINT_MISMATCH, 1);
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
if (!prover.validate(new String(decryptVerifyResult.getOutputBytes()))) {
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_PAYLOAD_MISMATCH, 1);
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
return new KeybaseVerificationResult(OperationResult.RESULT_OK, log, prover);
} catch (Exception e) {
// just adds the passed parameter, in this case e.getMessage()
log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_SPECIFIC, 1, e.getMessage());
return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
}
}
private String getFlattenedProverLog(Prover prover) {
String log = "";
for (String line : prover.getLog()) {
log += line + "\n";
}
return log;
}
}

View File

@ -1,87 +0,0 @@
/*
* Copyright (C) 2017 Schürmann & Breitmoser GbR
*
* 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.results;
import android.os.Parcel;
import android.os.Parcelable;
import com.textuality.keybase.lib.KeybaseException;
import com.textuality.keybase.lib.prover.Prover;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
public class KeybaseVerificationResult extends InputPendingResult {
public final String mProofUrl;
public final String mPresenceUrl;
public final String mPresenceLabel;
public KeybaseVerificationResult(int result, OperationLog log) {
super(result, log);
mProofUrl = null;
mPresenceLabel = null;
mPresenceUrl = null;
}
public KeybaseVerificationResult(int result, OperationLog log, Prover prover)
throws KeybaseException {
super(result, log);
mProofUrl = prover.getProofUrl();
mPresenceUrl = prover.getPresenceUrl();
mPresenceLabel = prover.getPresenceLabel();
}
public KeybaseVerificationResult(OperationLog log, RequiredInputParcel requiredInputParcel,
CryptoInputParcel cryptoInputParcel) {
super(log, requiredInputParcel, cryptoInputParcel);
mProofUrl = null;
mPresenceUrl = null;
mPresenceLabel = null;
}
protected KeybaseVerificationResult(Parcel in) {
super(in);
mProofUrl = in.readString();
mPresenceUrl = in.readString();
mPresenceLabel = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(mProofUrl);
dest.writeString(mPresenceUrl);
dest.writeString(mPresenceLabel);
}
public static final Parcelable.Creator<KeybaseVerificationResult> CREATOR = new Parcelable.Creator<KeybaseVerificationResult>() {
@Override
public KeybaseVerificationResult createFromParcel(Parcel in) {
return new KeybaseVerificationResult(in);
}
@Override
public KeybaseVerificationResult[] newArray(int size) {
return new KeybaseVerificationResult[size];
}
};
}

View File

@ -756,7 +756,6 @@ public abstract class OperationResult implements Parcelable {
MSG_IMPORT_FETCH_ERROR_NOT_FOUND (LogLevel.ERROR, R.string.msg_import_fetch_error_not_found),
MSG_IMPORT_FETCH_ERROR_KEYSERVER(LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver),
MSG_IMPORT_FETCH_ERROR_KEYSERVER_SECRET (LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver_secret),
MSG_IMPORT_FETCH_KEYBASE (LogLevel.INFO, R.string.msg_import_fetch_keybase),
MSG_IMPORT_FETCH_FACEBOOK (LogLevel.INFO, R.string.msg_import_fetch_facebook),
MSG_IMPORT_FETCH_KEYSERVER (LogLevel.INFO, R.string.msg_import_fetch_keyserver),
MSG_IMPORT_FETCH_KEYSERVER_OK (LogLevel.DEBUG, R.string.msg_import_fetch_keyserver_ok),
@ -820,18 +819,6 @@ public abstract class OperationResult implements Parcelable {
MSG_REVOKE_ERROR_KEY_FAIL (LogLevel.ERROR, R.string.msg_revoke_key_fail),
MSG_REVOKE_OK (LogLevel.OK, R.string.msg_revoke_ok),
// keybase verification
MSG_KEYBASE_VERIFICATION(LogLevel.START, R.string.msg_keybase_verification),
MSG_KEYBASE_ERROR_NO_PROVER(LogLevel.ERROR, R.string.msg_keybase_error_no_prover),
MSG_KEYBASE_ERROR_FETCH_PROOF(LogLevel.ERROR, R.string.msg_keybase_error_fetching_evidence),
MSG_KEYBASE_ERROR_FINGERPRINT_MISMATCH(LogLevel.ERROR,
R.string.msg_keybase_error_key_mismatch),
MSG_KEYBASE_ERROR_DNS_FAIL(LogLevel.ERROR, R.string.msg_keybase_error_dns_fail),
MSG_KEYBASE_ERROR_SPECIFIC(LogLevel.ERROR, R.string.msg_keybase_error_specific),
MSG_KEYBASE_ERROR_PAYLOAD_MISMATCH(LogLevel.ERROR,
R.string.msg_keybase_error_msg_payload_mismatch),
// InputData Operation
MSG_DATA (LogLevel.START, R.string.msg_data),
MSG_DATA_OPENPGP (LogLevel.DEBUG, R.string.msg_data_openpgp),

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2017 Schürmann & Breitmoser GbR
*
* 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.service;
import android.os.Parcel;
import android.os.Parcelable;
public class KeybaseVerificationParcel implements Parcelable {
public String mKeybaseProof;
public String mRequiredFingerprint;
public KeybaseVerificationParcel(String keybaseProof, String requiredFingerprint) {
mKeybaseProof = keybaseProof;
mRequiredFingerprint = requiredFingerprint;
}
protected KeybaseVerificationParcel(Parcel in) {
mKeybaseProof = in.readString();
mRequiredFingerprint = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mKeybaseProof);
dest.writeString(mRequiredFingerprint);
}
public static final Parcelable.Creator<KeybaseVerificationParcel> CREATOR = new Parcelable.Creator<KeybaseVerificationParcel>() {
@Override
public KeybaseVerificationParcel createFromParcel(Parcel in) {
return new KeybaseVerificationParcel(in);
}
@Override
public KeybaseVerificationParcel[] newArray(int size) {
return new KeybaseVerificationParcel[size];
}
};
}

View File

@ -41,7 +41,6 @@ import org.sufficientlysecure.keychain.operations.ImportOperation;
import org.sufficientlysecure.keychain.operations.InputDataOperation;
import org.sufficientlysecure.keychain.operations.KeySyncOperation;
import org.sufficientlysecure.keychain.operations.KeySyncParcel;
import org.sufficientlysecure.keychain.operations.KeybaseVerificationOperation;
import org.sufficientlysecure.keychain.operations.PromoteKeyOperation;
import org.sufficientlysecure.keychain.operations.RevokeOperation;
import org.sufficientlysecure.keychain.operations.SignEncryptOperation;
@ -114,8 +113,6 @@ public class KeychainServiceTask {
} else if (inputParcel instanceof UploadKeyringParcel) {
op = new UploadOperation(context, keyRepository, asyncProgressable,
operationCancelledBoolean);
} else if (inputParcel instanceof KeybaseVerificationParcel) {
op = new KeybaseVerificationOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof InputDataParcel) {
op = new InputDataOperation(context, keyRepository, asyncProgressable);
} else if (inputParcel instanceof BenchmarkInputParcel) {

View File

@ -138,7 +138,7 @@ public abstract class DecryptFragment extends Fragment {
{
ParcelableKeyRing keyEntry = ParcelableKeyRing.createFromReference(null,
KeyFormattingUtils.convertKeyIdToHex(unknownKeyId), null, null);
KeyFormattingUtils.convertKeyIdToHex(unknownKeyId), null);
ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
selectedEntries.add(keyEntry);

View File

@ -769,7 +769,7 @@ public class DecryptListFragment
{
ParcelableKeyRing keyEntry = ParcelableKeyRing.createFromReference(null,
KeyFormattingUtils.convertKeyIdToHex(unknownKeyId), null, null);
KeyFormattingUtils.convertKeyIdToHex(unknownKeyId), null);
ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
selectedEntries.add(keyEntry);

View File

@ -223,7 +223,7 @@ public class ImportKeysProxyActivity extends FragmentActivity
}
public void importKeysFromFingerprint(byte[] fingerprint) {
ParcelableKeyRing keyEntry = ParcelableKeyRing.createFromReference(fingerprint, null, null, null);
ParcelableKeyRing keyEntry = ParcelableKeyRing.createFromReference(fingerprint, null, null);
ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
selectedEntries.add(keyEntry);

View File

@ -1,465 +0,0 @@
/*
* Copyright (C) 2017 Schürmann & Breitmoser GbR
*
* 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.ui;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.StyleSpan;
import android.text.style.URLSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import com.textuality.keybase.lib.KeybaseException;
import com.textuality.keybase.lib.KeybaseQuery;
import com.textuality.keybase.lib.Proof;
import com.textuality.keybase.lib.User;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
import org.sufficientlysecure.keychain.network.OkHttpKeybaseClient;
import org.sufficientlysecure.keychain.network.orbot.OrbotHelper;
import org.sufficientlysecure.keychain.operations.results.KeybaseVerificationResult;
import org.sufficientlysecure.keychain.service.KeybaseVerificationParcel;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.ui.keyview.UnifiedKeyInfoViewModel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences;
public class ViewKeyKeybaseFragment extends Fragment implements
CryptoOperationHelper.Callback<KeybaseVerificationParcel, KeybaseVerificationResult> {
private TextView mReportHeader;
private TableLayout mProofListing;
private LayoutInflater mInflater;
private View mProofVerifyHeader;
private TextView mProofVerifyDetail;
private Proof mProof;
// for CryptoOperationHelper,Callback
private String mKeybaseProof;
private String mKeybaseFingerprint;
private CryptoOperationHelper<KeybaseVerificationParcel, KeybaseVerificationResult> mKeybaseOpHelper;
/**
* Creates new instance of this fragment
*/
public static ViewKeyKeybaseFragment newInstance() {
return new ViewKeyKeybaseFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.view_key_adv_keybase_fragment, viewGroup, false);
mInflater = inflater;
mReportHeader = view.findViewById(R.id.view_key_trust_cloud_narrative);
mProofListing = view.findViewById(R.id.view_key_proof_list);
mProofVerifyHeader = view.findViewById(R.id.view_key_proof_verify_header);
mProofVerifyDetail = view.findViewById(R.id.view_key_proof_verify_detail);
mReportHeader.setVisibility(View.GONE);
mProofListing.setVisibility(View.GONE);
mProofVerifyHeader.setVisibility(View.GONE);
mProofVerifyDetail.setVisibility(View.GONE);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
UnifiedKeyInfoViewModel viewKeyViewModel = ViewModelProviders.of(requireActivity()).get(UnifiedKeyInfoViewModel.class);
viewKeyViewModel.getUnifiedKeyInfoLiveData(requireContext()).observe(this, this::onLoadUnifiedKeyInfo);
}
private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) {
if (unifiedKeyInfo == null) {
return;
}
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(unifiedKeyInfo.fingerprint());
startSearch(fingerprint);
}
private void startSearch(final String fingerprint) {
final ParcelableProxy parcelableProxy =
Preferences.getPreferences(getActivity()).getParcelableProxy();
OrbotHelper.DialogActions dialogActions = new OrbotHelper.DialogActions() {
@Override
public void onOrbotStarted() {
new DescribeKey(parcelableProxy).execute(fingerprint);
}
@Override
public void onNeutralButton() {
new DescribeKey(ParcelableProxy.getForNoProxy())
.execute(fingerprint);
}
@Override
public void onCancel() {
}
};
if (OrbotHelper.putOrbotInRequiredState(dialogActions, getActivity())) {
new DescribeKey(parcelableProxy).execute(fingerprint);
}
}
class ResultPage {
String mHeader;
final List<CharSequence> mProofs;
ResultPage(String header, List<CharSequence> proofs) {
mHeader = header;
mProofs = proofs;
}
}
/**
* look for evidence from keybase in the background, make tabular version of result
*/
private class DescribeKey extends AsyncTask<String, Void, ResultPage> {
ParcelableProxy mParcelableProxy;
DescribeKey(ParcelableProxy parcelableProxy) {
mParcelableProxy = parcelableProxy;
}
@Override
protected ResultPage doInBackground(String... args) {
String fingerprint = args[0];
final ArrayList<CharSequence> proofList = new ArrayList<>();
final Hashtable<Integer, ArrayList<Proof>> proofs = new Hashtable<>();
try {
KeybaseQuery keybaseQuery = new KeybaseQuery(new OkHttpKeybaseClient());
keybaseQuery.setProxy(mParcelableProxy.getProxy());
User keybaseUser = User.findByFingerprint(keybaseQuery, fingerprint);
for (Proof proof : keybaseUser.getProofs()) {
Integer proofType = proof.getType();
appendIfOK(proofs, proofType, proof);
}
// a one-liner in a modern programming language
for (Integer proofType : proofs.keySet()) {
Proof[] x = {};
Proof[] proofsFor = proofs.get(proofType).toArray(x);
if (proofsFor.length > 0) {
SpannableStringBuilder ssb = new SpannableStringBuilder();
int i = 0;
while (i < proofsFor.length - 1) {
appendProofLinks(ssb, fingerprint, proofsFor[i]);
ssb.append(", ");
i++;
}
appendProofLinks(ssb, fingerprint, proofsFor[i]);
proofList.add(formatSpannableString(ssb, getProofNarrative(proofType)));
}
}
} catch (KeybaseException ignored) {
}
String prefix = "";
if (isAdded()) {
prefix = getString(R.string.key_trust_results_prefix);
}
return new ResultPage(prefix, proofList);
}
private SpannableStringBuilder formatSpannableString(SpannableStringBuilder proofLinks, String proofType) {
//Formatting SpannableStringBuilder with String.format() causes the links to stop working.
//This method is to insert the links while reserving the links
SpannableStringBuilder ssb = new SpannableStringBuilder();
ssb.append(proofType);
if (proofType.contains("%s")) {
int i = proofType.indexOf("%s");
ssb.replace(i, i + 2, proofLinks);
} else ssb.append(proofLinks);
return ssb;
}
private void appendProofLinks(SpannableStringBuilder ssb, final String fingerprint, final Proof proof) throws KeybaseException {
int startAt = ssb.length();
String handle = proof.getHandle();
ssb.append(handle);
ssb.setSpan(new URLSpan(proof.getServiceUrl()), startAt, startAt + handle.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
if (haveProofFor(proof.getType())) {
ssb.append("\u00a0[");
startAt = ssb.length();
String verify = "";
if (isAdded()) {
verify = getString(R.string.keybase_verify);
}
ssb.append(verify);
ClickableSpan clicker = new ClickableSpan() {
@Override
public void onClick(View view) {
verify(proof, fingerprint);
}
};
ssb.setSpan(clicker, startAt, startAt + verify.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append("]");
}
}
@Override
protected void onPostExecute(ResultPage result) {
super.onPostExecute(result);
// stop if fragment is no longer added to an activity
if(!isAdded()) {
return;
}
if (result.mProofs.isEmpty()) {
result.mHeader = requireActivity().getString(R.string.key_trust_no_cloud_evidence);
}
mReportHeader.setVisibility(View.VISIBLE);
mProofListing.setVisibility(View.VISIBLE);
mReportHeader.setText(result.mHeader);
int rowNumber = 1;
for (CharSequence s : result.mProofs) {
TableRow row = (TableRow) mInflater.inflate(R.layout.view_key_adv_keybase_proof, null);
TextView number = row.findViewById(R.id.proof_number);
TextView text = row.findViewById(R.id.proof_text);
number.setText(Integer.toString(rowNumber++) + ". ");
text.setText(s);
text.setMovementMethod(LinkMovementMethod.getInstance());
mProofListing.addView(row);
}
}
}
private String getProofNarrative(int proofType) {
int stringIndex;
switch (proofType) {
case Proof.PROOF_TYPE_TWITTER:
stringIndex = R.string.keybase_narrative_twitter;
break;
case Proof.PROOF_TYPE_GITHUB:
stringIndex = R.string.keybase_narrative_github;
break;
case Proof.PROOF_TYPE_DNS:
stringIndex = R.string.keybase_narrative_dns;
break;
case Proof.PROOF_TYPE_WEB_SITE:
stringIndex = R.string.keybase_narrative_web_site;
break;
case Proof.PROOF_TYPE_HACKERNEWS:
stringIndex = R.string.keybase_narrative_hackernews;
break;
case Proof.PROOF_TYPE_COINBASE:
stringIndex = R.string.keybase_narrative_coinbase;
break;
case Proof.PROOF_TYPE_REDDIT:
stringIndex = R.string.keybase_narrative_reddit;
break;
default:
stringIndex = R.string.keybase_narrative_unknown;
}
if (isAdded()) {
return getString(stringIndex);
} else {
return "";
}
}
private void appendIfOK(Hashtable<Integer, ArrayList<Proof>> table, Integer proofType, Proof proof) {
ArrayList<Proof> list = table.get(proofType);
if (list == null) {
list = new ArrayList<>();
table.put(proofType, list);
}
list.add(proof);
}
// which proofs do we have working verifiers for?
private boolean haveProofFor(int proofType) {
switch (proofType) {
case Proof.PROOF_TYPE_TWITTER:
return true;
case Proof.PROOF_TYPE_GITHUB:
return true;
case Proof.PROOF_TYPE_DNS:
return true;
case Proof.PROOF_TYPE_WEB_SITE:
return true;
case Proof.PROOF_TYPE_HACKERNEWS:
return true;
case Proof.PROOF_TYPE_COINBASE:
return true;
case Proof.PROOF_TYPE_REDDIT:
return true;
default:
return false;
}
}
private void verify(final Proof proof, final String fingerprint) {
mProof = proof;
mKeybaseProof = proof.toString();
mKeybaseFingerprint = fingerprint;
mProofVerifyDetail.setVisibility(View.GONE);
mKeybaseOpHelper = new CryptoOperationHelper<>(1, this, this,
R.string.progress_verifying_signature);
mKeybaseOpHelper.cryptoOperation();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (mKeybaseOpHelper != null) {
mKeybaseOpHelper.handleActivityResult(requestCode, resultCode, data);
}
}
// CryptoOperationHelper.Callback methods
@Override
public KeybaseVerificationParcel createOperationInput() {
return new KeybaseVerificationParcel(mKeybaseProof, mKeybaseFingerprint);
}
@Override
public void onCryptoOperationSuccess(KeybaseVerificationResult result) {
result.createNotify(getActivity()).show();
String proofUrl = result.mProofUrl;
String presenceUrl = result.mPresenceUrl;
String presenceLabel = result.mPresenceLabel;
Proof proof = mProof; // TODO: should ideally be contained in result
String proofLabel;
switch (proof.getType()) {
case Proof.PROOF_TYPE_TWITTER:
proofLabel = getString(R.string.keybase_twitter_proof);
break;
case Proof.PROOF_TYPE_DNS:
proofLabel = getString(R.string.keybase_dns_proof);
break;
case Proof.PROOF_TYPE_WEB_SITE:
proofLabel = getString(R.string.keybase_web_site_proof);
break;
case Proof.PROOF_TYPE_GITHUB:
proofLabel = getString(R.string.keybase_github_proof);
break;
case Proof.PROOF_TYPE_REDDIT:
proofLabel = getString(R.string.keybase_reddit_proof);
break;
default:
proofLabel = getString(R.string.keybase_a_post);
break;
}
SpannableStringBuilder ssb = new SpannableStringBuilder();
ssb.append(getString(R.string.keybase_proof_succeeded));
StyleSpan bold = new StyleSpan(Typeface.BOLD);
ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append("\n\n");
int length = ssb.length();
ssb.append(proofLabel);
if (proofUrl != null) {
URLSpan postLink = new URLSpan(proofUrl);
ssb.setSpan(postLink, length, length + proofLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (Proof.PROOF_TYPE_DNS == proof.getType()) {
ssb.append(" ").append(getString(R.string.keybase_for_the_domain)).append(" ");
} else {
ssb.append(" ").append(getString(R.string.keybase_fetched_from)).append(" ");
}
length = ssb.length();
URLSpan presenceLink = new URLSpan(presenceUrl);
ssb.append(presenceLabel);
ssb.setSpan(presenceLink, length, length + presenceLabel.length(), Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
if (Proof.PROOF_TYPE_REDDIT == proof.getType()) {
ssb.append(", ").
append(getString(R.string.keybase_reddit_attribution)).
append("").append(proof.getHandle()).append("”, ");
}
ssb.append(" ").append(getString(R.string.keybase_contained_signature));
displaySpannableResult(ssb);
}
@Override
public void onCryptoOperationCancelled() {
}
@Override
public void onCryptoOperationError(KeybaseVerificationResult result) {
result.createNotify(getActivity()).show();
SpannableStringBuilder ssb = new SpannableStringBuilder();
ssb.append(getString(R.string.keybase_proof_failure));
String msg = getString(result.getLog().getLast().mType.mMsgId);
if (msg == null) {
msg = getString(R.string.keybase_unknown_proof_failure);
}
StyleSpan bold = new StyleSpan(Typeface.BOLD);
ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append("\n\n").append(msg);
displaySpannableResult(ssb);
}
@Override
public boolean onCryptoSetProgress(String msg, int progress, int max) {
return false;
}
private void displaySpannableResult(SpannableStringBuilder ssb) {
mProofVerifyHeader.setVisibility(View.VISIBLE);
mProofVerifyDetail.setVisibility(View.VISIBLE);
mProofVerifyDetail.setMovementMethod(LinkMovementMethod.getInstance());
mProofVerifyDetail.setText(ssb);
}
}

View File

@ -24,15 +24,16 @@ import java.util.Date;
import java.util.List;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.RecyclerView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.daos.KeyRepository;
import org.sufficientlysecure.keychain.databinding.ImportKeysListItemBinding;
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
@ -45,7 +46,6 @@ import org.sufficientlysecure.keychain.operations.ImportOperation;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing;
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing.VerificationStatus;
import org.sufficientlysecure.keychain.daos.KeyRepository;
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity;
@ -308,10 +308,7 @@ public class ImportKeysAdapter extends RecyclerView.Adapter<ImportKeysAdapter.Vi
throw new AssertionError("Creation date doesn't match the expected one");
}
entry.setKeyId(keyRing.getMasterKeyId());
ArrayList<String> realUserIdsPlusKeybase = keyRing.getUnorderedUserIds();
realUserIdsPlusKeybase.addAll(entry.getKeybaseUserIds());
entry.setUserIds(realUserIdsPlusKeybase);
entry.setUserIds(keyRing.getUnorderedUserIds());
}
private class KeyState {

View File

@ -92,7 +92,6 @@ import org.sufficientlysecure.keychain.ui.MainActivity;
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.QrCodeViewActivity;
import org.sufficientlysecure.keychain.ui.ViewKeyAdvActivity;
import org.sufficientlysecure.keychain.ui.ViewKeyKeybaseFragment;
import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
@ -289,11 +288,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity {
ViewKeyFragment frag = ViewKeyFragment.newInstance();
manager.beginTransaction().replace(R.id.view_key_fragment, frag, "view_key_fragment").commit();
if (Preferences.getPreferences(this).getExperimentalEnableKeybase()) {
final ViewKeyKeybaseFragment keybaseFrag = ViewKeyKeybaseFragment.newInstance();
manager.beginTransaction().replace(R.id.view_key_keybase_fragment, keybaseFrag).commit();
}
}
@Override
@ -890,7 +884,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity {
HkpKeyserverAddress preferredKeyserver = Preferences.getPreferences(getApplicationContext()).getPreferredKeyserver();
ParcelableKeyRing keyEntry =
ParcelableKeyRing.createFromReference(unifiedKeyInfo.fingerprint(), null, null, null);
ParcelableKeyRing.createFromReference(unifiedKeyInfo.fingerprint(), null, null);
return ImportKeyringParcel
.createImportKeyringParcel(Collections.singletonList(keyEntry), preferredKeyserver);

View File

@ -65,7 +65,8 @@ public class EmailKeyHelper {
// Put them in a list and import
ArrayList<ParcelableKeyRing> keys = new ArrayList<>(entries.size());
for (ImportKeysListEntry entry : entries) {
keys.add(ParcelableKeyRing.createFromReference(entry.getFingerprint(), entry.getKeyIdHex(), null, null));
keys.add(ParcelableKeyRing.createFromReference(entry.getFingerprint(), entry.getKeyIdHex(),
null));
}
mKeyList = keys;
mKeyserver = keyserver;

View File

@ -330,7 +330,6 @@ public class Preferences {
public CloudSearchPrefs getCloudSearchPrefs() {
return CloudSearchPrefs.create(mSharedPreferences.getBoolean(Pref.SEARCH_KEYSERVER, true),
mSharedPreferences.getBoolean(Pref.SEARCH_KEYBASE, true),
false,
mSharedPreferences.getBoolean(Pref.SEARCH_WEB_KEY_DIRECTORY, true),
getPreferredKeyserver());
@ -387,7 +386,6 @@ public class Preferences {
@AutoValue
public static abstract class CloudSearchPrefs implements Parcelable {
public abstract boolean isKeyserverEnabled();
public abstract boolean isKeybaseEnabled();
public abstract boolean isFacebookEnabled();
public abstract boolean isWebKeyDirectoryEnabled();
@ -396,31 +394,29 @@ public class Preferences {
/**
* @param searchKeyserver should passed keyserver be searched
* @param searchKeybase should keybase.io be searched
* @param searchFacebook should Facebook be searched
* @param searchWebKeyDirectory should WKD be searched
* @param keyserver the keyserver url authority to search on
*/
public static CloudSearchPrefs create(boolean searchKeyserver, boolean searchKeybase,
public static CloudSearchPrefs create(boolean searchKeyserver,
boolean searchFacebook, boolean searchWebKeyDirectory,
@Nullable HkpKeyserverAddress keyserver) {
return new AutoValue_Preferences_CloudSearchPrefs(searchKeyserver,
searchKeybase,
searchFacebook,
searchWebKeyDirectory,
keyserver);
}
public static CloudSearchPrefs createWebKeyDirectoryOnly() {
return create(false, false, false, true, null);
return create(false, false, true, null);
}
public static CloudSearchPrefs createKeyserverOnly(HkpKeyserverAddress keyserver) {
return create(true, false, false, false, keyserver);
return create(true, false, false, keyserver);
}
public static CloudSearchPrefs createSocialOnly() {
return create(false, true, true, false, null);
return create(false, true, false, null);
}
}
@ -432,10 +428,6 @@ public class Preferences {
// experimental prefs
public boolean getExperimentalEnableKeybase() {
return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_ENABLE_KEYBASE, false);
}
public boolean getExperimentalUsbAllowUntested() {
return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_USB_ALLOW_UNTESTED, false);
}

View File

@ -205,11 +205,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/view_key_keybase_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!--
placeholder to improve the scrolling.
Somehow the content must be large enough to enable scrolling on NestedScrollView

View File

@ -1,81 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp">
<android.support.v7.widget.CardView
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="?attr/colorCardViewBackground"
card_view:cardCornerRadius="4dp"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
style="@style/CardViewHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/section_keybase_proofs" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp">
<TextView
android:id="@+id/view_key_trust_cloud_narrative"
style="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="14dp"
android:layout_marginLeft="8dp"
android:layout_weight="1" />
<TableLayout
android:id="@+id/view_key_proof_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/view_key_proof_verify_header"
style="@style/SectionHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_weight="1"
android:text="@string/section_proof_details" />
<TextView
android:id="@+id/view_key_proof_verify_detail"
style="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="14dp"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:id="@+id/proof_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dip"
android:text="1."
style="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/proof_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dip"
android:text="Posts to twitter as Timbray"
style="?android:attr/textAppearanceSmall" />
</TableRow>

View File

@ -46,12 +46,11 @@
<string name="section_user_ids">"Identities"</string>
<string name="section_security_token">"Security Token"</string>
<string name="section_linked_system_contact">"Linked System Contact"</string>
<string name="section_keybase_proofs">"Keybase.io Proofs"</string>
<string name="section_should_you_trust">"Should you trust this key?"</string>
<string name="section_proof_details">Proof verification</string>
<string name="section_keys">"Subkeys"</string>
<string name="section_cloud_search">"Key Search"</string>
<string name="section_cloud_search_summary">"Keyserver, keybase.io"</string>
<string name="section_cloud_search_summary">"Keyserver"</string>
<string name="section_passphrase_cache">"Passwords and PINs"</string>
<string name="section_passphrase_cache_summary">"Handling"</string>
<string name="section_proxy_settings">"Network Anonymity"</string>
@ -212,8 +211,6 @@
<string name="pref_keyserver">"OpenPGP keyservers"</string>
<string name="pref_keyserver_summary">"Search keys on selected OpenPGP keyservers (HKP protocol)"</string>
<string name="pref_keybase">"keybase.io"</string>
<string name="pref_keybase_summary">"Search keys on keybase.io"</string>
<string name="pref_facebook">"Facebook"</string>
<string name="pref_facebook_summary">"Search keys on Facebook by username"</string>
<string name="pref_wkd">"Web Key Directory"</string>
@ -232,8 +229,6 @@
<string name="label_experimental_settings_desc_title">"Warning"</string>
<string name="label_experimental_settings_desc_summary">"These features are not yet finished or results of user experience/security research. Thus, don't rely on their security and please don't report issues you encounter!"</string>
<string name="label_experimental_settings_keybase_title">"Keybase.io proofs"</string>
<string name="label_experimental_settings_keybase_summary">"Contact keybase.io for key proofs and show them every time a key is displayed"</string>
<string name="label_experimental_settings_theme_summary">"(The icons and many screens are not yet adjusted accordingly for the dark theme)"</string>
<string name="label_settings_analytics_title">Allow anonymous usage statistics</string>
@ -724,7 +719,6 @@
<string name="key_view_tab_share">"Share"</string>
<string name="key_view_tab_keys">"Subkeys"</string>
<string name="key_view_tab_certs">"Certificates"</string>
<string name="key_view_tab_keybase">"Keybase.io"</string>
<string name="user_id_info_revoked_title">"Revoked"</string>
<string name="user_id_info_revoked_text">"This identity has been revoked by the key owner. It is no longer valid."</string>
<string name="user_id_info_certified_title">"Confirmed"</string>
@ -735,37 +729,6 @@
<!-- Key trust -->
<string name="key_trust_no_cloud_evidence">"No proof from the Internet on this keys trustworthiness."</string>
<string name="key_trust_start_cloud_search">"Start search"</string>
<string name="key_trust_results_prefix">"Keybase.io offers “proofs” which assert that the owner of this key: "</string>
<!-- keybase proof stuff -->
<string name="keybase_narrative_twitter">"Posts to Twitter as %s"</string>
<string name="keybase_narrative_github">"Is known on GitHub as %s"</string>
<string name="keybase_narrative_dns">"Controls the domain name(s) %s"</string>
<string name="keybase_narrative_web_site">"Can post to the Web site(s) %s"</string>
<string name="keybase_narrative_reddit">"Posts to Reddit as %s"</string>
<string name="keybase_narrative_coinbase">"Is known on Coinbase as %s"</string>
<string name="keybase_narrative_hackernews">"Posts to Hacker News as %s"</string>
<string name="keybase_narrative_unknown">"Unknown proof type %s"</string>
<string name="keybase_proof_failure">"Unfortunately this proof cannot be verified."</string>
<string name="keybase_unknown_proof_failure">"Unrecognized problem with proof checker"</string>
<string name="keybase_problem_fetching_evidence">"Problem with proof"</string>
<string name="keybase_key_mismatch">"Key fingerprint doesnt match that in proof post"</string>
<string name="keybase_dns_query_failure">"DNS TXT Record retrieval failed"</string>
<string name="keybase_no_prover_found">"No proof checker found for"</string>
<string name="keybase_message_payload_mismatch">"Decrypted proof post does not match expected value"</string>
<string name="keybase_message_fetching_data">"Fetching proof"</string>
<string name="keybase_proof_succeeded">"This proof has been verified!"</string>
<string name="keybase_a_post">"A post"</string>
<string name="keybase_fetched_from">"fetched from"</string>
<string name="keybase_for_the_domain">"for the domain"</string>
<string name="keybase_contained_signature">"contains a message which could only have been created by the owner of this key."</string>
<string name="keybase_twitter_proof">"A tweet"</string>
<string name="keybase_dns_proof">"A DNS TXT record"</string>
<string name="keybase_web_site_proof">"A text file"</string>
<string name="keybase_github_proof">"A gist"</string>
<string name="keybase_reddit_proof">"A JSON file"</string>
<string name="keybase_reddit_attribution">"attributed by Reddit to"</string>
<string name="keybase_verify">"Verify"</string>
<!-- Edit key -->
<string name="edit_key_action_change_passphrase">"Change Password"</string>
@ -1334,7 +1297,6 @@
<string name="msg_import_fetch_error_not_found">"Key not found!"</string>
<string name="msg_import_fetch_error_keyserver">"Could not retrieve key from keyservers: %s"</string>
<string name="msg_import_fetch_error_keyserver_secret">"Cannot import secret key from keyserver!"</string>
<string name="msg_import_fetch_keybase">"Retrieving from keybase.io: %s"</string>
<string name="msg_import_fetch_facebook">"Retrieving from Facebook: %s"</string>
<string name="msg_import_fetch_keyserver">"Retrieving from keyserver: %s"</string>
<string name="msg_import_fetch_keyserver_ok">"Key retrieval successful"</string>
@ -1437,15 +1399,6 @@
<string name="msg_download_query_failed">"An error occurred when searching for keys."</string>
<!-- Messages for Keybase Verification operation -->
<string name="msg_keybase_verification">"Attempting keybase verification for %s"</string>
<string name="msg_keybase_error_no_prover">"No proof checker found for %s"</string>
<string name="msg_keybase_error_fetching_evidence">"Problem with fetching proof"</string>
<string name="msg_keybase_error_key_mismatch">"Key fingerprint doesnt match that in proof post"</string>
<string name="msg_keybase_error_dns_fail">"DNS TXT Record retrieval failed"</string>
<string name="msg_keybase_error_specific">"%s"</string>
<string name="msg_keybase_error_msg_payload_mismatch">"Decrypted proof post does not match expected value"</string>
<!-- Messages for Mime parsing operation -->
<string name="msg_mime_parsing_start">"Parsing the MIME structure"</string>
<string name="msg_mime_parsing_error">"MIME parsing failed"</string>

View File

@ -9,11 +9,6 @@
android:dependency="search_keyserver_pref"
android:key="keyServers"
android:title="@string/label_keyservers" />
<SwitchPreference
android:defaultValue="true"
android:key="search_keybase_pref"
android:summary="@string/pref_keybase_summary"
android:title="@string/pref_keybase" />
<SwitchPreference
android:defaultValue="true"
android:key="search_wkd_pref"

View File

@ -12,13 +12,6 @@
android:summary="@string/label_settings_analytics_summary"
android:title="@string/label_settings_analytics_title" />
<SwitchPreference
android:defaultValue="false"
android:key="experimentalEnableKeybase"
android:persistent="true"
android:summary="@string/label_experimental_settings_keybase_summary"
android:title="@string/label_experimental_settings_keybase_title" />
<ListPreference
android:defaultValue="light"
android:dialogTitle="@string/label_theme"

1
extern/KeybaseLib vendored

@ -1 +0,0 @@
Subproject commit 476fc52a7e59a490d89b8e15f96f5c8535c20328

View File

@ -11,8 +11,5 @@ include ':extern:MaterialChipsInput:library'
//include ':extern:openpgp-api-lib:openpgp-api'
include ':openpgp-api-lib'
project(':openpgp-api-lib').projectDir = new File('extern/openpgp-api-lib/openpgp-api')
//include ':extern:KeybaseLib:Lib'
include ':KeybaseLib'
project(':KeybaseLib').projectDir = new File('extern/KeybaseLib/Lib')
include ':sshauthentication-api'
project(':sshauthentication-api').projectDir = new File('sshauthentication-api')