diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
index d201a1426..09c0b2d8f 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
@@ -460,12 +460,16 @@ public class PgpKeyHelper {
public static String convertFingerprintToHex(byte[] fingerprint, boolean split) {
String hexString = Hex.toHexString(fingerprint);
if (split) {
- hexString = hexString.replaceAll("(.{4})(?!$)", "$1 ");
+ hexString = splitFingerprintHex(hexString);
}
return hexString;
}
+ public static String splitFingerprintHex(String hexString) {
+ return hexString.replaceAll("(.{4})(?!$)", "$1 ");
+ }
+
/**
* Convert key id from long to 64 bit hex string
*
@@ -497,19 +501,6 @@ public class PgpKeyHelper {
return hexString;
}
- /**
- * Used in HkpKeyServer to convert hex encoded key ids back to long.
- *
- * @param hexString
- * @return
- */
- public static long convertHexToKeyId(String hexString) {
- int len = hexString.length();
- String s2 = hexString.substring(len - 8);
- String s1 = hexString.substring(0, len - 8);
- return ((!s1.isEmpty() ? Long.parseLong(s1, 16) << 32 : 0) | Long.parseLong(s2, 16));
- }
-
/**
* Splits userId string into naming part, email part, and comment part
*
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index 6ec6dcf8a..5af81d39d 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -749,7 +749,7 @@ public class KeychainIntentService extends IntentService
HkpKeyServer server = new HkpKeyServer(keyServer);
for (ImportKeysListEntry entry : entries) {
- byte[] downloadedKey = server.get(entry.getKeyId()).getBytes();
+ byte[] downloadedKey = server.get(entry.getKeyIdHex()).getBytes();
/**
* TODO: copied from ImportKeysListLoader
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
index 0f05af447..37a8dd416 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
@@ -134,10 +134,10 @@ public class ImportKeysAdapter extends ArrayAdapter {
holder.mMainUserIdRest.setVisibility(View.GONE);
}
- holder.mKeyId.setText(entry.hexKeyId);
+ holder.mKeyId.setText(entry.keyIdHex);
- if (entry.fingerPrint != null) {
- holder.mFingerprint.setText(mActivity.getString(R.string.fingerprint) + " " + entry.fingerPrint);
+ if (entry.fingerPrintHex != null) {
+ holder.mFingerprint.setText(mActivity.getString(R.string.fingerprint) + " " + entry.fingerPrintHex);
holder.mFingerprint.setVisibility(View.VISIBLE);
} else {
holder.mFingerprint.setVisibility(View.GONE);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java
index 05521b0c9..d7c38213d 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui.adapter;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
+
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
@@ -38,10 +39,11 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
public ArrayList userIds;
public long keyId;
+ public String keyIdHex;
+
public boolean revoked;
public Date date; // TODO: not displayed
- public String fingerPrint;
- public String hexKeyId;
+ public String fingerPrintHex;
public int bitStrength;
public String algorithm;
public boolean secretKey;
@@ -55,8 +57,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
this.keyId = b.keyId;
this.revoked = b.revoked;
this.date = b.date;
- this.fingerPrint = b.fingerPrint;
- this.hexKeyId = b.hexKeyId;
+ this.fingerPrintHex = b.fingerPrintHex;
+ this.keyIdHex = b.keyIdHex;
this.bitStrength = b.bitStrength;
this.algorithm = b.algorithm;
this.secretKey = b.secretKey;
@@ -74,8 +76,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
dest.writeLong(keyId);
dest.writeByte((byte) (revoked ? 1 : 0));
dest.writeSerializable(date);
- dest.writeString(fingerPrint);
- dest.writeString(hexKeyId);
+ dest.writeString(fingerPrintHex);
+ dest.writeString(keyIdHex);
dest.writeInt(bitStrength);
dest.writeString(algorithm);
dest.writeByte((byte) (secretKey ? 1 : 0));
@@ -92,8 +94,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
vr.keyId = source.readLong();
vr.revoked = source.readByte() == 1;
vr.date = (Date) source.readSerializable();
- vr.fingerPrint = source.readString();
- vr.hexKeyId = source.readString();
+ vr.fingerPrintHex = source.readString();
+ vr.keyIdHex = source.readString();
vr.bitStrength = source.readInt();
vr.algorithm = source.readString();
vr.secretKey = source.readByte() == 1;
@@ -109,8 +111,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
}
};
- public long getKeyId() {
- return keyId;
+ public String getKeyIdHex() {
+ return keyIdHex;
}
public byte[] getBytes() {
@@ -121,6 +123,14 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
this.mBytes = bytes;
}
+ public boolean isSelected() {
+ return mSelected;
+ }
+
+ public void setSelected(boolean selected) {
+ this.mSelected = selected;
+ }
+
/**
* Constructor for later querying from keyserver
*/
@@ -132,14 +142,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
userIds = new ArrayList();
}
- public boolean isSelected() {
- return mSelected;
- }
-
- public void setSelected(boolean selected) {
- this.mSelected = selected;
- }
-
/**
* Constructor based on key object, used for import from NFC, QR Codes, files
*/
@@ -165,12 +167,13 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
for (String userId : new IterableIterator(pgpKeyRing.getPublicKey().getUserIDs())) {
userIds.add(userId);
}
+
this.keyId = pgpKeyRing.getPublicKey().getKeyID();
+ this.keyIdHex = PgpKeyHelper.convertKeyIdToHex(keyId);
this.revoked = pgpKeyRing.getPublicKey().isRevoked();
- this.fingerPrint = PgpKeyHelper.convertFingerprintToHex(pgpKeyRing.getPublicKey()
+ this.fingerPrintHex = PgpKeyHelper.convertFingerprintToHex(pgpKeyRing.getPublicKey()
.getFingerprint(), true);
- this.hexKeyId = PgpKeyHelper.convertKeyIdToHex(keyId);
this.bitStrength = pgpKeyRing.getPublicKey().getBitStrength();
final int algorithm = pgpKeyRing.getPublicKey().getAlgorithm();
this.algorithm = getAlgorithmFromId(algorithm);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java
index 43b40a4db..3658ef6c6 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java
@@ -18,7 +18,6 @@
package org.sufficientlysecure.keychain.util;
-import android.text.Html;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
@@ -34,7 +33,6 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
-import org.sufficientlysecure.keychain.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -74,26 +72,26 @@ public class HkpKeyServer extends KeyServer {
/**
* pub:%keyid%:%algo%:%keylen%:%creationdate%:%expirationdate%:%flags%
*
- * - %keyid% = this is either the fingerprint or the key ID of the key. Either the 16-digit or 8-digit
- * key IDs are acceptable, but obviously the fingerprint is best.
- * - %algo% = the algorithm number, (i.e. 1==RSA, 17==DSA, etc).
- * See RFC-2440
- * - %keylen% = the key length (i.e. 1024, 2048, 4096, etc.)
- * - %creationdate% = creation date of the key in standard
- * RFC-2440 form (i.e. number of seconds since
- * 1/1/1970 UTC time)
- * - %expirationdate% = expiration date of the key in standard
- * RFC-2440 form (i.e. number of seconds since
- * 1/1/1970 UTC time)
- * - %flags% = letter codes to indicate details of the key, if any. Flags may be in any order. The
- * meaning of "disabled" is implementation-specific. Note that individual flags may be unimplemented, so
- * the absence of a given flag does not necessarily mean the absence of the detail.
- *
- * - r == revoked
- * - d == disabled
- * - e == expired
- *
- *
+ * - %keyid% = this is either the fingerprint or the key ID of the key. Either the 16-digit or 8-digit
+ * key IDs are acceptable, but obviously the fingerprint is best.
+ * - %algo% = the algorithm number, (i.e. 1==RSA, 17==DSA, etc).
+ * See RFC-2440
+ * - %keylen% = the key length (i.e. 1024, 2048, 4096, etc.)
+ * - %creationdate% = creation date of the key in standard
+ * RFC-2440 form (i.e. number of seconds since
+ * 1/1/1970 UTC time)
+ * - %expirationdate% = expiration date of the key in standard
+ * RFC-2440 form (i.e. number of seconds since
+ * 1/1/1970 UTC time)
+ * - %flags% = letter codes to indicate details of the key, if any. Flags may be in any order. The
+ * meaning of "disabled" is implementation-specific. Note that individual flags may be unimplemented, so
+ * the absence of a given flag does not necessarily mean the absence of the detail.
+ *
+ * - r == revoked
+ * - d == disabled
+ * - e == expired
+ *
+ *
*
*
* @see 5.2. Machine Readable Indexes
@@ -107,23 +105,23 @@ public class HkpKeyServer extends KeyServer {
/**
* uid:%escaped uid string%:%creationdate%:%expirationdate%:%flags%
*
- * - %escaped uid string% = the user ID string, with HTTP %-escaping for anything that isn't 7-bit
- * safe as well as for the ":" character. Any other characters may be escaped, as desired.
- * - %creationdate% = creation date of the key in standard
- * RFC-2440 form (i.e. number of seconds since
- * 1/1/1970 UTC time)
- * - %expirationdate% = expiration date of the key in standard
- * RFC-2440 form (i.e. number of seconds since
- * 1/1/1970 UTC time)
- * - %flags% = letter codes to indicate details of the key, if any. Flags may be in any order. The
- * meaning of "disabled" is implementation-specific. Note that individual flags may be unimplemented, so
- * the absence of a given flag does not necessarily mean the absence of the detail.
- *
- * - r == revoked
- * - d == disabled
- * - e == expired
- *
- *
+ * - %escaped uid string% = the user ID string, with HTTP %-escaping for anything that isn't 7-bit
+ * safe as well as for the ":" character. Any other characters may be escaped, as desired.
+ * - %creationdate% = creation date of the key in standard
+ * RFC-2440 form (i.e. number of seconds since
+ * 1/1/1970 UTC time)
+ * - %expirationdate% = expiration date of the key in standard
+ * RFC-2440 form (i.e. number of seconds since
+ * 1/1/1970 UTC time)
+ * - %flags% = letter codes to indicate details of the key, if any. Flags may be in any order. The
+ * meaning of "disabled" is implementation-specific. Note that individual flags may be unimplemented, so
+ * the absence of a given flag does not necessarily mean the absence of the detail.
+ *
+ * - r == revoked
+ * - d == disabled
+ * - e == expired
+ *
+ *
*
*/
public static final Pattern UID_LINE = Pattern
@@ -246,8 +244,18 @@ public class HkpKeyServer extends KeyServer {
final int algorithmId = Integer.decode(matcher.group(2));
info.algorithm = getAlgorithmFromId(algorithmId);
- info.hexKeyId = "0x" + matcher.group(1);
- info.keyId = PgpKeyHelper.convertHexToKeyId(matcher.group(1));
+ // group 1 contains the full fingerprint (v4) or the long key id if available
+ // see https://bitbucket.org/skskeyserver/sks-keyserver/pull-request/12/fixes-for-machine-readable-indexes/diff
+ // and https://github.com/openpgp-keychain/openpgp-keychain/issues/259#issuecomment-38168176
+ String fingerprintOrKeyId = matcher.group(1);
+ if (fingerprintOrKeyId.length() > 16) {
+ info.fingerPrintHex = "0x" + PgpKeyHelper.splitFingerprintHex(fingerprintOrKeyId);
+ info.keyIdHex = "0x" + fingerprintOrKeyId.substring(fingerprintOrKeyId.length()
+ - 16, fingerprintOrKeyId.length());
+ } else {
+ // set key id only
+ info.keyIdHex = "0x" + fingerprintOrKeyId;
+ }
final long creationDate = Long.parseLong(matcher.group(4));
final GregorianCalendar tmpGreg = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
@@ -277,11 +285,11 @@ public class HkpKeyServer extends KeyServer {
}
@Override
- public String get(long keyId) throws QueryException {
+ public String get(String keyIdHex) throws QueryException {
HttpClient client = new DefaultHttpClient();
try {
String query = "http://" + mHost + ":" + mPort +
- "/pks/lookup?op=get&options=mr&search=" + PgpKeyHelper.convertKeyIdToHex(keyId);
+ "/pks/lookup?op=get&options=mr&search=" + keyIdHex;
Log.d(Constants.TAG, "hkp keyserver get: " + query);
HttpGet get = new HttpGet(query);
HttpResponse response = client.execute(get);
@@ -306,14 +314,14 @@ public class HkpKeyServer extends KeyServer {
}
@Override
- public void add(String armoredText) throws AddKeyException {
+ public void add(String armoredKey) throws AddKeyException {
HttpClient client = new DefaultHttpClient();
try {
String query = "http://" + mHost + ":" + mPort + "/pks/add";
HttpPost post = new HttpPost(query);
Log.d(Constants.TAG, "hkp keyserver add: " + query);
List nameValuePairs = new ArrayList(2);
- nameValuePairs.add(new BasicNameValuePair("keytext", armoredText));
+ nameValuePairs.add(new BasicNameValuePair("keytext", armoredKey));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/KeyServer.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/KeyServer.java
index a31fdc5ae..7f70867a5 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/KeyServer.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/KeyServer.java
@@ -46,7 +46,7 @@ public abstract class KeyServer {
abstract List search(String query) throws QueryException, TooManyResponses,
InsufficientQuery;
- abstract String get(long keyId) throws QueryException;
+ abstract String get(String keyIdHex) throws QueryException;
- abstract void add(String armoredText) throws AddKeyException;
+ abstract void add(String armoredKey) throws AddKeyException;
}
diff --git a/OpenPGP-Keychain/src/main/res/layout/import_keys_list_entry.xml b/OpenPGP-Keychain/src/main/res/layout/import_keys_list_entry.xml
index 3cc0bc6dc..fb092793b 100644
--- a/OpenPGP-Keychain/src/main/res/layout/import_keys_list_entry.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/import_keys_list_entry.xml
@@ -77,10 +77,11 @@
+ android:typeface="monospace"
+ android:layout_weight="1" />