aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-01-13 20:36:37 +0100
committerVincent Breitmoser <valodim@mugenguild.com>2015-01-13 20:36:37 +0100
commit4b5de13e4297d688901e8070f627a9a213097bb5 (patch)
tree641f2844c4467d928791e55559601456d2403e84
parent08ea4e1b7e0547bdc3049125817710f226550a55 (diff)
downloadopen-keychain-4b5de13e4297d688901e8070f627a9a213097bb5.tar.gz
open-keychain-4b5de13e4297d688901e8070f627a9a213097bb5.tar.bz2
open-keychain-4b5de13e4297d688901e8070f627a9a213097bb5.zip
certification of the first linked identity packet!
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/AffirmationResource.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/LinkedIdentity.java22
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/resources/GenericHttpsResource.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateHttpsStep2Fragment.java184
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep1Fragment.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep2Fragment.java1
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml1
8 files changed, 189 insertions, 45 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/AffirmationResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/AffirmationResource.java
index 45919a89a..ffe89931a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/AffirmationResource.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/AffirmationResource.java
@@ -13,13 +13,14 @@ 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.Matcher;
import java.util.regex.Pattern;
public abstract class AffirmationResource {
- protected final URI mUri;
+ protected final URI mSubUri;
protected final Set<String> mFlags;
protected final HashMap<String,String> mParams;
@@ -29,7 +30,19 @@ public abstract class AffirmationResource {
protected AffirmationResource(Set<String> flags, HashMap<String,String> params, URI uri) {
mFlags = flags;
mParams = params;
- mUri = uri;
+ mSubUri = uri;
+ }
+
+ public Set<String> getFlags () {
+ return new HashSet<String>(mFlags);
+ }
+
+ public HashMap<String,String> getParams () {
+ return new HashMap<String,String>(mParams);
+ }
+
+ public URI getSubUri () {
+ return mSubUri;
}
public static String generate (Context context, byte[] fingerprint, String nonce) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/LinkedIdentity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/LinkedIdentity.java
index 1e27b2c64..ee9933da3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/LinkedIdentity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/LinkedIdentity.java
@@ -1,12 +1,13 @@
package org.sufficientlysecure.keychain.pgp.affirmation;
import org.spongycastle.bcpg.UserAttributeSubpacket;
+import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector;
import org.spongycastle.util.Strings;
import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.util.Log;
-import java.io.Serializable;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
@@ -15,7 +16,7 @@ import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
-public class LinkedIdentity implements Serializable {
+public class LinkedIdentity {
protected byte[] mData;
public final String mNonce;
@@ -41,7 +42,7 @@ public class LinkedIdentity implements Serializable {
this(null, nonce, flags, params, subUri);
}
- public byte[] encode() {
+ public byte[] getEncoded() {
if (mData != null) {
return mData;
}
@@ -79,11 +80,14 @@ public class LinkedIdentity implements Serializable {
b.append(mSubUri);
byte[] nonceBytes = Hex.decode(mNonce);
+ if (nonceBytes.length != 12) {
+ throw new AssertionError("nonce must be 12 bytes");
+ }
byte[] data = Strings.toUTF8ByteArray(b.toString());
byte[] result = new byte[data.length+12];
System.arraycopy(nonceBytes, 0, result, 0, 12);
- System.arraycopy(data, 0, result, 12, result.length);
+ System.arraycopy(data, 0, result, 12, data.length);
return result;
}
@@ -91,7 +95,7 @@ public class LinkedIdentity implements Serializable {
/** This method parses an affirmation from a UserAttributeSubpacket, or returns null if the
* subpacket can not be parsed as a valid affirmation.
*/
- public static LinkedIdentity parseAffirmation(UserAttributeSubpacket subpacket) {
+ static LinkedIdentity parseAffirmation(UserAttributeSubpacket subpacket) {
if (subpacket.getType() != 100) {
return null;
}
@@ -148,6 +152,14 @@ public class LinkedIdentity implements Serializable {
}
+ public static LinkedIdentity fromResource (AffirmationResource res, String nonce) {
+ return new LinkedIdentity(nonce, res.getFlags(), res.getParams(), res.getSubUri());
+ }
+
+ public WrappedUserAttribute toUserAttribute () {
+ return WrappedUserAttribute.fromSubpacket(WrappedUserAttribute.UAT_LINKED_ID, getEncoded());
+ }
+
public static String generateNonce() {
// TODO make this actually random
// byte[] data = new byte[96];
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/resources/GenericHttpsResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/resources/GenericHttpsResource.java
index 8f4d0c41b..74c0689b5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/resources/GenericHttpsResource.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/affirmation/resources/GenericHttpsResource.java
@@ -9,6 +9,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.pgp.affirmation.AffirmationResource;
+import org.sufficientlysecure.keychain.pgp.affirmation.LinkedIdentity;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
@@ -38,13 +39,13 @@ public class GenericHttpsResource extends AffirmationResource {
@Override
protected String fetchResource (OperationLog log, int indent) {
- log.add(LogType.MSG_LV_FETCH, indent, mUri.toString());
+ log.add(LogType.MSG_LV_FETCH, indent, mSubUri.toString());
indent += 1;
try {
HttpsURLConnection conn = null;
- URL url = mUri.toURL();
+ URL url = mSubUri.toURL();
int status = 0;
int redirects = 0;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index fd9324992..5bface1fb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -214,6 +214,9 @@ public class PassphraseDialogActivity extends FragmentActivity {
case DIVERT_TO_CARD:
message = getString(R.string.yubikey_pin_for, userId);
break;
+ // special case: empty passphrase just returns the empty passphrase
+ case PASSPHRASE_EMPTY:
+ finishCaching("");
default:
message = "This should not happen!";
break;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateHttpsStep2Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateHttpsStep2Fragment.java
index 2f9b77f4a..eb1088989 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateHttpsStep2Fragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateHttpsStep2Fragment.java
@@ -17,6 +17,8 @@
package org.sufficientlysecure.keychain.ui.affirmations;
+import android.app.Activity;
+import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.PorterDuff;
import android.net.Uri;
@@ -24,6 +26,8 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
+import android.os.Message;
+import android.os.Messenger;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
@@ -36,7 +40,16 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
+import org.sufficientlysecure.keychain.pgp.affirmation.LinkedIdentity;
import org.sufficientlysecure.keychain.pgp.affirmation.resources.GenericHttpsResource;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
+import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.ui.EditKeyActivity;
+import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.FileHelper;
@@ -50,6 +63,7 @@ import java.net.URISyntaxException;
public class AffirmationCreateHttpsStep2Fragment extends Fragment {
private static final int REQUEST_CODE_OUTPUT = 0x00007007;
+ private static final int REQUEST_CODE_PASSPHRASE = 0x00007008;
public static final String URI = "uri", NONCE = "nonce", TEXT = "text";
@@ -63,6 +77,9 @@ public class AffirmationCreateHttpsStep2Fragment extends Fragment {
String mResourceUri;
String mResourceNonce, mResourceString;
+ // This is a resource, set AFTER it has been verified
+ GenericHttpsResource mVerifiedResource = null;
+
/**
* Creates new instance of this fragment
*/
@@ -91,11 +108,7 @@ public class AffirmationCreateHttpsStep2Fragment extends Fragment {
view.findViewById(R.id.next_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
-
- // AffirmationCreateHttpsStep2Fragment frag =
- // AffirmationCreateHttpsStep2Fragment.newInstance();
-
- // mAffirmationWizard.loadFragment(null, frag, AffirmationWizard.FRAG_ACTION_TO_RIGHT);
+ startCertify();
}
});
@@ -149,7 +162,7 @@ public class AffirmationCreateHttpsStep2Fragment extends Fragment {
public void setVerifyProgress(boolean on, Boolean success) {
mVerifyProgress.setVisibility(on ? View.VISIBLE : View.GONE);
- mVerifyImage.setVisibility(on ? View.GONE : View.VISIBLE);
+ mVerifyImage.setVisibility(on ? View.GONE : View.VISIBLE);
if (success == null) {
mVerifyStatus.setText(R.string.linked_verifying);
mVerifyImage.setImageResource(R.drawable.status_signature_unverified_cutout);
@@ -168,6 +181,46 @@ public class AffirmationCreateHttpsStep2Fragment extends Fragment {
}
}
+ private void proofSend () {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_TEXT, mResourceString);
+ sendIntent.setType("text/plain");
+ startActivity(sendIntent);
+ }
+
+ private void proofSave () {
+ String state = Environment.getExternalStorageState();
+ if (!Environment.MEDIA_MOUNTED.equals(state)) {
+ Notify.showNotify(getActivity(), "External storage not available!", Style.ERROR);
+ return;
+ }
+
+ String targetName = "pgpkey.txt";
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ File targetFile = new File(Constants.Path.APP_DIR, targetName);
+ FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file),
+ getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT);
+ } else {
+ FileHelper.saveDocument(this, "text/plain", targetName, REQUEST_CODE_OUTPUT);
+ }
+ }
+
+ private void saveFile(Uri uri) {
+ try {
+ PrintWriter out =
+ new PrintWriter(getActivity().getContentResolver().openOutputStream(uri));
+ out.print(mResourceString);
+ if (out.checkError()) {
+ Notify.showNotify(getActivity(), "Error writing file!", Style.ERROR);
+ }
+ } catch (FileNotFoundException e) {
+ Notify.showNotify(getActivity(), "File could not be opened for writing!", Style.ERROR);
+ e.printStackTrace();
+ }
+ }
+
public void proofVerify() {
setVerifyProgress(true, null);
@@ -186,6 +239,7 @@ public class AffirmationCreateHttpsStep2Fragment extends Fragment {
super.onPostExecute(result);
if (result.success()) {
setVerifyProgress(false, true);
+ mVerifiedResource = resource;
} else {
setVerifyProgress(false, false);
// on error, show error message
@@ -199,49 +253,100 @@ public class AffirmationCreateHttpsStep2Fragment extends Fragment {
}
- private void proofSend() {
- Intent sendIntent = new Intent();
- sendIntent.setAction(Intent.ACTION_SEND);
- sendIntent.putExtra(Intent.EXTRA_TEXT, mResourceString);
- sendIntent.setType("text/plain");
- startActivity(sendIntent);
- }
+ public void startCertify() {
- private void proofSave () {
- String state = Environment.getExternalStorageState();
- if (!Environment.MEDIA_MOUNTED.equals(state)) {
- Notify.showNotify(getActivity(), "External storage not available!", Style.ERROR);
+ if (mVerifiedResource == null) {
+ Notify.showNotify(getActivity(), R.string.linked_need_verify, Notify.Style.ERROR);
return;
}
- String targetName = "pgpkey.txt";
+ Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
+ intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, mAffirmationWizard.mMasterKeyId);
+ startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- File targetFile = new File(Constants.Path.APP_DIR, targetName);
- FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file),
- getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT);
- } else {
- FileHelper.saveDocument(this, "text/plain", targetName, REQUEST_CODE_OUTPUT);
- }
}
- private void saveFile(Uri uri) {
- try {
- PrintWriter out =
- new PrintWriter(getActivity().getContentResolver().openOutputStream(uri));
- out.print(mResourceString);
- if (out.checkError()) {
- Notify.showNotify(getActivity(), "Error writing file!", Style.ERROR);
+ public void certifyLinkedIdentity (String passphrase) {
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
+ getActivity(),
+ getString(R.string.progress_saving),
+ ProgressDialog.STYLE_HORIZONTAL,
+ true) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+
+ // get returned data bundle
+ Bundle returnData = message.getData();
+ if (returnData == null) {
+ return;
+ }
+ final OperationResult result =
+ returnData.getParcelable(OperationResult.EXTRA_RESULT);
+ if (result == null) {
+ return;
+ }
+
+ // if bad -> display here!
+ if (!result.success()) {
+ result.createNotify(getActivity()).show();
+ return;
+ }
+
+ result.createNotify(getActivity()).show();
+
+ // if good -> finish, return result to showkey and display there!
+ // Intent intent = new Intent();
+ // intent.putExtra(OperationResult.EXTRA_RESULT, result);
+ // getActivity().setResult(EditKeyActivity.RESULT_OK, intent);
+
+ // AffirmationCreateHttpsStep3Fragment frag =
+ // AffirmationCreateHttpsStep3Fragment.newInstance(
+ // mResourceUri, mResourceNonce, mResourceString);
+
+ // mAffirmationWizard.loadFragment(null, frag, AffirmationWizard.FRAG_ACTION_TO_RIGHT);
+
+ }
}
- } catch (FileNotFoundException e) {
- Notify.showNotify(getActivity(), "File could not be opened for writing!", Style.ERROR);
- e.printStackTrace();
- }
+ };
+
+ SaveKeyringParcel skp =
+ new SaveKeyringParcel(mAffirmationWizard.mMasterKeyId, mAffirmationWizard.mFingerprint);
+
+ WrappedUserAttribute ua =
+ LinkedIdentity.fromResource(mVerifiedResource, mResourceNonce).toUserAttribute();
+
+ skp.mAddUserAttribute.add(ua);
+
+ // Send all information needed to service to import key in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+ intent.setAction(KeychainIntentService.ACTION_EDIT_KEYRING);
+
+ // fill values for this action
+ Bundle data = new Bundle();
+ data.putString(KeychainIntentService.EDIT_KEYRING_PASSPHRASE, passphrase);
+ data.putParcelable(KeychainIntentService.EDIT_KEYRING_PARCEL, skp);
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ // show progress dialog
+ saveHandler.showProgressDialog(getActivity());
+
+ // start service with intent
+ getActivity().startService(intent);
+
}
+
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
+ // For saving a file
case REQUEST_CODE_OUTPUT:
if (data == null) {
return;
@@ -249,6 +354,13 @@ public class AffirmationCreateHttpsStep2Fragment extends Fragment {
Uri uri = data.getData();
saveFile(uri);
break;
+ case REQUEST_CODE_PASSPHRASE:
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ String passphrase =
+ data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
+ certifyLinkedIdentity(passphrase);
+ }
+ break;
}
super.onActivityResult(requestCode, resultCode, data);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep1Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep1Fragment.java
index 995823499..f52a18807 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep1Fragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep1Fragment.java
@@ -33,6 +33,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.affirmation.LinkedIdentity;
import org.sufficientlysecure.keychain.pgp.affirmation.resources.GenericHttpsResource;
import org.sufficientlysecure.keychain.pgp.affirmation.resources.TwitterResource;
+import org.sufficientlysecure.keychain.ui.CreateKeyActivity;
import org.sufficientlysecure.keychain.ui.util.Notify;
import java.io.IOException;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep2Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep2Fragment.java
index fad8cadd4..e12d2f86b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep2Fragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/affirmations/AffirmationCreateTwitterStep2Fragment.java
@@ -31,6 +31,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.CreateKeyActivity;
public class AffirmationCreateTwitterStep2Fragment extends Fragment {
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index 7477ee7c5..d8bfb86f2 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -1162,5 +1162,6 @@
<string name="linked_verify_success">Verification successful!</string>
<string name="linked_verify_error">Veriication error!</string>
<string name="linked_verify_pending">Not yet verified</string>
+ <string name="linked_need_verify">The resource needs to be verified before you can proceed!</string>
</resources>