do a TON of UI work
This commit is contained in:
@@ -114,6 +114,15 @@ public class WrappedUserAttribute implements Serializable {
|
||||
|
||||
}
|
||||
|
||||
public byte[][] getSubpackets() {
|
||||
UserAttributeSubpacket[] subpackets = mVector.toSubpacketArray();
|
||||
byte[][] ret = new byte[subpackets.length][];
|
||||
for (int i = 0; i < subpackets.length; i++) {
|
||||
ret[i] = subpackets[i].getData();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void readObjectNoData() throws ObjectStreamException {
|
||||
}
|
||||
|
||||
|
||||
@@ -19,27 +19,10 @@ import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public abstract class LinkedCookieResource {
|
||||
|
||||
protected final URI mSubUri;
|
||||
protected final Set<String> mFlags;
|
||||
protected final HashMap<String,String> mParams;
|
||||
|
||||
static Pattern magicPattern =
|
||||
Pattern.compile("\\[Verifying my PGP key: openpgp4fpr:([a-zA-Z0-9]+)#([a-zA-Z0-9]+)\\]");
|
||||
public abstract class LinkedCookieResource extends LinkedResource {
|
||||
|
||||
protected LinkedCookieResource(Set<String> flags, HashMap<String, String> params, URI uri) {
|
||||
mFlags = flags;
|
||||
mParams = params;
|
||||
mSubUri = uri;
|
||||
}
|
||||
|
||||
public Set<String> getFlags () {
|
||||
return new HashSet<String>(mFlags);
|
||||
}
|
||||
|
||||
public HashMap<String,String> getParams () {
|
||||
return new HashMap<String,String>(mParams);
|
||||
super(flags, params, uri);
|
||||
}
|
||||
|
||||
public URI toUri () {
|
||||
@@ -82,10 +65,10 @@ public abstract class LinkedCookieResource {
|
||||
return mSubUri;
|
||||
}
|
||||
|
||||
public static String generate (Context context, byte[] fingerprint, String nonce) {
|
||||
public static String generate (Context context, byte[] fingerprint, int nonce) {
|
||||
|
||||
return "[Verifying my PGP key: openpgp4fpr:"
|
||||
+ KeyFormattingUtils.convertFingerprintToHex(fingerprint) + "#" + nonce + "]";
|
||||
+ KeyFormattingUtils.convertFingerprintToHex(fingerprint) + "#" + Integer.toHexString(nonce) + "]";
|
||||
|
||||
}
|
||||
|
||||
@@ -129,7 +112,17 @@ public abstract class LinkedCookieResource {
|
||||
}
|
||||
|
||||
String candidateFp = match.group(1).toLowerCase();
|
||||
int nonceCandidate = Integer.parseInt(match.group(2).toLowerCase(), 16);
|
||||
try {
|
||||
int nonceCandidate = Integer.parseInt(match.group(2).toLowerCase(), 16);
|
||||
|
||||
if (nonce != nonceCandidate) {
|
||||
log.add(LogType.MSG_LV_NONCE_ERROR, indent);
|
||||
return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
log.add(LogType.MSG_LV_NONCE_ERROR, indent);
|
||||
return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
String fp = KeyFormattingUtils.convertFingerprintToHex(fingerprint);
|
||||
|
||||
@@ -139,72 +132,9 @@ public abstract class LinkedCookieResource {
|
||||
}
|
||||
log.add(LogType.MSG_LV_FP_OK, indent);
|
||||
|
||||
if (nonce != nonceCandidate) {
|
||||
log.add(LogType.MSG_LV_NONCE_ERROR, indent);
|
||||
return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
log.add(LogType.MSG_LV_NONCE_OK, indent);
|
||||
return new LinkedVerifyResult(LinkedVerifyResult.RESULT_OK, log);
|
||||
|
||||
}
|
||||
|
||||
protected static LinkedCookieResource fromRawLinkedId (RawLinkedIdentity id) {
|
||||
return fromUri(id.mNonce, id.mUri);
|
||||
}
|
||||
|
||||
protected static LinkedCookieResource fromUri (int nonce, URI uri) {
|
||||
|
||||
if ("pgpid".equals(uri.getScheme())) {
|
||||
Log.e(Constants.TAG, "unknown uri scheme in (suspected) linked id packet");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!uri.isOpaque()) {
|
||||
Log.e(Constants.TAG, "non-opaque uri in (suspected) linked id packet");
|
||||
return null;
|
||||
}
|
||||
|
||||
String specific = uri.getSchemeSpecificPart();
|
||||
if (!specific.contains("@")) {
|
||||
Log.e(Constants.TAG, "unknown uri scheme in linked id packet");
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] pieces = specific.split("@", 2);
|
||||
URI subUri = URI.create(pieces[1]);
|
||||
|
||||
Set<String> flags = new HashSet<String>();
|
||||
HashMap<String,String> params = new HashMap<String,String>();
|
||||
{
|
||||
String[] rawParams = pieces[0].split(";");
|
||||
for (String param : rawParams) {
|
||||
String[] p = param.split("=", 2);
|
||||
if (p.length == 1) {
|
||||
flags.add(param);
|
||||
} else {
|
||||
params.put(p[0], p[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return findResourceType(nonce, flags, params, subUri);
|
||||
|
||||
}
|
||||
|
||||
protected static LinkedCookieResource findResourceType (int nonce, Set<String> flags,
|
||||
HashMap<String,String> params,
|
||||
URI subUri) {
|
||||
|
||||
LinkedCookieResource res;
|
||||
|
||||
res = GenericHttpsResource.create(flags, params, subUri);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return new UnknownResource(flags, params, subUri);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.sufficientlysecure.keychain.pgp.linked;
|
||||
|
||||
import org.spongycastle.bcpg.UserAttributeSubpacket;
|
||||
import org.spongycastle.util.Strings;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class LinkedIdentity extends RawLinkedIdentity {
|
||||
|
||||
public final LinkedResource mResource;
|
||||
|
||||
protected LinkedIdentity(int nonce, URI uri, LinkedResource resource) {
|
||||
super(nonce, uri);
|
||||
if (resource == null) {
|
||||
throw new AssertionError("resource must not be null in a LinkedIdentity!");
|
||||
}
|
||||
mResource = resource;
|
||||
}
|
||||
|
||||
public static RawLinkedIdentity fromAttributeData(byte[] data) throws IOException {
|
||||
WrappedUserAttribute att = WrappedUserAttribute.fromData(data);
|
||||
|
||||
byte[][] subpackets = att.getSubpackets();
|
||||
if (subpackets.length >= 1) {
|
||||
return fromSubpacketData(subpackets[0]);
|
||||
}
|
||||
|
||||
throw new IOException("no subpacket data");
|
||||
}
|
||||
|
||||
/** This method parses a linked id from a UserAttributeSubpacket, or returns null if the
|
||||
* subpacket can not be parsed as a valid linked id.
|
||||
*/
|
||||
static RawLinkedIdentity fromAttributeSubpacket(UserAttributeSubpacket subpacket) {
|
||||
if (subpacket.getType() != 100) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] data = subpacket.getData();
|
||||
|
||||
return fromSubpacketData(data);
|
||||
|
||||
}
|
||||
|
||||
static RawLinkedIdentity fromSubpacketData(byte[] data) {
|
||||
|
||||
try {
|
||||
int nonce = ByteBuffer.wrap(data).getInt();
|
||||
String uriStr = Strings.fromUTF8ByteArray(Arrays.copyOfRange(data, 4, data.length));
|
||||
URI uri = URI.create(uriStr);
|
||||
|
||||
LinkedResource res = LinkedResource.fromUri(uri);
|
||||
if (res == null) {
|
||||
return new RawLinkedIdentity(nonce, uri);
|
||||
}
|
||||
|
||||
return new LinkedIdentity(nonce, uri, res);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(Constants.TAG, "error parsing uri in (suspected) linked id packet");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static RawLinkedIdentity fromResource (LinkedCookieResource res, int nonce) {
|
||||
return new RawLinkedIdentity(nonce, res.toUri());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.sufficientlysecure.keychain.pgp.linked;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.pgp.linked.resources.DnsResource;
|
||||
import org.sufficientlysecure.keychain.pgp.linked.resources.GenericHttpsResource;
|
||||
import org.sufficientlysecure.keychain.pgp.linked.resources.UnknownResource;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public abstract class LinkedResource {
|
||||
|
||||
protected final URI mSubUri;
|
||||
protected final Set<String> mFlags;
|
||||
protected final HashMap<String,String> mParams;
|
||||
|
||||
static Pattern magicPattern =
|
||||
Pattern.compile("\\[Verifying my PGP key: openpgp4fpr:([a-zA-Z0-9]+)#([a-zA-Z0-9]+)\\]");
|
||||
|
||||
protected LinkedResource(Set<String> flags, HashMap<String, String> params, URI uri) {
|
||||
mFlags = flags;
|
||||
mParams = params;
|
||||
mSubUri = uri;
|
||||
}
|
||||
|
||||
public abstract URI toUri();
|
||||
|
||||
public Set<String> getFlags () {
|
||||
return new HashSet<>(mFlags);
|
||||
}
|
||||
|
||||
public HashMap<String,String> getParams () {
|
||||
return new HashMap<>(mParams);
|
||||
}
|
||||
|
||||
protected static LinkedCookieResource fromUri (URI uri) {
|
||||
|
||||
if ("pgpid+cookie".equals(uri.getScheme())) {
|
||||
Log.e(Constants.TAG, "unknown uri scheme in (suspected) linked id packet");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!uri.isOpaque()) {
|
||||
Log.e(Constants.TAG, "non-opaque uri in (suspected) linked id packet");
|
||||
return null;
|
||||
}
|
||||
|
||||
String specific = uri.getSchemeSpecificPart();
|
||||
if (!specific.contains("@")) {
|
||||
Log.e(Constants.TAG, "unknown uri scheme in linked id packet");
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] pieces = specific.split("@", 2);
|
||||
URI subUri = URI.create(pieces[1]);
|
||||
|
||||
Set<String> flags = new HashSet<String>();
|
||||
HashMap<String,String> params = new HashMap<String,String>();
|
||||
{
|
||||
String[] rawParams = pieces[0].split(";");
|
||||
for (String param : rawParams) {
|
||||
String[] p = param.split("=", 2);
|
||||
if ("".equals(p[0])) {
|
||||
continue;
|
||||
}
|
||||
if (p.length == 1) {
|
||||
flags.add(param);
|
||||
} else {
|
||||
params.put(p[0], p[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return findResourceType(flags, params, subUri);
|
||||
|
||||
}
|
||||
|
||||
protected static LinkedCookieResource findResourceType (Set<String> flags,
|
||||
HashMap<String,String> params,
|
||||
URI subUri) {
|
||||
|
||||
LinkedCookieResource res;
|
||||
|
||||
res = GenericHttpsResource.create(flags, params, subUri);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
res = DnsResource.create(flags, params, subUri);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +1,10 @@
|
||||
package org.sufficientlysecure.keychain.pgp.linked;
|
||||
|
||||
import org.spongycastle.bcpg.UserAttributeSubpacket;
|
||||
import org.spongycastle.util.Strings;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
/** The RawLinkedIdentity contains raw parsed data from a Linked Identity subpacket. */
|
||||
public class RawLinkedIdentity {
|
||||
@@ -36,50 +28,18 @@ public class RawLinkedIdentity {
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
/** This method parses a linked id from a UserAttributeSubpacket, or returns null if the
|
||||
* subpacket can not be parsed as a valid linked id.
|
||||
*/
|
||||
static RawLinkedIdentity fromAttributeSubpacket(UserAttributeSubpacket subpacket) {
|
||||
if (subpacket.getType() != 100) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] data = subpacket.getData();
|
||||
|
||||
return fromSubpacketData(data);
|
||||
|
||||
}
|
||||
|
||||
public static RawLinkedIdentity fromSubpacketData(byte[] data) {
|
||||
|
||||
try {
|
||||
int nonce = ByteBuffer.wrap(data).getInt();
|
||||
String uri = Strings.fromUTF8ByteArray(Arrays.copyOfRange(data, 4, data.length));
|
||||
|
||||
return new RawLinkedIdentity(nonce, URI.create(uri));
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(Constants.TAG, "error parsing uri in (suspected) linked id packet");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static RawLinkedIdentity fromResource (LinkedCookieResource res, int nonce) {
|
||||
return new RawLinkedIdentity(nonce, res.toUri());
|
||||
}
|
||||
|
||||
public WrappedUserAttribute toUserAttribute () {
|
||||
return WrappedUserAttribute.fromSubpacket(WrappedUserAttribute.UAT_LINKED_ID, getEncoded());
|
||||
}
|
||||
|
||||
public static String generateNonce() {
|
||||
public static int generateNonce() {
|
||||
// TODO make this actually random
|
||||
// byte[] data = new byte[4];
|
||||
// new SecureRandom().nextBytes(data);
|
||||
// return Hex.toHexString(data);
|
||||
|
||||
// debug for now
|
||||
return "01234567";
|
||||
return 1234567;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,10 +39,11 @@ public class DnsResource extends LinkedCookieResource {
|
||||
mType = type;
|
||||
}
|
||||
|
||||
public static String generateText (Context context, byte[] fingerprint, String nonce) {
|
||||
public static String generateText (Context context, byte[] fingerprint, int nonce) {
|
||||
|
||||
return "pgpid+cookie="
|
||||
+ KeyFormattingUtils.convertFingerprintToHex(fingerprint) + ";" + nonce + "";
|
||||
+ KeyFormattingUtils.convertFingerprintToHex(fingerprint) + ";"
|
||||
+ Integer.toHexString(nonce) + "";
|
||||
|
||||
}
|
||||
|
||||
@@ -81,6 +82,10 @@ public class DnsResource extends LinkedCookieResource {
|
||||
return new DnsResource(flags, params, uri, fqdn, clazz, type);
|
||||
}
|
||||
|
||||
public String getFqdn() {
|
||||
return mFqdn;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String fetchResource (OperationLog log, int indent) {
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public class GenericHttpsResource extends LinkedCookieResource {
|
||||
super(flags, params, uri);
|
||||
}
|
||||
|
||||
public static String generateText (Context context, byte[] fingerprint, String nonce) {
|
||||
public static String generateText (Context context, byte[] fingerprint, int nonce) {
|
||||
String cookie = LinkedCookieResource.generate(context, fingerprint, nonce);
|
||||
|
||||
return String.format(context.getResources().getString(R.string.linked_id_generic_text),
|
||||
|
||||
@@ -35,7 +35,7 @@ public class TwitterResource extends LinkedCookieResource {
|
||||
super(flags, params, uri);
|
||||
}
|
||||
|
||||
public static String generateText (Context context, byte[] fingerprint, String nonce) {
|
||||
public static String generateText (Context context, byte[] fingerprint, int nonce) {
|
||||
// nothing special here for now, might change this later
|
||||
return LinkedCookieResource.generate(context, fingerprint, nonce);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user