From 1f324be24316175a111b9424a22fc5fcb6104e2b Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 5 Mar 2015 01:58:36 +0100 Subject: do a TON of UI work --- .../keychain/pgp/WrappedUserAttribute.java | 9 ++ .../keychain/pgp/linked/LinkedCookieResource.java | 100 +++----------------- .../keychain/pgp/linked/LinkedIdentity.java | 75 +++++++++++++++ .../keychain/pgp/linked/LinkedResource.java | 101 +++++++++++++++++++++ .../keychain/pgp/linked/RawLinkedIdentity.java | 44 +-------- .../keychain/pgp/linked/resources/DnsResource.java | 9 +- .../pgp/linked/resources/GenericHttpsResource.java | 2 +- .../pgp/linked/resources/TwitterResource.java | 2 +- 8 files changed, 211 insertions(+), 131 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedResource.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java index 8f967499e..49e4d9793 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java @@ -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 { } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java index 6228b29ec..fb3f2433a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedCookieResource.java @@ -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 mFlags; - protected final HashMap 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 flags, HashMap params, URI uri) { - mFlags = flags; - mParams = params; - mSubUri = uri; - } - - public Set getFlags () { - return new HashSet(mFlags); - } - - public HashMap getParams () { - return new HashMap(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 flags = new HashSet(); - HashMap params = new HashMap(); - { - 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 flags, - HashMap params, - URI subUri) { - - LinkedCookieResource res; - - res = GenericHttpsResource.create(flags, params, subUri); - if (res != null) { - return res; - } - - return new UnknownResource(flags, params, subUri); - - } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java new file mode 100644 index 000000000..f06a23681 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedIdentity.java @@ -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()); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedResource.java new file mode 100644 index 000000000..6077db606 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/LinkedResource.java @@ -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 mFlags; + protected final HashMap mParams; + + static Pattern magicPattern = + Pattern.compile("\\[Verifying my PGP key: openpgp4fpr:([a-zA-Z0-9]+)#([a-zA-Z0-9]+)\\]"); + + protected LinkedResource(Set flags, HashMap params, URI uri) { + mFlags = flags; + mParams = params; + mSubUri = uri; + } + + public abstract URI toUri(); + + public Set getFlags () { + return new HashSet<>(mFlags); + } + + public HashMap 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 flags = new HashSet(); + HashMap params = new HashMap(); + { + 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 flags, + HashMap 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; + + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/RawLinkedIdentity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/RawLinkedIdentity.java index 931f2ec6b..bfde3c3b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/RawLinkedIdentity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/RawLinkedIdentity.java @@ -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; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/DnsResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/DnsResource.java index 796e2f120..5df008ed7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/DnsResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/DnsResource.java @@ -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) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/GenericHttpsResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/GenericHttpsResource.java index a0f1cf0aa..ba94bae75 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/GenericHttpsResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/GenericHttpsResource.java @@ -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), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java index 84277380d..f6ec4f97a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/linked/resources/TwitterResource.java @@ -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); } -- cgit v1.2.3