diff --git a/OpenPGP-Keychain/res/layout/edit_key_section.xml b/OpenPGP-Keychain/res/layout/edit_key_section.xml
index 870e1b063..dd0a5d4bd 100644
--- a/OpenPGP-Keychain/res/layout/edit_key_section.xml
+++ b/OpenPGP-Keychain/res/layout/edit_key_section.xml
@@ -41,6 +41,7 @@
android:text="Section Name" />
-
\ No newline at end of file
+
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpMain.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpMain.java
index f4b7c7bbd..27047cd0f 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpMain.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/PgpMain.java
@@ -309,6 +309,31 @@ public class PgpMain {
return secKeyRing;
}
+ public static void changeSecretKeyPassphrase(Context context,
+ PGPSecretKeyRing keyRing, String oldPassPhrase, String newPassPhrase,
+ ProgressDialogUpdater progress) throws IOException, PGPException, PGPException,
+ NoSuchProviderException {
+
+ updateProgress(progress, R.string.progress_buildingKey, 0, 100);
+ if (oldPassPhrase == null) {
+ oldPassPhrase = "";
+ }
+ if (newPassPhrase == null) {
+ newPassPhrase = "";
+ }
+
+ PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword(keyRing,
+ oldPassPhrase.toCharArray(), newPassPhrase.toCharArray(), keyRing.getSecretKey().getKeyEncryptionAlgorithm(),
+ new SecureRandom(), BOUNCY_CASTLE_PROVIDER_NAME);
+
+ updateProgress(progress, R.string.progress_savingKeyRing, 50, 100);
+
+ ProviderHelper.saveKeyRing(context, newKeyRing);
+
+ updateProgress(progress, R.string.progress_done, 100, 100);
+
+ }
+
public static void buildSecretKey(Context context, ArrayList userIds,
ArrayList keys, ArrayList keysUsages, long masterKeyId,
String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress)
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 7190d72c4..2665456ea 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -34,6 +34,7 @@ import org.sufficientlysecure.keychain.helper.PgpMain;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
@@ -494,6 +495,49 @@ public class ProviderHelper {
return getMasterKeyId(context, queryUri, keyRingRowId);
}
+ /**
+ * Get empty status of master key of keyring by its row id
+ *
+ * @param context
+ * @param keyRingRowId
+ * @return
+ */
+ public static boolean getSecretMasterKeyCanSign(Context context, long keyRingRowId) {
+ Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId));
+ return getMasterKeyCanSign(context, queryUri, keyRingRowId);
+ }
+
+ /**
+ * Private helper method to get master key private empty status of keyring by its row id
+ *
+ * @param context
+ * @param queryUri
+ * @param keyRingRowId
+ * @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", };
+
+ ContentResolver cr = context.getContentResolver();
+ Cursor cursor = cr.query(queryUri, projection, null, null, null);
+
+ long masterKeyId = -1;
+ if (cursor != null && cursor.moveToFirst()) {
+ int masterKeyIdCol = cursor.getColumnIndex("sign");
+
+ masterKeyId = cursor.getLong(masterKeyIdCol);
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+
+ return (masterKeyId > 0);
+ }
+
/**
* Get master key id of keyring by its row id
*
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index e525fe96e..48afdff5c 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -123,6 +123,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
public static final String SAVE_KEYRING_KEYS = "keys";
public static final String SAVE_KEYRING_KEYS_USAGES = "keysUsages";
public static final String SAVE_KEYRING_MASTER_KEY_ID = "masterKeyId";
+ public static final String SAVE_KEYRING_CAN_SIGN = "can_sign";
// generate key
public static final String GENERATE_KEY_ALGORITHM = "algorithm";
@@ -523,6 +524,12 @@ public class KeychainIntentService extends IntentService implements ProgressDial
/* Input */
String oldPassPhrase = data.getString(SAVE_KEYRING_CURRENT_PASSPHRASE);
String newPassPhrase = data.getString(SAVE_KEYRING_NEW_PASSPHRASE);
+ boolean canSign = true;
+
+ if (data.containsKey(SAVE_KEYRING_CAN_SIGN)) {
+ canSign = data.getBoolean(SAVE_KEYRING_CAN_SIGN);
+ }
+
if (newPassPhrase == null) {
newPassPhrase = oldPassPhrase;
}
@@ -533,8 +540,13 @@ public class KeychainIntentService extends IntentService implements ProgressDial
long masterKeyId = data.getLong(SAVE_KEYRING_MASTER_KEY_ID);
/* Operation */
- PgpMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase,
+ if (!canSign) { //library fails, fix later
+ //PgpMain.changeSecretKeyPassphrase(this, ProviderHelper.getPGPSecretKeyRingByKeyId(this, masterKeyId),
+ //oldPassPhrase, newPassPhrase, this);
+ } else {
+ PgpMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase,
newPassPhrase, this);
+ }
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
/* Output */
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 90ee9838e..3d819a824 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -75,6 +75,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
public static final String EXTRA_NO_PASSPHRASE = "noPassphrase";
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generateDefaultKeys";
public static final String EXTRA_MASTER_KEY_ID = "masterKeyId";
+ public static final String EXTRA_MASTER_CAN_SIGN = "masterCanSign";
// results when saving key
public static final String RESULT_EXTRA_MASTER_KEY_ID = "masterKeyId";
@@ -97,6 +98,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
Vector mUserIds;
Vector mKeys;
Vector mKeysUsages;
+ boolean masterCanSign = true;
// will be set to false to build layout later in handler
private boolean mBuildLayout = true;
@@ -192,6 +194,13 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
});
+ //disable key passhphrase changing with empty private keys for no
+ //library fails, fix later
+ if (!masterCanSign) {
+ mChangePassPhrase.setEnabled(false);
+ mNoPassphrase.setEnabled(false);
+ }
+
if (mBuildLayout) {
buildLayout();
}
@@ -317,6 +326,9 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
if (extras != null) {
+ if (extras.containsKey(EXTRA_MASTER_CAN_SIGN)) {
+ masterCanSign = extras.getBoolean(EXTRA_MASTER_CAN_SIGN);
+ }
if (extras.containsKey(EXTRA_MASTER_KEY_ID)) {
long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
@@ -394,10 +406,12 @@ public class EditKeyActivity extends SherlockFragmentActivity {
LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
mUserIdsView.setType(Id.type.user_id);
+ mUserIdsView.setCanEdit(masterCanSign);
mUserIdsView.setUserIds(mUserIds);
container.addView(mUserIdsView);
mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
mKeysView.setType(Id.type.key);
+ mKeysView.setCanEdit(masterCanSign);
mKeysView.setKeys(mKeys, mKeysUsages);
container.addView(mKeysView);
@@ -447,6 +461,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
data.putIntegerArrayList(KeychainIntentService.SAVE_KEYRING_KEYS_USAGES,
getKeysUsages(mKeysView));
data.putLong(KeychainIntentService.SAVE_KEYRING_MASTER_KEY_ID, getMasterKeyId());
+ data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, masterCanSign);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
index 0e6cdd6a1..52ce19f97 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
@@ -70,18 +70,19 @@ public class KeyListSecretActivity extends KeyListActivity {
}
}
- public void checkPassPhraseAndEdit(long masterKeyId) {
+ public void checkPassPhraseAndEdit(long masterKeyId, boolean masterCanSign) {
String passPhrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
if (passPhrase == null) {
- showPassphraseDialog(masterKeyId);
+ showPassphraseDialog(masterKeyId, masterCanSign);
} else {
PgpMain.setEditPassPhrase(passPhrase);
- editKey(masterKeyId);
+ editKey(masterKeyId, masterCanSign);
}
}
- private void showPassphraseDialog(final long masterKeyId) {
+ private void showPassphraseDialog(final long masterKeyId, boolean masterCanSign) {
// Message is received after passphrase is cached
+ final boolean mCanSign = masterCanSign;
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
@@ -89,7 +90,7 @@ public class KeyListSecretActivity extends KeyListActivity {
String passPhrase = PassphraseCacheService.getCachedPassphrase(
KeyListSecretActivity.this, masterKeyId);
PgpMain.setEditPassPhrase(passPhrase);
- editKey(masterKeyId);
+ editKey(masterKeyId, mCanSign);
}
}
};
@@ -115,9 +116,10 @@ public class KeyListSecretActivity extends KeyListActivity {
startActivityForResult(intent, 0);
}
- private void editKey(long masterKeyId) {
+ private void editKey(long masterKeyId, boolean masterCanSign) {
Intent intent = new Intent(EditKeyActivity.ACTION_EDIT_KEY);
intent.putExtra(EditKeyActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
+ intent.putExtra(EditKeyActivity.EXTRA_MASTER_CAN_SIGN, masterCanSign);
startActivityForResult(intent, 0);
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
index f4ba2b4d9..e41755840 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
@@ -91,9 +91,11 @@ public class KeyListSecretFragment extends KeyListFragment implements
long masterKeyId = ProviderHelper
.getSecretMasterKeyId(mKeyListSecretActivity, keyRingRowId);
+ boolean masterCanSign = ProviderHelper.getSecretMasterKeyCanSign(mKeyListSecretActivity, keyRingRowId);
+
switch (item.getItemId()) {
case Id.menu.edit:
- mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId);
+ mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId, masterCanSign);
return true;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
index 1122fc522..e9a5674cd 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
@@ -125,6 +125,14 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
super.onFinishInflate();
}
+ public void setCanEdit(boolean bCanEdit) {
+ if (!bCanEdit) {
+ mDeleteButton.setVisibility(View.INVISIBLE);
+ mUsage.setEnabled(false);
+ mExpiryDateButton.setEnabled(false);
+ }
+ }
+
public void setValue(PGPSecretKey key, boolean isMasterKey, int usage) {
mKey = key;
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 7142e4426..898b05372 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
@@ -45,6 +45,7 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
@@ -55,12 +56,14 @@ import java.util.Vector;
public class SectionView extends LinearLayout implements OnClickListener, EditorListener {
private LayoutInflater mInflater;
private View mAdd;
+ private ImageView mPlusButton;
private ViewGroup mEditors;
private TextView mTitle;
private int mType = 0;
private Choice mNewKeyAlgorithmChoice;
private int mNewKeySize;
+ private boolean canEdit = true;
private SherlockFragmentActivity mActivity;
@@ -99,6 +102,14 @@ 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);
+ }
+ }
+
/** {@inheritDoc} */
@Override
protected void onFinishInflate() {
@@ -129,6 +140,7 @@ 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,
@@ -205,6 +217,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
}
}
this.updateEditorsVisible();
+ }
}
public void setUserIds(Vector list) {
@@ -221,6 +234,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
if (mEditors.getChildCount() == 0) {
view.setIsMainUserId(true);
}
+ view.setCanEdit(canEdit);
mEditors.addView(view);
}
@@ -241,6 +255,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
view.setEditorListener(this);
boolean isMasterKey = (mEditors.getChildCount() == 0);
view.setValue(list.get(i), isMasterKey, usages.get(i));
+ view.setCanEdit(canEdit);
mEditors.addView(view);
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
index 2215d29e7..5b43ebbd9 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
@@ -56,6 +56,16 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
}
}
+ public void setCanEdit(boolean bCanEdit) {
+ if (!bCanEdit) {
+ mDeleteButton.setVisibility(View.INVISIBLE);
+ mName.setEnabled(false);
+ mIsMainUserId.setEnabled(false);
+ mEmail.setEnabled(false);
+ mComment.setEnabled(false);
+ }
+ }
+
public static class NoEmailException extends Exception {
static final long serialVersionUID = 0xf812773344L;