aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src
diff options
context:
space:
mode:
Diffstat (limited to 'OpenPGP-Keychain/src')
-rw-r--r--OpenPGP-Keychain/src/com/android/crypto/CryptoError.aidl20
-rw-r--r--OpenPGP-Keychain/src/com/android/crypto/CryptoError.java76
-rw-r--r--OpenPGP-Keychain/src/com/android/crypto/CryptoServiceConnection.java73
-rw-r--r--OpenPGP-Keychain/src/com/android/crypto/CryptoSignatureResult.aidl20
-rw-r--r--OpenPGP-Keychain/src/com/android/crypto/CryptoSignatureResult.java76
-rw-r--r--OpenPGP-Keychain/src/com/android/crypto/ICryptoCallback.aidl32
-rw-r--r--OpenPGP-Keychain/src/com/android/crypto/ICryptoService.aidl78
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java92
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java196
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/RegisterActivity.java74
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java17
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java33
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java46
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java39
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java10
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java197
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java14
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java72
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java152
19 files changed, 1117 insertions, 200 deletions
diff --git a/OpenPGP-Keychain/src/com/android/crypto/CryptoError.aidl b/OpenPGP-Keychain/src/com/android/crypto/CryptoError.aidl
new file mode 100644
index 000000000..d1b941212
--- /dev/null
+++ b/OpenPGP-Keychain/src/com/android/crypto/CryptoError.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.crypto;
+
+// Declare CryptoError so AIDL can find it and knows that it implements the parcelable protocol.
+parcelable CryptoError; \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/android/crypto/CryptoError.java b/OpenPGP-Keychain/src/com/android/crypto/CryptoError.java
new file mode 100644
index 000000000..9540f4f68
--- /dev/null
+++ b/OpenPGP-Keychain/src/com/android/crypto/CryptoError.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.crypto;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class CryptoError implements Parcelable {
+ int errorId;
+ String message;
+
+ public CryptoError() {
+ }
+
+ public CryptoError(int errorId, String message) {
+ this.errorId = errorId;
+ this.message = message;
+ }
+
+ public CryptoError(CryptoError b) {
+ this.errorId = b.errorId;
+ this.message = b.message;
+ }
+
+ public int getErrorId() {
+ return errorId;
+ }
+
+ public void setErrorId(int errorId) {
+ this.errorId = errorId;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(errorId);
+ dest.writeString(message);
+ }
+
+ public static final Creator<CryptoError> CREATOR = new Creator<CryptoError>() {
+ public CryptoError createFromParcel(final Parcel source) {
+ CryptoError error = new CryptoError();
+ error.errorId = source.readInt();
+ error.message = source.readString();
+ return error;
+ }
+
+ public CryptoError[] newArray(final int size) {
+ return new CryptoError[size];
+ }
+ };
+}
diff --git a/OpenPGP-Keychain/src/com/android/crypto/CryptoServiceConnection.java b/OpenPGP-Keychain/src/com/android/crypto/CryptoServiceConnection.java
new file mode 100644
index 000000000..4d659d344
--- /dev/null
+++ b/OpenPGP-Keychain/src/com/android/crypto/CryptoServiceConnection.java
@@ -0,0 +1,73 @@
+package com.android.crypto;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.util.Log;
+
+public class CryptoServiceConnection {
+ private Context mApplicationContext;
+
+ private ICryptoService mService;
+ private boolean bound;
+ private String cryptoProviderPackageName;
+
+ private static final String TAG = "CryptoConnection";
+
+ public CryptoServiceConnection(Context context, String cryptoProviderPackageName) {
+ mApplicationContext = context.getApplicationContext();
+ this.cryptoProviderPackageName = cryptoProviderPackageName;
+ }
+
+ public ICryptoService getService() {
+ return mService;
+ }
+
+ private ServiceConnection mCryptoServiceConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mService = ICryptoService.Stub.asInterface(service);
+ Log.d(TAG, "connected to service");
+ bound = true;
+ }
+
+ public void onServiceDisconnected(ComponentName name) {
+ mService = null;
+ Log.d(TAG, "disconnected from service");
+ bound = false;
+ }
+ };
+
+ /**
+ * If not already bound, bind!
+ *
+ * @return
+ */
+ public boolean bindToService() {
+ if (mService == null && !bound) { // if not already connected
+ try {
+ Log.d(TAG, "not bound yet");
+
+ Intent serviceIntent = new Intent();
+ serviceIntent.setAction("com.android.crypto.ICryptoService");
+ serviceIntent.setPackage(cryptoProviderPackageName); // TODO: test
+ mApplicationContext.bindService(serviceIntent, mCryptoServiceConnection,
+ Context.BIND_AUTO_CREATE);
+
+ return true;
+ } catch (Exception e) {
+ Log.d(TAG, "Exception", e);
+ return false;
+ }
+ } else { // already connected
+ Log.d(TAG, "already bound... ");
+ return true;
+ }
+ }
+
+ public void unbindFromService() {
+ mApplicationContext.unbindService(mCryptoServiceConnection);
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/com/android/crypto/CryptoSignatureResult.aidl b/OpenPGP-Keychain/src/com/android/crypto/CryptoSignatureResult.aidl
new file mode 100644
index 000000000..21862c497
--- /dev/null
+++ b/OpenPGP-Keychain/src/com/android/crypto/CryptoSignatureResult.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.crypto;
+
+// Declare CryptoSignatureResult so AIDL can find it and knows that it implements the parcelable protocol.
+parcelable CryptoSignatureResult; \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/android/crypto/CryptoSignatureResult.java b/OpenPGP-Keychain/src/com/android/crypto/CryptoSignatureResult.java
new file mode 100644
index 000000000..87f5f43b5
--- /dev/null
+++ b/OpenPGP-Keychain/src/com/android/crypto/CryptoSignatureResult.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.crypto;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class CryptoSignatureResult implements Parcelable {
+ String signatureUserId;
+
+ boolean signature;
+ boolean signatureSuccess;
+ boolean signatureUnknown;
+
+ public CryptoSignatureResult() {
+
+ }
+
+ public CryptoSignatureResult(String signatureUserId, boolean signature,
+ boolean signatureSuccess, boolean signatureUnknown) {
+ this.signatureUserId = signatureUserId;
+
+ this.signature = signature;
+ this.signatureSuccess = signatureSuccess;
+ this.signatureUnknown = signatureUnknown;
+ }
+
+ public CryptoSignatureResult(CryptoSignatureResult b) {
+ this.signatureUserId = b.signatureUserId;
+
+ this.signature = b.signature;
+ this.signatureSuccess = b.signatureSuccess;
+ this.signatureUnknown = b.signatureUnknown;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(signatureUserId);
+
+ dest.writeByte((byte) (signature ? 1 : 0));
+ dest.writeByte((byte) (signatureSuccess ? 1 : 0));
+ dest.writeByte((byte) (signatureUnknown ? 1 : 0));
+ }
+
+ public static final Creator<CryptoSignatureResult> CREATOR = new Creator<CryptoSignatureResult>() {
+ public CryptoSignatureResult createFromParcel(final Parcel source) {
+ CryptoSignatureResult vr = new CryptoSignatureResult();
+ vr.signatureUserId = source.readString();
+ vr.signature = source.readByte() == 1;
+ vr.signatureSuccess = source.readByte() == 1;
+ vr.signatureUnknown = source.readByte() == 1;
+ return vr;
+ }
+
+ public CryptoSignatureResult[] newArray(final int size) {
+ return new CryptoSignatureResult[size];
+ }
+ };
+}
diff --git a/OpenPGP-Keychain/src/com/android/crypto/ICryptoCallback.aidl b/OpenPGP-Keychain/src/com/android/crypto/ICryptoCallback.aidl
new file mode 100644
index 000000000..af6587c04
--- /dev/null
+++ b/OpenPGP-Keychain/src/com/android/crypto/ICryptoCallback.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.crypto;
+
+import com.android.crypto.CryptoSignatureResult;
+import com.android.crypto.CryptoError;
+
+interface ICryptoCallback {
+
+ oneway void onEncryptSignSuccess(in byte[] outputBytes);
+
+ oneway void onDecryptVerifySuccess(in byte[] outputBytes, in CryptoSignatureResult signatureResult);
+
+
+ oneway void onError(in CryptoError error);
+
+ oneway void onActivityRequired(in Intent intent);
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/android/crypto/ICryptoService.aidl b/OpenPGP-Keychain/src/com/android/crypto/ICryptoService.aidl
new file mode 100644
index 000000000..05baa16e0
--- /dev/null
+++ b/OpenPGP-Keychain/src/com/android/crypto/ICryptoService.aidl
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.crypto;
+
+import com.android.crypto.ICryptoCallback;
+
+/**
+ * All methods are oneway, which means they are asynchronous and non-blocking.
+ * Results are returned to the callback, which has to be implemented on client side.
+ */
+interface ICryptoService {
+
+ /**
+ * Encrypt
+ *
+ * @param inputBytes
+ * Byte array you want to encrypt
+ * @param encryptionKeyIds
+ * Ids of public keys used for encryption
+ * @param handler
+ * Results are returned to this Handler after successful encryption
+ */
+ oneway void encrypt(in byte[] inputBytes, in String[] encryptionUserIds, in ICryptoCallback callback);
+
+ /**
+ * Encrypt and sign
+ *
+ *
+ *
+ * @param inputBytes
+ * Byte array you want to encrypt
+ * @param signatureKeyId
+ * Key id of key to sign with
+ * @param handler
+ * Results are returned to this Handler after successful encryption and signing
+ */
+ oneway void encryptAndSign(in byte[] inputBytes, in String[] encryptionUserIds, String signatureUserId, in ICryptoCallback callback);
+
+ /**
+ * Sign
+ *
+ *
+ *
+ * @param inputBytes
+ * Byte array you want to encrypt
+ * @param signatureId
+ *
+ * @param handler
+ * Results are returned to this Handler after successful encryption and signing
+ */
+ oneway void sign(in byte[] inputBytes, String signatureUserId, in ICryptoCallback callback);
+
+ /**
+ * Decrypts and verifies given input bytes. If no signature is present this method
+ * will only decrypt.
+ *
+ * @param inputBytes
+ * Byte array you want to decrypt and verify
+ * @param handler
+ * Handler where to return results to after successful encryption
+ */
+ oneway void decryptAndVerify(in byte[] inputBytes, in ICryptoCallback callback);
+
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java
new file mode 100644
index 000000000..b1d248e42
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoActivity.java
@@ -0,0 +1,92 @@
+package org.sufficientlysecure.keychain.crypto_provider;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.helper.PgpMain;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
+import org.sufficientlysecure.keychain.util.Log;
+
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class CryptoActivity extends SherlockFragmentActivity {
+
+ public static final String ACTION_CACHE_PASSPHRASE = "org.sufficientlysecure.keychain.CRYPTO_CACHE_PASSPHRASE";
+
+ public static final String EXTRA_SECRET_KEY_ID = "secret_key_id";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ handleActions(getIntent());
+ }
+
+ protected void handleActions(Intent intent) {
+
+ // TODO: Important: Check if calling package is in list!
+
+ String action = intent.getAction();
+ Bundle extras = intent.getExtras();
+
+ if (extras == null) {
+ extras = new Bundle();
+ }
+
+ /**
+ * com.android.crypto actions
+ */
+ if (ACTION_CACHE_PASSPHRASE.equals(action)) {
+ long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID);
+
+ showPassphraseDialog(secretKeyId);
+ } else {
+ Log.e(Constants.TAG, "Wrong action!");
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ }
+
+ /**
+ * Shows passphrase dialog to cache a new passphrase the user enters for using it later for
+ * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks
+ * for a symmetric passphrase
+ */
+ private void showPassphraseDialog(long secretKeyId) {
+ // Message is received after passphrase is cached
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
+ setResult(RESULT_OK);
+ finish();
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+
+ try {
+ PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this,
+ messenger, secretKeyId);
+
+ passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
+ } catch (PgpMain.PgpGeneralException e) {
+ Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
+ // send message to handler to start encryption directly
+ returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
+ }
+ }
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java
new file mode 100644
index 000000000..1a57a457d
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/CryptoService.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.sufficientlysecure.keychain.crypto_provider;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.helper.PgpMain;
+import org.sufficientlysecure.keychain.util.InputData;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+
+import com.android.crypto.CryptoError;
+import com.android.crypto.ICryptoCallback;
+import com.android.crypto.ICryptoService;
+import com.android.crypto.CryptoSignatureResult;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+public class CryptoService extends Service {
+ Context mContext;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mContext = this;
+ Log.d(Constants.TAG, "CryptoService, onCreate()");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.d(Constants.TAG, "CryptoService, onDestroy()");
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ private synchronized void decryptAndVerifySafe(byte[] inputBytes, ICryptoCallback callback)
+ throws RemoteException {
+ try {
+ // build InputData and write into OutputStream
+ InputStream inputStream = new ByteArrayInputStream(inputBytes);
+ long inputLength = inputBytes.length;
+ InputData inputData = new InputData(inputStream, inputLength);
+
+ OutputStream outputStream = new ByteArrayOutputStream();
+
+ long secretKeyId = PgpMain.getDecryptionKeyId(mContext, inputStream);
+ if (secretKeyId == Id.key.none) {
+ throw new PgpMain.PgpGeneralException(getString(R.string.error_noSecretKeyFound));
+ }
+
+ Log.d(Constants.TAG, "Got input:\n"+new String(inputBytes));
+
+ Log.d(Constants.TAG, "secretKeyId " + secretKeyId);
+
+ String passphrase = PassphraseCacheService.getCachedPassphrase(mContext, secretKeyId);
+
+ if (passphrase == null) {
+ Log.d(Constants.TAG, "No passphrase! Activity required!");
+ // No passphrase cached for this ciphertext! Intent required to cache
+ // passphrase!
+ Intent intent = new Intent(CryptoActivity.ACTION_CACHE_PASSPHRASE);
+ intent.putExtra(CryptoActivity.EXTRA_SECRET_KEY_ID, secretKeyId);
+ callback.onActivityRequired(intent);
+ return;
+ }
+
+ // if (signedOnly) {
+ // resultData = PgpMain.verifyText(this, this, inputData, outStream,
+ // lookupUnknownKey);
+ // } else {
+ // resultData = PgpMain.decryptAndVerify(this, this, inputData, outStream,
+ // PassphraseCacheService.getCachedPassphrase(this, secretKeyId),
+ // assumeSymmetricEncryption);
+ // }
+
+ Bundle outputBundle = PgpMain.decryptAndVerify(mContext, null, inputData, outputStream,
+ passphrase, false);
+
+ outputStream.close();
+
+ byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray();
+
+ // get signature informations from bundle
+ boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE);
+ long signatureKeyId = outputBundle
+ .getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID);
+ String signatureUserId = outputBundle
+ .getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID);
+ boolean signatureSuccess = outputBundle
+ .getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS);
+ boolean signatureUnknown = outputBundle
+ .getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN);
+
+ CryptoSignatureResult sigResult = new CryptoSignatureResult(signatureUserId, signature,
+ signatureSuccess, signatureUnknown);
+
+ // return over handler on client side
+ callback.onDecryptVerifySuccess(outputBytes, sigResult);
+ } catch (Exception e) {
+ Log.e(Constants.TAG, "KeychainService, Exception!", e);
+
+ try {
+ callback.onError(new CryptoError(0, e.getMessage()));
+ } catch (Exception t) {
+ Log.e(Constants.TAG, "Error returning exception to client", t);
+ }
+ }
+ }
+
+ private final ICryptoService.Stub mBinder = new ICryptoService.Stub() {
+
+ @Override
+ public void encrypt(byte[] inputBytes, String[] encryptionUserIds, ICryptoCallback callback)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void encryptAndSign(byte[] inputBytes, String[] encryptionUserIds,
+ String signatureUserId, ICryptoCallback callback) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void sign(byte[] inputBytes, String signatureUserId, ICryptoCallback callback)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void decryptAndVerify(byte[] inputBytes, ICryptoCallback callback)
+ throws RemoteException {
+ decryptAndVerifySafe(inputBytes, callback);
+ }
+
+ };
+
+ // /**
+ // * As we can not throw an exception through Android RPC, we assign identifiers to the
+ // exception
+ // * types.
+ // *
+ // * @param e
+ // * @return
+ // */
+ // private int getExceptionId(Exception e) {
+ // if (e instanceof NoSuchProviderException) {
+ // return 0;
+ // } else if (e instanceof NoSuchAlgorithmException) {
+ // return 1;
+ // } else if (e instanceof SignatureException) {
+ // return 2;
+ // } else if (e instanceof IOException) {
+ // return 3;
+ // } else if (e instanceof PgpGeneralException) {
+ // return 4;
+ // } else if (e instanceof PGPException) {
+ // return 5;
+ // } else {
+ // return -1;
+ // }
+ // }
+
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/RegisterActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/RegisterActivity.java
new file mode 100644
index 000000000..39b29f9a0
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/crypto_provider/RegisterActivity.java
@@ -0,0 +1,74 @@
+package org.sufficientlysecure.keychain.crypto_provider;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.util.Log;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class RegisterActivity extends Activity {
+
+ public static final String ACTION_REGISTER = "com.android.crypto.REGISTER";
+
+ public static final String EXTRA_PACKAGE_NAME = "packageName";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ handleActions(getIntent());
+ }
+
+ protected void handleActions(Intent intent) {
+ String action = intent.getAction();
+ Bundle extras = intent.getExtras();
+
+ if (extras == null) {
+ extras = new Bundle();
+ }
+
+ final String callingPackageName = this.getCallingPackage();
+
+ /**
+ * com.android.crypto actions
+ */
+ if (ACTION_REGISTER.equals(action)) {
+ setContentView(R.layout.register_crypto_consumer_activity);
+
+ Button allowButton = (Button) findViewById(R.id.register_crypto_consumer_allow);
+ Button disallowButton = (Button) findViewById(R.id.register_crypto_consumer_disallow);
+
+ allowButton.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ ProviderHelper.addCryptoConsumer(RegisterActivity.this, callingPackageName);
+ Intent data = new Intent();
+ data.putExtra(EXTRA_PACKAGE_NAME, "org.sufficientlysecure.keychain");
+
+ setResult(RESULT_OK, data);
+ finish();
+ }
+ });
+
+ disallowButton.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ });
+
+ } else {
+ Log.e(Constants.TAG, "Please use com.android.crypto.REGISTER as intent action!");
+ finish();
+ }
+ }
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
index b284eccaa..46928c6fa 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -53,6 +53,10 @@ public class KeychainContract {
String RANK = "rank";
}
+ interface CryptoConsumersColumns {
+ String PACKAGE_NAME = "package_name";
+ }
+
public static final class KeyTypes {
public static final int PUBLIC = 0;
public static final int SECRET = 1;
@@ -78,6 +82,8 @@ public class KeychainContract {
public static final String PATH_USER_IDS = "user_ids";
public static final String PATH_KEYS = "keys";
+ public static final String BASE_CRYPTO_CONSUMERS = "crypto_consumers";
+
public static class KeyRings implements KeyRingsColumns, BaseColumns {
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
.appendPath(BASE_KEY_RINGS).build();
@@ -207,6 +213,17 @@ public class KeychainContract {
}
}
+ public static class CryptoConsumers implements CryptoConsumersColumns, BaseColumns {
+ public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
+ .appendPath(BASE_CRYPTO_CONSUMERS).build();
+
+ /** Use if multiple items get returned */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.crypto_consumers";
+
+ /** Use if a single item is returned */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.crypto_consumers";
+ }
+
public static class DataStream {
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
.appendPath(BASE_DATA).build();
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index ef95ce7f7..f30292b52 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.provider;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumersColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns;
@@ -28,15 +29,15 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
-
public class KeychainDatabase extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "apg.db";
- private static final int DATABASE_VERSION = 4;
+ private static final int DATABASE_VERSION = 5;
public interface Tables {
String KEY_RINGS = "key_rings";
String KEYS = "keys";
String USER_IDS = "user_ids";
+ String CRYPTO_CONSUMERS = "crypto_consumers";
}
private static final String CREATE_KEY_RINGS = "CREATE TABLE IF NOT EXISTS " + Tables.KEY_RINGS
@@ -48,13 +49,13 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KeysColumns.KEY_ID
+ " INT64, " + KeysColumns.TYPE + " INTEGER, " + KeysColumns.IS_MASTER_KEY
+ " INTEGER, " + KeysColumns.ALGORITHM + " INTEGER, " + KeysColumns.KEY_SIZE
- + " INTEGER, " + KeysColumns.CAN_CERTIFY
- + " INTEGER, " + KeysColumns.CAN_SIGN + " INTEGER, " + KeysColumns.CAN_ENCRYPT
- + " INTEGER, " + KeysColumns.IS_REVOKED + " INTEGER, " + KeysColumns.CREATION
- + " INTEGER, " + KeysColumns.EXPIRY + " INTEGER, " + KeysColumns.KEY_DATA + " BLOB,"
- + KeysColumns.RANK + " INTEGER, " + KeysColumns.KEY_RING_ROW_ID
- + " INTEGER NOT NULL, FOREIGN KEY(" + KeysColumns.KEY_RING_ROW_ID + ") REFERENCES "
- + Tables.KEY_RINGS + "(" + BaseColumns._ID + ") ON DELETE CASCADE)";
+ + " INTEGER, " + KeysColumns.CAN_CERTIFY + " INTEGER, " + KeysColumns.CAN_SIGN
+ + " INTEGER, " + KeysColumns.CAN_ENCRYPT + " INTEGER, " + KeysColumns.IS_REVOKED
+ + " INTEGER, " + KeysColumns.CREATION + " INTEGER, " + KeysColumns.EXPIRY
+ + " INTEGER, " + KeysColumns.KEY_DATA + " BLOB," + KeysColumns.RANK + " INTEGER, "
+ + KeysColumns.KEY_RING_ROW_ID + " INTEGER NOT NULL, FOREIGN KEY("
+ + KeysColumns.KEY_RING_ROW_ID + ") REFERENCES " + Tables.KEY_RINGS + "("
+ + BaseColumns._ID + ") ON DELETE CASCADE)";
private static final String CREATE_USER_IDS = "CREATE TABLE IF NOT EXISTS " + Tables.USER_IDS
+ " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
@@ -63,6 +64,11 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ UserIdsColumns.KEY_RING_ROW_ID + ") REFERENCES " + Tables.KEY_RINGS + "("
+ BaseColumns._ID + ") ON DELETE CASCADE)";
+ private static final String CREATE_CRYPTO_CONSUMERS = "CREATE TABLE IF NOT EXISTS "
+ + Tables.CRYPTO_CONSUMERS + " (" + BaseColumns._ID
+ + " INTEGER PRIMARY KEY AUTOINCREMENT, " + CryptoConsumersColumns.PACKAGE_NAME
+ + " TEXT UNIQUE)";
+
KeychainDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@@ -74,6 +80,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
db.execSQL(CREATE_KEY_RINGS);
db.execSQL(CREATE_KEYS);
db.execSQL(CREATE_USER_IDS);
+ db.execSQL(CREATE_CRYPTO_CONSUMERS);
}
@Override
@@ -95,9 +102,13 @@ public class KeychainDatabase extends SQLiteOpenHelper {
switch (version) {
case 3:
- db.execSQL("ALTER TABLE " + Tables.KEYS + " ADD COLUMN " + KeysColumns.CAN_CERTIFY + " INTEGER DEFAULT 0;");
- db.execSQL("UPDATE " + Tables.KEYS + " SET " + KeysColumns.CAN_CERTIFY + " = 1 WHERE " + KeysColumns.IS_MASTER_KEY + "= 1;");
+ db.execSQL("ALTER TABLE " + Tables.KEYS + " ADD COLUMN " + KeysColumns.CAN_CERTIFY
+ + " INTEGER DEFAULT 0;");
+ db.execSQL("UPDATE " + Tables.KEYS + " SET " + KeysColumns.CAN_CERTIFY
+ + " = 1 WHERE " + KeysColumns.IS_MASTER_KEY + "= 1;");
break;
+ case 4:
+ db.execSQL(CREATE_CRYPTO_CONSUMERS);
default:
break;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java
index c63d9e772..49286b9ce 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -23,6 +23,7 @@ import java.util.Arrays;
import java.util.HashMap;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes;
@@ -80,7 +81,9 @@ public class KeychainProvider extends ContentProvider {
private static final int SECRET_KEY_RING_USER_ID = 221;
private static final int SECRET_KEY_RING_USER_ID_BY_ROW_ID = 222;
- private static final int DATA_STREAM = 301;
+ private static final int CRYPTO_CONSUMERS = 301;
+
+ // private static final int DATA_STREAM = 401;
protected boolean mInternalProvider;
protected UriMatcher mUriMatcher;
@@ -126,8 +129,7 @@ public class KeychainProvider extends ContentProvider {
PUBLIC_KEY_RING_BY_EMAILS);
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
+ KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_EMAILS,
- PUBLIC_KEY_RING_BY_EMAILS); // without emails
- // specified
+ PUBLIC_KEY_RING_BY_EMAILS); // without emails specified
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
+ KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_LIKE_EMAIL + "/*",
PUBLIC_KEY_RING_BY_LIKE_EMAIL);
@@ -189,8 +191,7 @@ public class KeychainProvider extends ContentProvider {
SECRET_KEY_RING_BY_EMAILS);
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
+ KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_EMAILS,
- SECRET_KEY_RING_BY_EMAILS); // without emails
- // specified
+ SECRET_KEY_RING_BY_EMAILS); // without emails specified
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
+ KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_LIKE_EMAIL + "/*",
SECRET_KEY_RING_BY_LIKE_EMAIL);
@@ -226,13 +227,18 @@ public class KeychainProvider extends ContentProvider {
SECRET_KEY_RING_USER_ID_BY_ROW_ID);
/**
+ * Crypto Consumers
+ */
+ matcher.addURI(authority, KeychainContract.BASE_CRYPTO_CONSUMERS, CRYPTO_CONSUMERS);
+
+ /**
* data stream
*
* <pre>
* data / _
* </pre>
*/
- matcher.addURI(authority, KeychainContract.BASE_DATA + "/*", DATA_STREAM);
+ // matcher.addURI(authority, KeychainContract.BASE_DATA + "/*", DATA_STREAM);
return matcher;
}
@@ -284,6 +290,9 @@ public class KeychainProvider extends ContentProvider {
case SECRET_KEY_RING_USER_ID_BY_ROW_ID:
return UserIds.CONTENT_ITEM_TYPE;
+ case CRYPTO_CONSUMERS:
+ return CryptoConsumers.CONTENT_TYPE;
+
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
@@ -591,6 +600,11 @@ public class KeychainProvider extends ContentProvider {
qb.appendWhereEscapeString(uri.getLastPathSegment());
break;
+
+ case CRYPTO_CONSUMERS:
+ qb.setTables(Tables.CRYPTO_CONSUMERS);
+
+ break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
@@ -869,16 +883,16 @@ public class KeychainProvider extends ContentProvider {
return BaseColumns._ID + "=" + rowId + andForeignKeyRing + andSelection;
}
- @Override
- public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
- int match = mUriMatcher.match(uri);
- if (match != DATA_STREAM) {
- throw new FileNotFoundException();
- }
- String fileName = uri.getLastPathSegment();
- File file = new File(getContext().getFilesDir().getAbsolutePath(), fileName);
- return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
- }
+ // @Override
+ // public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ // int match = mUriMatcher.match(uri);
+ // if (match != DATA_STREAM) {
+ // throw new FileNotFoundException();
+ // }
+ // String fileName = uri.getLastPathSegment();
+ // File file = new File(getContext().getFilesDir().getAbsolutePath(), fileName);
+ // return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
+ // }
/**
* This broadcast is send system wide to inform other application that a keyring was inserted,
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 2665456ea..57d3b54d6 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -31,6 +31,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.helper.PgpConversionHelper;
import org.sufficientlysecure.keychain.helper.PgpHelper;
import org.sufficientlysecure.keychain.helper.PgpMain;
+import org.sufficientlysecure.keychain.provider.KeychainContract.CryptoConsumers;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
@@ -516,10 +517,13 @@ public class ProviderHelper {
* @return
*/
private static boolean getMasterKeyCanSign(Context context, Uri queryUri, long keyRingRowId) {
- String[] projection = new String[] { KeyRings.MASTER_KEY_ID, "(SELECT COUNT(sign_keys." +
- Keys._ID + ") FROM " + Tables.KEYS + " AS sign_keys WHERE sign_keys." + Keys.KEY_RING_ROW_ID + " = "
- + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID + " AND sign_keys."
- + Keys.CAN_SIGN + " = '1' AND " + Keys.IS_MASTER_KEY + " = 1) AS sign", };
+ String[] projection = new String[] {
+ KeyRings.MASTER_KEY_ID,
+ "(SELECT COUNT(sign_keys." + Keys._ID + ") FROM " + Tables.KEYS
+ + " AS sign_keys WHERE sign_keys." + Keys.KEY_RING_ROW_ID + " = "
+ + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID
+ + " AND sign_keys." + Keys.CAN_SIGN + " = '1' AND " + Keys.IS_MASTER_KEY
+ + " = 1) AS sign", };
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(queryUri, projection, null, null, null);
@@ -713,4 +717,31 @@ public class ProviderHelper {
return cursor;
}
+
+ public static ArrayList<String> getCryptoConsumers(Context context) {
+ Cursor cursor = context.getContentResolver().query(CryptoConsumers.CONTENT_URI, null, null,
+ null, null);
+
+ ArrayList<String> packageNames = new ArrayList<String>();
+ if (cursor != null) {
+ int packageNameCol = cursor.getColumnIndex(CryptoConsumers.PACKAGE_NAME);
+ if (cursor.moveToFirst()) {
+ do {
+ packageNames.add(cursor.getString(packageNameCol));
+ } while (cursor.moveToNext());
+ }
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+
+ return packageNames;
+ }
+
+ public static void addCryptoConsumer(Context context, String packageName) {
+ ContentValues values = new ContentValues();
+ values.put(CryptoConsumers.PACKAGE_NAME, packageName);
+ context.getContentResolver().insert(CryptoConsumers.CONTENT_URI, values);
+ }
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index 1d48278eb..711cdae24 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -56,7 +56,6 @@ import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
-
/**
* This Service contains all important long lasting operations for APG. It receives Intents with
* data from the activities or other apps, queues these intents, executes them, and stops itself
@@ -541,11 +540,12 @@ public class KeychainIntentService extends IntentService implements ProgressDial
/* Operation */
if (!canSign) {
- PgpMain.changeSecretKeyPassphrase(this, ProviderHelper.getPGPSecretKeyRingByKeyId(this, masterKeyId),
- oldPassPhrase, newPassPhrase, this);
+ PgpMain.changeSecretKeyPassphrase(this,
+ ProviderHelper.getPGPSecretKeyRingByKeyId(this, masterKeyId),
+ oldPassPhrase, newPassPhrase, this);
} else {
- PgpMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase,
- newPassPhrase, this);
+ PgpMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId,
+ oldPassPhrase, newPassPhrase, this);
}
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index eb1232769..d11b8e92a 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,8 +19,12 @@ package org.sufficientlysecure.keychain.service;
import java.util.Date;
import java.util.HashMap;
+import org.spongycastle.openpgp.PGPException;
+import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
+import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.PgpHelper;
@@ -35,27 +39,39 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
import android.util.Log;
public class PassphraseCacheService extends Service {
public static final String TAG = Constants.TAG + ": PassphraseCacheService";
+ public static final String ACTION_PASSPHRASE_CACHE_ADD = Constants.INTENT_PREFIX
+ + "PASSPHRASE_CACHE_ADD";
+ public static final String ACTION_PASSPHRASE_CACHE_GET = Constants.INTENT_PREFIX
+ + "PASSPHRASE_CACHE_GET";
+
public static final String BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE = Constants.INTENT_PREFIX
- + "PASSPHRASE_CACHE_SERVICE";
+ + "PASSPHRASE_CACHE_BROADCAST";
public static final String EXTRA_TTL = "ttl";
public static final String EXTRA_KEY_ID = "keyId";
public static final String EXTRA_PASSPHRASE = "passphrase";
+ public static final String EXTRA_MESSENGER = "messenger";
private static final int REQUEST_ID = 0;
private static final long DEFAULT_TTL = 15;
private BroadcastReceiver mIntentReceiver;
- // This is static to be easily retrieved by getCachedPassphrase() without the need of callback
- // functions
- private static HashMap<Long, String> mPassphraseCache = new HashMap<Long, String>();
+ private HashMap<Long, String> mPassphraseCache = new HashMap<Long, String>();
+
+ Context mContext;
/**
* This caches a new passphrase by sending a new command to the service. An android service is
@@ -70,6 +86,7 @@ public class PassphraseCacheService extends Service {
Log.d(TAG, "cacheNewPassphrase() for " + keyId);
Intent intent = new Intent(context, PassphraseCacheService.class);
+ intent.setAction(ACTION_PASSPHRASE_CACHE_ADD);
intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl());
intent.putExtra(EXTRA_PASSPHRASE, passphrase);
intent.putExtra(EXTRA_KEY_ID, keyId);
@@ -78,17 +95,65 @@ public class PassphraseCacheService extends Service {
}
/**
- * Gets a cached passphrase from memory
+ * Gets a cached passphrase from memory, blocking method
*
* @param context
* @param keyId
* @return
*/
public static String getCachedPassphrase(Context context, long keyId) {
+ Log.d(TAG, "getCachedPassphrase() get masterKeyId for " + keyId);
+ Intent intent = new Intent(context, PassphraseCacheService.class);
+ intent.setAction(ACTION_PASSPHRASE_CACHE_GET);
+
+ final Object mutex = new Object();
+ final Bundle returnBundle = new Bundle();
+
+ HandlerThread handlerThread = new HandlerThread("getPassphrase");
+ handlerThread.start();
+ Handler returnHandler = new Handler(handlerThread.getLooper()) {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.obj != null) {
+ String passphrase = ((Bundle) message.obj).getString(EXTRA_PASSPHRASE);
+ returnBundle.putString(EXTRA_PASSPHRASE, passphrase);
+ }
+ synchronized (mutex) {
+ mutex.notify();
+ }
+ getLooper().quit();
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+ intent.putExtra(EXTRA_KEY_ID, keyId);
+ intent.putExtra(EXTRA_MESSENGER, messenger);
+ // send intent to this service
+ context.startService(intent);
+
+ // Wait on mutex until passphrase is returned to handlerThread
+ synchronized (mutex) {
+ try {
+ mutex.wait(3000);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ if (returnBundle.containsKey(EXTRA_PASSPHRASE)) {
+ return returnBundle.getString(EXTRA_PASSPHRASE);
+ } else {
+ return null;
+ }
+ }
+
+ private String getCachedPassphraseImpl(long keyId) {
+ Log.d(TAG, "getCachedPassphraseImpl() get masterKeyId for " + keyId);
+
// try to get master key id which is used as an identifier for cached passphrases
long masterKeyId = keyId;
if (masterKeyId != Id.key.symmetric) {
- PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, keyId);
+ PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(this, keyId);
if (keyRing == null) {
return null;
}
@@ -98,20 +163,60 @@ public class PassphraseCacheService extends Service {
}
masterKeyId = masterKey.getKeyID();
}
+ Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId" + masterKeyId);
// get cached passphrase
String cachedPassphrase = mPassphraseCache.get(masterKeyId);
if (cachedPassphrase == null) {
+ // TODO: fix!
+ // check if secret key has a passphrase
+ // if (!hasPassphrase(context, masterKeyId)) {
+ // // cache empty passphrase
+ // addCachedPassphrase(context, masterKeyId, "");
+ // return "";
+ // } else {
return null;
+ // }
}
// set it again to reset the cache life cycle
Log.d(TAG, "Cache passphrase again when getting it!");
- addCachedPassphrase(context, masterKeyId, cachedPassphrase);
+ addCachedPassphrase(this, masterKeyId, cachedPassphrase);
return cachedPassphrase;
}
/**
+ * Checks if key has a passphrase.
+ *
+ * @param secretKeyId
+ * @return true if it has a passphrase
+ */
+ public static boolean hasPassphrase(Context context, long secretKeyId) {
+ // check if the key has no passphrase
+ try {
+ PGPSecretKey secretKey = PgpHelper.getMasterKey(ProviderHelper
+ .getPGPSecretKeyRingByKeyId(context, secretKeyId));
+
+ Log.d(Constants.TAG, "Check if key has no passphrase...");
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ "SC").build("".toCharArray());
+ PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
+ if (testKey != null) {
+ Log.d(Constants.TAG, "Key has no passphrase! Caches empty passphrase!");
+
+ // cache empty passphrase
+ PassphraseCacheService.addCachedPassphrase(context, secretKey.getKeyID(), "");
+
+ return false;
+ }
+ } catch (PGPException e) {
+ // silently catch
+ }
+
+ return true;
+ }
+
+ /**
* Register BroadcastReceiver that is unregistered when service is destroyed. This
* BroadcastReceiver hears on intents with ACTION_PASSPHRASE_CACHE_SERVICE to then timeout
* specific passphrases in memory.
@@ -154,11 +259,6 @@ public class PassphraseCacheService extends Service {
return sender;
}
- @Override
- public void onCreate() {
- Log.d(TAG, "onCreate()");
- }
-
/**
* Executed when service is started by intent
*/
@@ -169,20 +269,41 @@ public class PassphraseCacheService extends Service {
// register broadcastreceiver
registerReceiver();
- if (intent != null) {
- long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL);
- long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
- String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE);
-
- Log.d(TAG, "Received intent in onStartCommand() with keyId: " + keyId + ", ttl: " + ttl);
-
- // add keyId and passphrase to memory
- mPassphraseCache.put(keyId, passphrase);
-
- // register new alarm with keyId for this passphrase
- long triggerTime = new Date().getTime() + (ttl * 1000);
- AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
- am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId));
+ if (intent != null && intent.getAction() != null) {
+ if (ACTION_PASSPHRASE_CACHE_ADD.equals(intent.getAction())) {
+ long ttl = intent.getLongExtra(EXTRA_TTL, DEFAULT_TTL);
+ long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
+ String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE);
+
+ Log.d(TAG,
+ "Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with keyId: "
+ + keyId + ", ttl: " + ttl);
+
+ // add keyId and passphrase to memory
+ mPassphraseCache.put(keyId, passphrase);
+
+ // register new alarm with keyId for this passphrase
+ long triggerTime = new Date().getTime() + (ttl * 1000);
+ AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
+ am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId));
+ } else if (ACTION_PASSPHRASE_CACHE_GET.equals(intent.getAction())) {
+ long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
+ Messenger messenger = intent.getParcelableExtra(EXTRA_MESSENGER);
+
+ String passphrase = getCachedPassphraseImpl(keyId);
+
+ Message msg = Message.obtain();
+ Bundle bundle = new Bundle();
+ bundle.putString(EXTRA_PASSPHRASE, passphrase);
+ msg.obj = bundle;
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ Log.e(Constants.TAG, "Sending message failed", e);
+ }
+ } else {
+ Log.e(Constants.TAG, "Intent or Intent Action not supported!");
+ }
}
return START_STICKY;
@@ -198,7 +319,7 @@ public class PassphraseCacheService extends Service {
// remove passphrase corresponding to keyId from memory
mPassphraseCache.remove(keyId);
- Log.d(TAG, "Timeout of " + keyId + ", removed from memory!");
+ Log.d(TAG, "Timeout of keyId " + keyId + ", removed from memory!");
// stop whole service if no cached passphrases remaining
if (mPassphraseCache.isEmpty()) {
@@ -208,12 +329,25 @@ public class PassphraseCacheService extends Service {
}
@Override
+ public void onCreate() {
+ super.onCreate();
+ mContext = this;
+ Log.d(Constants.TAG, "PassphraseCacheService, onCreate()");
+ }
+
+ @Override
public void onDestroy() {
- Log.d(TAG, "onDestroy()");
+ super.onDestroy();
+ Log.d(Constants.TAG, "PassphraseCacheService, onDestroy()");
unregisterReceiver(mIntentReceiver);
}
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
public class PassphraseCacheBinder extends Binder {
public PassphraseCacheService getService() {
return PassphraseCacheService.this;
@@ -222,9 +356,4 @@ public class PassphraseCacheService extends Service {
private final IBinder mBinder = new PassphraseCacheBinder();
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
index 1e7fe0120..06d59b9a2 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
@@ -199,7 +199,8 @@ public class SignKeyActivity extends SherlockFragmentActivity {
// Send all information needed to service to sign key in other thread
Intent intent = new Intent(this, KeychainIntentService.class);
- intent.putExtra(KeychainIntentService.EXTRA_ACTION, KeychainIntentService.ACTION_SIGN_KEYRING);
+ intent.putExtra(KeychainIntentService.EXTRA_ACTION,
+ KeychainIntentService.ACTION_SIGN_KEYRING);
// fill values for this action
Bundle data = new Bundle();
@@ -210,8 +211,8 @@ public class SignKeyActivity extends SherlockFragmentActivity {
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
// Message is received after signing is done in ApgService
- KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, R.string.progress_signing,
- ProgressDialog.STYLE_SPINNER) {
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this,
+ R.string.progress_signing, ProgressDialog.STYLE_SPINNER) {
public void handleMessage(Message message) {
// handle messages by standard ApgHandler first
super.handleMessage(message);
@@ -250,7 +251,8 @@ public class SignKeyActivity extends SherlockFragmentActivity {
// Send all information needed to service to upload key in other thread
Intent intent = new Intent(this, KeychainIntentService.class);
- intent.putExtra(KeychainIntentService.EXTRA_ACTION, KeychainIntentService.ACTION_UPLOAD_KEYRING);
+ intent.putExtra(KeychainIntentService.EXTRA_ACTION,
+ KeychainIntentService.ACTION_UPLOAD_KEYRING);
// fill values for this action
Bundle data = new Bundle();
@@ -264,8 +266,8 @@ public class SignKeyActivity extends SherlockFragmentActivity {
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
// Message is received after uploading is done in ApgService
- KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, R.string.progress_exporting,
- ProgressDialog.STYLE_HORIZONTAL) {
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this,
+ R.string.progress_exporting, ProgressDialog.STYLE_HORIZONTAL) {
public void handleMessage(Message message) {
// handle messages by standard ApgHandler first
super.handleMessage(message);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
index 10fc74551..9e42b1f4e 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
@@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui.dialog;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPSecretKey;
-import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.sufficientlysecure.keychain.Constants;
@@ -44,7 +43,6 @@ import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.DialogFragment;
-
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -80,7 +78,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
long secretKeyId) throws PgpGeneralException {
// check if secret key has a passphrase
if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) {
- if (!hasPassphrase(context, secretKeyId)) {
+ if (!PassphraseCacheService.hasPassphrase(context, secretKeyId)) {
throw new PgpMain.PgpGeneralException("No passphrase! No passphrase dialog needed!");
}
}
@@ -95,39 +93,6 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
return frag;
}
- /**
- * Checks if key has a passphrase
- *
- * @param secretKeyId
- * @return true if it has a passphrase
- */
- private static boolean hasPassphrase(Context context, long secretKeyId) {
- // check if the key has no passphrase
- try {
- PGPSecretKey secretKey = PgpHelper.getMasterKey(ProviderHelper
- .getPGPSecretKeyRingByKeyId(context, secretKeyId));
- // PGPSecretKey secretKey =
- // PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
-
- Log.d(Constants.TAG, "Check if key has no passphrase...");
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- "SC").build("".toCharArray());
- PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
- if (testKey != null) {
- Log.d(Constants.TAG, "Key has no passphrase! Caches empty passphrase!");
-
- // cache empty passphrase
- PassphraseCacheService.addCachedPassphrase(context, secretKey.getKeyID(), "");
-
- return false;
- }
- } catch (PGPException e) {
- // silently catch
- }
-
- return true;
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -153,7 +118,8 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
alert.setMessage(R.string.passPhraseForSymmetricEncryption);
} else {
// TODO: by master key id???
- secretKey = PgpHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByKeyId(activity, secretKeyId));
+ secretKey = PgpHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByKeyId(activity,
+ secretKeyId));
// secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
if (secretKey == null) {
@@ -181,7 +147,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-
+
@Override
public void onClick(DialogInterface dialog, int id) {
dismiss();
@@ -189,38 +155,42 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
boolean keyOK = true;
String passPhrase = mPassphraseEditText.getText().toString();
long keyId;
- PGPSecretKey clickSecretKey = secretKey;
+ PGPSecretKey clickSecretKey = secretKey;
if (clickSecretKey != null) {
while (keyOK == true) {
- if (clickSecretKey != null) { //check again for loop
+ if (clickSecretKey != null) { // check again for loop
try {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
.setProvider(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME).build(
passPhrase.toCharArray());
- PGPPrivateKey testKey = clickSecretKey.extractPrivateKey(keyDecryptor);
+ PGPPrivateKey testKey = clickSecretKey
+ .extractPrivateKey(keyDecryptor);
if (testKey == null) {
if (!clickSecretKey.isMasterKey()) {
- Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
+ Toast.makeText(activity,
+ R.string.error_couldNotExtractPrivateKey,
Toast.LENGTH_SHORT).show();
return;
} else {
- clickSecretKey = PgpHelper.getKeyNum(ProviderHelper.getPGPSecretKeyRingByKeyId(activity, secretKeyId), curKeyIndex);
- curKeyIndex++; //does post-increment work like C?
+ clickSecretKey = PgpHelper.getKeyNum(ProviderHelper
+ .getPGPSecretKeyRingByKeyId(activity, secretKeyId),
+ curKeyIndex);
+ curKeyIndex++; // does post-increment work like C?
continue;
}
} else {
keyOK = false;
}
} catch (PGPException e) {
- Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
- .show();
+ Toast.makeText(activity, R.string.wrongPassPhrase,
+ Toast.LENGTH_SHORT).show();
return;
}
} else {
Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
Toast.LENGTH_SHORT).show();
- return; //ran out of keys to try
+ return; // ran out of keys to try
}
}
keyId = secretKey.getKeyID();
@@ -232,7 +202,8 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
PassphraseCacheService.addCachedPassphrase(activity, keyId, passPhrase);
if (keyOK == false && clickSecretKey.getKeyID() != keyId) {
- PassphraseCacheService.addCachedPassphrase(activity, clickSecretKey.getKeyID(), passPhrase);
+ PassphraseCacheService.addCachedPassphrase(activity, clickSecretKey.getKeyID(),
+ passPhrase);
}
sendMessageToHandler(MESSAGE_OKAY);
@@ -240,7 +211,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
});
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
-
+
@Override
public void onClick(DialogInterface dialog, int id) {
dismiss();
@@ -255,7 +226,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
public void onActivityCreated(Bundle arg0) {
super.onActivityCreated(arg0);
if (canKB) {
- // request focus and open soft keyboard
+ // request focus and open soft keyboard
mPassphraseEditText.requestFocus();
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
@@ -298,4 +269,3 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
}
}
-
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
index 898b05372..6d94889cf 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
@@ -103,11 +103,11 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
}
public void setCanEdit(boolean bCanEdit) {
- canEdit = bCanEdit;
- mPlusButton = (ImageView)findViewById(R.id.plusbutton);
- if (!canEdit) {
- mPlusButton.setVisibility(View.INVISIBLE);
- }
+ canEdit = bCanEdit;
+ mPlusButton = (ImageView) findViewById(R.id.plusbutton);
+ if (!canEdit) {
+ mPlusButton.setVisibility(View.INVISIBLE);
+ }
}
/** {@inheritDoc} */
@@ -141,82 +141,85 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
/** {@inheritDoc} */
public void onClick(View v) {
if (canEdit) {
- switch (mType) {
- case Id.type.user_id: {
- UserIdEditor view = (UserIdEditor) mInflater.inflate(R.layout.edit_key_user_id_item,
- mEditors, false);
- view.setEditorListener(this);
- if (mEditors.getChildCount() == 0) {
- view.setIsMainUserId(true);
+ switch (mType) {
+ case Id.type.user_id: {
+ UserIdEditor view = (UserIdEditor) mInflater.inflate(
+ R.layout.edit_key_user_id_item, mEditors, false);
+ view.setEditorListener(this);
+ if (mEditors.getChildCount() == 0) {
+ view.setIsMainUserId(true);
+ }
+ mEditors.addView(view);
+ break;
}
- mEditors.addView(view);
- break;
- }
- case Id.type.key: {
- AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
-
- View view = mInflater.inflate(R.layout.create_key, null);
- dialog.setView(view);
- dialog.setTitle(R.string.title_createKey);
+ case Id.type.key: {
+ AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
- boolean wouldBeMasterKey = (mEditors.getChildCount() == 0);
+ View view = mInflater.inflate(R.layout.create_key, null);
+ dialog.setView(view);
+ dialog.setTitle(R.string.title_createKey);
- final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm);
- Vector<Choice> choices = new Vector<Choice>();
- choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString(R.string.dsa)));
- if (!wouldBeMasterKey) {
- choices.add(new Choice(Id.choice.algorithm.elgamal, getResources().getString(
- R.string.elgamal)));
- }
+ boolean wouldBeMasterKey = (mEditors.getChildCount() == 0);
- choices.add(new Choice(Id.choice.algorithm.rsa, getResources().getString(R.string.rsa)));
-
- ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(getContext(),
- android.R.layout.simple_spinner_item, choices);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- algorithm.setAdapter(adapter);
- // make RSA the default
- for (int i = 0; i < choices.size(); ++i) {
- if (choices.get(i).getId() == Id.choice.algorithm.rsa) {
- algorithm.setSelection(i);
- break;
+ final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm);
+ Vector<Choice> choices = new Vector<Choice>();
+ choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString(
+ R.string.dsa)));
+ if (!wouldBeMasterKey) {
+ choices.add(new Choice(Id.choice.algorithm.elgamal, getResources().getString(
+ R.string.elgamal)));
}
- }
-
- final EditText keySize = (EditText) view.findViewById(R.id.create_key_size);
- dialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface di, int id) {
- di.dismiss();
- try {
- mNewKeySize = Integer.parseInt("" + keySize.getText());
- } catch (NumberFormatException e) {
- mNewKeySize = 0;
+ choices.add(new Choice(Id.choice.algorithm.rsa, getResources().getString(
+ R.string.rsa)));
+
+ ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(getContext(),
+ android.R.layout.simple_spinner_item, choices);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ algorithm.setAdapter(adapter);
+ // make RSA the default
+ for (int i = 0; i < choices.size(); ++i) {
+ if (choices.get(i).getId() == Id.choice.algorithm.rsa) {
+ algorithm.setSelection(i);
+ break;
}
-
- mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem();
- createKey();
}
- });
-
- dialog.setCancelable(true);
- dialog.setNegativeButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface di, int id) {
- di.dismiss();
- }
- });
- dialog.create().show();
- break;
- }
+ final EditText keySize = (EditText) view.findViewById(R.id.create_key_size);
+
+ dialog.setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface di, int id) {
+ di.dismiss();
+ try {
+ mNewKeySize = Integer.parseInt("" + keySize.getText());
+ } catch (NumberFormatException e) {
+ mNewKeySize = 0;
+ }
+
+ mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem();
+ createKey();
+ }
+ });
+
+ dialog.setCancelable(true);
+ dialog.setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface di, int id) {
+ di.dismiss();
+ }
+ });
+
+ dialog.create().show();
+ break;
+ }
- default: {
- break;
- }
- }
- this.updateEditorsVisible();
+ default: {
+ break;
+ }
+ }
+ this.updateEditorsVisible();
}
}
@@ -266,7 +269,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
// Send all information needed to service to edit key in other thread
Intent intent = new Intent(mActivity, KeychainIntentService.class);
- intent.putExtra(KeychainIntentService.EXTRA_ACTION, KeychainIntentService.ACTION_GENERATE_KEY);
+ intent.putExtra(KeychainIntentService.EXTRA_ACTION,
+ KeychainIntentService.ACTION_GENERATE_KEY);
// fill values for this action
Bundle data = new Bundle();
@@ -293,7 +297,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
ProgressDialog.STYLE_SPINNER);
// Message is received after generating is done in ApgService
- KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(mActivity, mGeneratingDialog) {
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(mActivity,
+ mGeneratingDialog) {
public void handleMessage(Message message) {
// handle messages by standard ApgHandler first
super.handleMessage(message);
@@ -302,7 +307,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
// get new key from data bundle returned from service
Bundle data = message.getData();
PGPSecretKeyRing newKeyRing = (PGPSecretKeyRing) PgpConversionHelper
- .BytesToPGPKeyRing(data.getByteArray(KeychainIntentService.RESULT_NEW_KEY));
+ .BytesToPGPKeyRing(data
+ .getByteArray(KeychainIntentService.RESULT_NEW_KEY));
boolean isMasterKey = (mEditors.getChildCount() == 0);