mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-01 07:30:18 -05:00
completly new PasswordCacheService (more energy efficient), reworked Password dialogs
This commit is contained in:
parent
be49597882
commit
4b8400685a
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
|
Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -49,7 +50,7 @@
|
|||||||
android:theme="@style/Theme.Sherlock.Light.ForceOverflow" >
|
android:theme="@style/Theme.Sherlock.Light.ForceOverflow" >
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.MainActivity"
|
android:name=".ui.MainActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/app_name" >
|
android:label="@string/app_name" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
@ -59,7 +60,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.PublicKeyListActivity"
|
android:name=".ui.PublicKeyListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_managePublicKeys"
|
android:label="@string/title_managePublicKeys"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:uiOptions="splitActionBarWhenNarrow" >
|
android:uiOptions="splitActionBarWhenNarrow" >
|
||||||
@ -73,7 +74,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.SecretKeyListActivity"
|
android:name=".ui.SecretKeyListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_manageSecretKeys"
|
android:label="@string/title_manageSecretKeys"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:uiOptions="splitActionBarWhenNarrow" >
|
android:uiOptions="splitActionBarWhenNarrow" >
|
||||||
@ -87,7 +88,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.EditKeyActivity"
|
android:name=".ui.EditKeyActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_editKey"
|
android:label="@string/title_editKey"
|
||||||
android:uiOptions="splitActionBarWhenNarrow"
|
android:uiOptions="splitActionBarWhenNarrow"
|
||||||
android:windowSoftInputMode="stateHidden" >
|
android:windowSoftInputMode="stateHidden" >
|
||||||
@ -100,7 +101,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.SelectPublicKeyListActivity"
|
android:name=".ui.SelectPublicKeyListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_selectRecipients"
|
android:label="@string/title_selectRecipients"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:uiOptions="splitActionBarWhenNarrow" >
|
android:uiOptions="splitActionBarWhenNarrow" >
|
||||||
@ -119,7 +120,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.SelectSecretKeyListActivity"
|
android:name=".ui.SelectSecretKeyListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_selectSignature"
|
android:label="@string/title_selectSignature"
|
||||||
android:launchMode="singleTop" >
|
android:launchMode="singleTop" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -137,7 +138,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.EncryptActivity"
|
android:name=".ui.EncryptActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_encrypt"
|
android:label="@string/title_encrypt"
|
||||||
android:uiOptions="splitActionBarWhenNarrow"
|
android:uiOptions="splitActionBarWhenNarrow"
|
||||||
android:windowSoftInputMode="stateHidden" >
|
android:windowSoftInputMode="stateHidden" >
|
||||||
@ -154,7 +155,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.DecryptActivity"
|
android:name=".ui.DecryptActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_decrypt"
|
android:label="@string/title_decrypt"
|
||||||
android:uiOptions="splitActionBarWhenNarrow"
|
android:uiOptions="splitActionBarWhenNarrow"
|
||||||
android:windowSoftInputMode="stateHidden" >
|
android:windowSoftInputMode="stateHidden" >
|
||||||
@ -170,7 +171,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".deprecated.GeneralActivity"
|
android:name=".deprecated.GeneralActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@android:style/Theme.Dialog" >
|
android:theme="@android:style/Theme.Dialog" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -202,39 +203,39 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.MailListActivity"
|
android:name=".ui.MailListActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_mailInbox" />
|
android:label="@string/title_mailInbox" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.KeyServerQueryActivity"
|
android:name=".ui.KeyServerQueryActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_keyServerQuery" />
|
android:label="@string/title_keyServerQuery" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.KeyServerUploadActivity"
|
android:name=".ui.KeyServerUploadActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_sendKey" />
|
android:label="@string/title_sendKey" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.PreferencesActivity"
|
android:name=".ui.PreferencesActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_preferences" />
|
android:label="@string/title_preferences" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.PreferencesKeyServerActivity"
|
android:name=".ui.PreferencesKeyServerActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_keyServerPreference"
|
android:label="@string/title_keyServerPreference"
|
||||||
android:uiOptions="splitActionBarWhenNarrow"
|
android:uiOptions="splitActionBarWhenNarrow"
|
||||||
android:windowSoftInputMode="stateHidden" />
|
android:windowSoftInputMode="stateHidden" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.SignKeyActivity"
|
android:name=".ui.SignKeyActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_signKey" />
|
android:label="@string/title_signKey" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.ImportFromQRCodeActivity"
|
android:name=".ui.ImportFromQRCodeActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
|
||||||
android:label="@string/title_importFromQRCode" />
|
android:label="@string/title_importFromQRCode" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.HelpActivity"
|
android:name=".ui.HelpActivity"
|
||||||
android:label="@string/title_help" />
|
android:label="@string/title_help" />
|
||||||
|
|
||||||
<service android:name=".service.password.PassphraseCacheService" />
|
<service android:name=".service.PassphraseCacheService" />
|
||||||
<service android:name=".service.ApgService" />
|
<service android:name=".service.ApgService" />
|
||||||
|
|
||||||
<!-- TODO: need to be moved into new service model -->
|
<!-- TODO: need to be moved into new service model -->
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
android:id="@+id/passphrase_passphrase"
|
android:id="@+id/passphrase_passphrase"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:imeOptions="actionDone"
|
||||||
android:inputType="textPassword"
|
android:inputType="textPassword"
|
||||||
android:padding="4dp" />
|
android:padding="4dp" />
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
android:id="@+id/passphrase_passphrase_again"
|
android:id="@+id/passphrase_passphrase_again"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:imeOptions="actionDone"
|
||||||
android:inputType="textPassword"
|
android:inputType="textPassword"
|
||||||
android:padding="4dp" />
|
android:padding="4dp" />
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
@ -38,7 +38,8 @@ public class ApgApplication extends Application {
|
|||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
/* Start passphrase cache service */
|
/* Start passphrase cache service */
|
||||||
PassphraseCacheService.startCacheService(this);
|
// TODO: not needed anymore!
|
||||||
|
// PassphraseCacheService.startCacheService(this);
|
||||||
|
|
||||||
// TODO: Do it better than this!
|
// TODO: Do it better than this!
|
||||||
// this initializes the database to be used in PGPMain
|
// this initializes the database to be used in PGPMain
|
||||||
|
@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
|
||||||
*
|
|
||||||
* 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.thialfihar.android.apg.deprecated;
|
|
||||||
|
|
||||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
|
||||||
import org.spongycastle.openpgp.PGPException;
|
|
||||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
|
||||||
import org.thialfihar.android.apg.Id;
|
|
||||||
import org.thialfihar.android.apg.R;
|
|
||||||
import org.thialfihar.android.apg.helper.PGPHelper;
|
|
||||||
import org.thialfihar.android.apg.helper.PGPMain;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.DialogInterface.OnClickListener;
|
|
||||||
import org.thialfihar.android.apg.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO:
|
|
||||||
*
|
|
||||||
* - Use new PassphraseDialogFragment!
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class AskForPassphrase {
|
|
||||||
public static interface PassPhraseCallbackInterface {
|
|
||||||
void passPhraseCallback(long keyId, String passPhrase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Dialog createDialog(Activity context, long secretKeyId,
|
|
||||||
PassPhraseCallbackInterface callback) {
|
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(context);
|
|
||||||
|
|
||||||
alert.setTitle(R.string.title_authentication);
|
|
||||||
|
|
||||||
final PGPSecretKey secretKey;
|
|
||||||
final Activity activity = context;
|
|
||||||
|
|
||||||
if (secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none) {
|
|
||||||
secretKey = null;
|
|
||||||
alert.setMessage(context.getString(R.string.passPhraseForSymmetricEncryption));
|
|
||||||
} else {
|
|
||||||
secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
|
|
||||||
if (secretKey == null) {
|
|
||||||
alert.setTitle(R.string.title_keyNotFound);
|
|
||||||
alert.setMessage(context.getString(R.string.keyNotFound, secretKeyId));
|
|
||||||
alert.setPositiveButton(android.R.string.ok, new OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
activity.removeDialog(Id.dialog.pass_phrase);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
alert.setCancelable(false);
|
|
||||||
return alert.create();
|
|
||||||
}
|
|
||||||
String userId = PGPHelper.getMainUserIdSafe(context, secretKey);
|
|
||||||
alert.setMessage(context.getString(R.string.passPhraseFor, userId));
|
|
||||||
}
|
|
||||||
|
|
||||||
LayoutInflater inflater = (LayoutInflater) context
|
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
View view = inflater.inflate(R.layout.passphrase, null);
|
|
||||||
final EditText input = (EditText) view.findViewById(R.id.passphrase_passphrase);
|
|
||||||
|
|
||||||
final TextView labelNotUsed = (TextView) view
|
|
||||||
.findViewById(R.id.passphrase_label_passphrase_again);
|
|
||||||
labelNotUsed.setVisibility(View.GONE);
|
|
||||||
final EditText inputNotUsed = (EditText) view
|
|
||||||
.findViewById(R.id.passphrase_passphrase_again);
|
|
||||||
inputNotUsed.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
alert.setView(view);
|
|
||||||
|
|
||||||
final PassPhraseCallbackInterface cb = callback;
|
|
||||||
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
activity.removeDialog(Id.dialog.pass_phrase);
|
|
||||||
String passPhrase = input.getText().toString();
|
|
||||||
long keyId;
|
|
||||||
if (secretKey != null) {
|
|
||||||
try {
|
|
||||||
PGPPrivateKey testKey = secretKey.extractPrivateKey(
|
|
||||||
passPhrase.toCharArray(), new BouncyCastleProvider());
|
|
||||||
if (testKey == null) {
|
|
||||||
Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (PGPException e) {
|
|
||||||
Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
|
|
||||||
.show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
keyId = secretKey.getKeyID();
|
|
||||||
} else {
|
|
||||||
keyId = Id.key.symmetric;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache again
|
|
||||||
PGPMain.setCachedPassPhrase(keyId, passPhrase);
|
|
||||||
// return by callback
|
|
||||||
cb.passPhraseCallback(keyId, passPhrase);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
activity.removeDialog(Id.dialog.pass_phrase);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// check if the key has no passphrase
|
|
||||||
if (secretKey != null) {
|
|
||||||
try {
|
|
||||||
Log.d("APG", "check if key has no passphrase...");
|
|
||||||
PGPPrivateKey testKey = secretKey.extractPrivateKey("".toCharArray(),
|
|
||||||
new BouncyCastleProvider());
|
|
||||||
if (testKey != null) {
|
|
||||||
Log.d("APG", "Key has no passphrase!");
|
|
||||||
|
|
||||||
// cache null
|
|
||||||
PGPMain.setCachedPassPhrase(secretKey.getKeyID(), null);
|
|
||||||
// return by callback
|
|
||||||
cb.passPhraseCallback(secretKey.getKeyID(), null);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (PGPException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return alert.create();
|
|
||||||
}
|
|
||||||
}
|
|
@ -42,7 +42,7 @@ import android.os.Handler;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
|
||||||
public class BaseActivity extends SherlockFragmentActivity implements Runnable,
|
public class BaseActivity extends SherlockFragmentActivity implements Runnable,
|
||||||
ProgressDialogUpdater, AskForPassphrase.PassPhraseCallbackInterface {
|
ProgressDialogUpdater {
|
||||||
|
|
||||||
private ProgressDialog mProgressDialog = null;
|
private ProgressDialog mProgressDialog = null;
|
||||||
// private PausableThread mRunningThread = null;
|
// private PausableThread mRunningThread = null;
|
||||||
@ -363,11 +363,11 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable,
|
|||||||
//
|
//
|
||||||
// Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
// Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
public void passPhraseCallback(long keyId, String passPhrase) {
|
// public void passPhraseCallback(long keyId, String passPhrase) {
|
||||||
// TODO: Not needed anymore, now implemented in AskForSecretKeyPass
|
// // TODO: Not needed anymore, now implemented in AskForSecretKeyPass
|
||||||
PGPMain.setCachedPassPhrase(keyId, passPhrase);
|
// PGPMain.setCachedPassPhrase(keyId, passPhrase);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// public void sendMessage(Message msg) {
|
// public void sendMessage(Message msg) {
|
||||||
// mHandler.sendMessage(msg);
|
// mHandler.sendMessage(msg);
|
||||||
|
@ -78,7 +78,6 @@ import org.thialfihar.android.apg.provider.KeyRings;
|
|||||||
import org.thialfihar.android.apg.provider.Keys;
|
import org.thialfihar.android.apg.provider.Keys;
|
||||||
import org.thialfihar.android.apg.provider.UserIds;
|
import org.thialfihar.android.apg.provider.UserIds;
|
||||||
import org.thialfihar.android.apg.service.ApgService;
|
import org.thialfihar.android.apg.service.ApgService;
|
||||||
import org.thialfihar.android.apg.service.CachedPassphrase;
|
|
||||||
import org.thialfihar.android.apg.util.HkpKeyServer;
|
import org.thialfihar.android.apg.util.HkpKeyServer;
|
||||||
import org.thialfihar.android.apg.util.InputData;
|
import org.thialfihar.android.apg.util.InputData;
|
||||||
import org.thialfihar.android.apg.util.PositionAwareInputStream;
|
import org.thialfihar.android.apg.util.PositionAwareInputStream;
|
||||||
@ -121,9 +120,7 @@ import java.security.Security;
|
|||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -185,7 +182,6 @@ public class PGPMain {
|
|||||||
".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
|
".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
|
||||||
Pattern.DOTALL);
|
Pattern.DOTALL);
|
||||||
|
|
||||||
private static HashMap<Long, CachedPassphrase> mPassPhraseCache = new HashMap<Long, CachedPassphrase>();
|
|
||||||
private static String mEditPassPhrase = null;
|
private static String mEditPassPhrase = null;
|
||||||
|
|
||||||
private static Database mDatabase = null;
|
private static Database mDatabase = null;
|
||||||
@ -224,58 +220,6 @@ public class PGPMain {
|
|||||||
return mEditPassPhrase;
|
return mEditPassPhrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setCachedPassPhrase(long keyId, String passPhrase) {
|
|
||||||
mPassPhraseCache.put(keyId, new CachedPassphrase(new Date().getTime(), passPhrase));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getCachedPassPhrase(long keyId) {
|
|
||||||
long realId = keyId;
|
|
||||||
if (realId != Id.key.symmetric) {
|
|
||||||
PGPSecretKeyRing keyRing = getSecretKeyRing(keyId);
|
|
||||||
if (keyRing == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
PGPSecretKey masterKey = PGPHelper.getMasterKey(keyRing);
|
|
||||||
if (masterKey == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
realId = masterKey.getKeyID();
|
|
||||||
}
|
|
||||||
CachedPassphrase cpp = mPassPhraseCache.get(realId);
|
|
||||||
if (cpp == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// set it again to reset the cache life cycle
|
|
||||||
setCachedPassPhrase(realId, cpp.passPhrase);
|
|
||||||
return cpp.passPhrase;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int cleanUpCache(int ttl, int initialDelay) {
|
|
||||||
int delay = initialDelay;
|
|
||||||
long realTtl = ttl * 1000;
|
|
||||||
long now = new Date().getTime();
|
|
||||||
Vector<Long> oldKeys = new Vector<Long>();
|
|
||||||
for (Map.Entry<Long, CachedPassphrase> pair : mPassPhraseCache.entrySet()) {
|
|
||||||
long lived = now - pair.getValue().timestamp;
|
|
||||||
if (lived >= realTtl) {
|
|
||||||
oldKeys.add(pair.getKey());
|
|
||||||
} else {
|
|
||||||
// see, whether the remaining time for this cache entry improves our
|
|
||||||
// check delay
|
|
||||||
long nextCheck = realTtl - lived + 1000;
|
|
||||||
if (nextCheck < delay) {
|
|
||||||
delay = (int) nextCheck;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (long keyId : oldKeys) {
|
|
||||||
mPassPhraseCache.remove(keyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new secret key. The returned PGPSecretKeyRing contains only one newly generated key
|
* Creates new secret key. The returned PGPSecretKeyRing contains only one newly generated key
|
||||||
* when this key is the new masterkey. If a masterkey is supplied in the parameters
|
* when this key is the new masterkey. If a masterkey is supplied in the parameters
|
||||||
@ -1268,11 +1212,10 @@ public class PGPMain {
|
|||||||
progress.setProgress(R.string.progress_done, 100, 100);
|
progress.setProgress(R.string.progress_done, 100, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PGPPublicKeyRing signKey(Context context, long masterKeyId, long pubKeyId)
|
public static PGPPublicKeyRing signKey(Context context, long masterKeyId, long pubKeyId,
|
||||||
throws GeneralException, NoSuchAlgorithmException, NoSuchProviderException,
|
String passphrase) throws GeneralException, NoSuchAlgorithmException,
|
||||||
PGPException, SignatureException {
|
NoSuchProviderException, PGPException, SignatureException {
|
||||||
String signaturePassPhrase = PGPMain.getCachedPassPhrase(masterKeyId);
|
if (passphrase == null || passphrase.length() <= 0) {
|
||||||
if (signaturePassPhrase == null || signaturePassPhrase.length() <= 0) {
|
|
||||||
throw new GeneralException("Unable to obtain passphrase");
|
throw new GeneralException("Unable to obtain passphrase");
|
||||||
} else {
|
} else {
|
||||||
PGPPublicKeyRing pubring = PGPMain.getPublicKeyRing(pubKeyId);
|
PGPPublicKeyRing pubring = PGPMain.getPublicKeyRing(pubKeyId);
|
||||||
@ -1283,7 +1226,7 @@ public class PGPMain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||||
BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassPhrase.toCharArray());
|
BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
||||||
PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
|
PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
|
||||||
if (signaturePrivateKey == null) {
|
if (signaturePrivateKey == null) {
|
||||||
throw new GeneralException(
|
throw new GeneralException(
|
||||||
|
@ -70,6 +70,25 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
|||||||
public static final String EXTRA_ACTION = "action";
|
public static final String EXTRA_ACTION = "action";
|
||||||
public static final String EXTRA_DATA = "data";
|
public static final String EXTRA_DATA = "data";
|
||||||
|
|
||||||
|
/* possible EXTRA_ACTIONs */
|
||||||
|
public static final int ACTION_ENCRYPT_SIGN = 10;
|
||||||
|
|
||||||
|
public static final int ACTION_DECRYPT_VERIFY = 20;
|
||||||
|
|
||||||
|
public static final int ACTION_SAVE_KEYRING = 30;
|
||||||
|
public static final int ACTION_GENERATE_KEY = 31;
|
||||||
|
public static final int ACTION_GENERATE_DEFAULT_RSA_KEYS = 32;
|
||||||
|
|
||||||
|
public static final int ACTION_DELETE_FILE_SECURELY = 40;
|
||||||
|
|
||||||
|
public static final int ACTION_IMPORT_KEY = 50;
|
||||||
|
public static final int ACTION_EXPORT_KEY = 51;
|
||||||
|
|
||||||
|
public static final int ACTION_UPLOAD_KEY = 60;
|
||||||
|
public static final int ACTION_QUERY_KEY = 61;
|
||||||
|
|
||||||
|
public static final int ACTION_SIGN_KEY = 70;
|
||||||
|
|
||||||
/* keys for data bundle */
|
/* keys for data bundle */
|
||||||
|
|
||||||
// encrypt, decrypt, import export
|
// encrypt, decrypt, import export
|
||||||
@ -143,25 +162,6 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
|||||||
public static final String SIGN_KEY_MASTER_KEY_ID = "signKeyMasterKeyId";
|
public static final String SIGN_KEY_MASTER_KEY_ID = "signKeyMasterKeyId";
|
||||||
public static final String SIGN_KEY_PUB_KEY_ID = "signKeyPubKeyId";
|
public static final String SIGN_KEY_PUB_KEY_ID = "signKeyPubKeyId";
|
||||||
|
|
||||||
/* possible EXTRA_ACTIONs */
|
|
||||||
public static final int ACTION_ENCRYPT_SIGN = 10;
|
|
||||||
|
|
||||||
public static final int ACTION_DECRYPT_VERIFY = 20;
|
|
||||||
|
|
||||||
public static final int ACTION_SAVE_KEYRING = 30;
|
|
||||||
public static final int ACTION_GENERATE_KEY = 31;
|
|
||||||
public static final int ACTION_GENERATE_DEFAULT_RSA_KEYS = 32;
|
|
||||||
|
|
||||||
public static final int ACTION_DELETE_FILE_SECURELY = 40;
|
|
||||||
|
|
||||||
public static final int ACTION_IMPORT_KEY = 50;
|
|
||||||
public static final int ACTION_EXPORT_KEY = 51;
|
|
||||||
|
|
||||||
public static final int ACTION_UPLOAD_KEY = 60;
|
|
||||||
public static final int ACTION_QUERY_KEY = 61;
|
|
||||||
|
|
||||||
public static final int ACTION_SIGN_KEY = 70;
|
|
||||||
|
|
||||||
/* possible data keys as result send over messenger */
|
/* possible data keys as result send over messenger */
|
||||||
// keys
|
// keys
|
||||||
public static final String RESULT_NEW_KEY = "newKey";
|
public static final String RESULT_NEW_KEY = "newKey";
|
||||||
@ -320,19 +320,21 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
|||||||
if (generateSignature) {
|
if (generateSignature) {
|
||||||
Log.d(Constants.TAG, "generating signature...");
|
Log.d(Constants.TAG, "generating signature...");
|
||||||
PGPMain.generateSignature(this, inputData, outStream, useAsciiArmour, false,
|
PGPMain.generateSignature(this, inputData, outStream, useAsciiArmour, false,
|
||||||
secretKeyId, PGPMain.getCachedPassPhrase(secretKeyId), Preferences
|
secretKeyId, PassphraseCacheService.getCachedPassphrase(this,
|
||||||
.getPreferences(this).getDefaultHashAlgorithm(), Preferences
|
secretKeyId), Preferences.getPreferences(this)
|
||||||
.getPreferences(this).getForceV3Signatures(), this);
|
.getDefaultHashAlgorithm(), Preferences.getPreferences(this)
|
||||||
|
.getForceV3Signatures(), this);
|
||||||
} else if (signOnly) {
|
} else if (signOnly) {
|
||||||
Log.d(Constants.TAG, "sign only...");
|
Log.d(Constants.TAG, "sign only...");
|
||||||
PGPMain.signText(this, inputData, outStream, secretKeyId, PGPMain
|
PGPMain.signText(this, inputData, outStream, secretKeyId,
|
||||||
.getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this)
|
PassphraseCacheService.getCachedPassphrase(this, secretKeyId),
|
||||||
.getDefaultHashAlgorithm(), Preferences.getPreferences(this)
|
Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences
|
||||||
.getForceV3Signatures(), this);
|
.getPreferences(this).getForceV3Signatures(), this);
|
||||||
} else {
|
} else {
|
||||||
Log.d(Constants.TAG, "encrypt...");
|
Log.d(Constants.TAG, "encrypt...");
|
||||||
PGPMain.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds,
|
PGPMain.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds,
|
||||||
signatureKeyId, PGPMain.getCachedPassPhrase(signatureKeyId), this,
|
signatureKeyId,
|
||||||
|
PassphraseCacheService.getCachedPassphrase(this, signatureKeyId), this,
|
||||||
Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(),
|
Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(),
|
||||||
Preferences.getPreferences(this).getDefaultHashAlgorithm(),
|
Preferences.getPreferences(this).getDefaultHashAlgorithm(),
|
||||||
compressionId, Preferences.getPreferences(this).getForceV3Signatures(),
|
compressionId, Preferences.getPreferences(this).getForceV3Signatures(),
|
||||||
@ -478,7 +480,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
|||||||
this);
|
this);
|
||||||
} else {
|
} else {
|
||||||
resultData = PGPMain.decrypt(this, inputData, outStream,
|
resultData = PGPMain.decrypt(this, inputData, outStream,
|
||||||
PGPMain.getCachedPassPhrase(secretKeyId), this,
|
PassphraseCacheService.getCachedPassphrase(this, secretKeyId), this,
|
||||||
assumeSymmetricEncryption);
|
assumeSymmetricEncryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,7 +541,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
|||||||
/* Operation */
|
/* Operation */
|
||||||
PGPMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase,
|
PGPMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase,
|
||||||
newPassPhrase, this);
|
newPassPhrase, this);
|
||||||
PGPMain.setCachedPassPhrase(masterKeyId, newPassPhrase);
|
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
|
||||||
|
|
||||||
/* Output */
|
/* Output */
|
||||||
sendMessageToHandler(ApgServiceHandler.MESSAGE_OKAY);
|
sendMessageToHandler(ApgServiceHandler.MESSAGE_OKAY);
|
||||||
@ -798,7 +800,11 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
|||||||
long pubKeyId = data.getLong(SIGN_KEY_PUB_KEY_ID);
|
long pubKeyId = data.getLong(SIGN_KEY_PUB_KEY_ID);
|
||||||
|
|
||||||
/* Operation */
|
/* Operation */
|
||||||
PGPPublicKeyRing signedPubKeyRing = PGPMain.signKey(this, masterKeyId, pubKeyId);
|
String signaturePassPhrase = PassphraseCacheService.getCachedPassphrase(this,
|
||||||
|
masterKeyId);
|
||||||
|
|
||||||
|
PGPPublicKeyRing signedPubKeyRing = PGPMain.signKey(this, masterKeyId, pubKeyId,
|
||||||
|
signaturePassPhrase);
|
||||||
|
|
||||||
// store the signed key in our local cache
|
// store the signed key in our local cache
|
||||||
int retval = PGPMain.storeKeyRingInCache(signedPubKeyRing);
|
int retval = PGPMain.storeKeyRingInCache(signedPubKeyRing);
|
||||||
|
@ -15,19 +15,27 @@
|
|||||||
package org.thialfihar.android.apg.service;
|
package org.thialfihar.android.apg.service;
|
||||||
|
|
||||||
public class CachedPassphrase {
|
public class CachedPassphrase {
|
||||||
public final long timestamp;
|
private final long timestamp;
|
||||||
public final String passPhrase;
|
private final String passphrase;
|
||||||
|
|
||||||
public CachedPassphrase(long timestamp, String passPhrase) {
|
public CachedPassphrase(long timestamp, String passPhrase) {
|
||||||
super();
|
super();
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.passPhrase = passPhrase;
|
this.passphrase = passPhrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassphrase() {
|
||||||
|
return passphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hc1 = (int) (this.timestamp & 0xffffffff);
|
int hc1 = (int) (this.timestamp & 0xffffffff);
|
||||||
int hc2 = (this.passPhrase == null ? 0 : this.passPhrase.hashCode());
|
int hc2 = (this.passphrase == null ? 0 : this.passphrase.hashCode());
|
||||||
return (hc1 + hc2) * hc2 + hc1;
|
return (hc1 + hc2) * hc2 + hc1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,12 +50,12 @@ public class CachedPassphrase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passPhrase != o.passPhrase) {
|
if (passphrase != o.passphrase) {
|
||||||
if (passPhrase == null || o.passPhrase == null) {
|
if (passphrase == null || o.passphrase == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!passPhrase.equals(o.passPhrase)) {
|
if (!passphrase.equals(o.passphrase)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@ -14,90 +16,211 @@
|
|||||||
|
|
||||||
package org.thialfihar.android.apg.service;
|
package org.thialfihar.android.apg.service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.thialfihar.android.apg.Constants;
|
||||||
|
import org.thialfihar.android.apg.Id;
|
||||||
|
import org.thialfihar.android.apg.helper.PGPHelper;
|
||||||
import org.thialfihar.android.apg.helper.PGPMain;
|
import org.thialfihar.android.apg.helper.PGPMain;
|
||||||
import org.thialfihar.android.apg.helper.Preferences;
|
import org.thialfihar.android.apg.helper.Preferences;
|
||||||
|
|
||||||
|
import android.app.AlarmManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
public class PassphraseCacheService extends Service {
|
public class PassphraseCacheService extends Service {
|
||||||
private final IBinder mBinder = new LocalBinder();
|
public static final String BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE = Constants.INTENT_PREFIX
|
||||||
|
+ "PASSPHRASE_CACHE_SERVICE";
|
||||||
|
|
||||||
public static final String EXTRA_TTL = "ttl";
|
public static final String EXTRA_TTL = "ttl";
|
||||||
|
public static final String EXTRA_KEY_ID = "keyId";
|
||||||
|
public static final String EXTRA_PASSPHRASE = "passphrase";
|
||||||
|
|
||||||
|
private static final int REQUEST_ID = 0;
|
||||||
|
private static final long DEFAULT_TTL = 15;
|
||||||
|
|
||||||
|
private BroadcastReceiver mIntentReceiver;
|
||||||
|
|
||||||
|
// TODO: This is static to be easily retrieved by getCachedPassphrase()
|
||||||
|
// To avoid static we would need a messenger from the service back to the activity?
|
||||||
|
private static HashMap<Long, CachedPassphrase> mPassphraseCache = new HashMap<Long, CachedPassphrase>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This caches a new passphrase by sending a new command to the service. An android service is
|
||||||
|
* only run once. Thus when it is already started new commands just add new BroadcastReceivers
|
||||||
|
* for cached passphrases
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param keyId
|
||||||
|
* @param passphrase
|
||||||
|
*/
|
||||||
|
public static void addCachedPassphrase(Context context, long keyId, String passphrase) {
|
||||||
|
Log.d(Constants.TAG, "cacheNewPassphrase() for " + keyId);
|
||||||
|
|
||||||
public static void startCacheService(Context context) {
|
|
||||||
Intent intent = new Intent(context, PassphraseCacheService.class);
|
Intent intent = new Intent(context, PassphraseCacheService.class);
|
||||||
intent.putExtra(PassphraseCacheService.EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl());
|
intent.putExtra(EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl());
|
||||||
|
intent.putExtra(EXTRA_PASSPHRASE, passphrase);
|
||||||
|
intent.putExtra(EXTRA_KEY_ID, keyId);
|
||||||
|
|
||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int mPassPhraseCacheTtl = 15;
|
/**
|
||||||
private Handler mCacheHandler = new Handler();
|
* Gets a cached passphrase from memory
|
||||||
private Runnable mCacheTask = new Runnable() {
|
*
|
||||||
public void run() {
|
* @param context
|
||||||
// check every ttl/2 seconds, which shouldn't be heavy on the device (even if ttl = 15),
|
* @param keyId
|
||||||
// and makes sure the longest a pass phrase survives in the cache is 1.5 * ttl
|
* @return
|
||||||
int delay = mPassPhraseCacheTtl * 1000 / 2;
|
*/
|
||||||
// also make sure the delay is not longer than one minute
|
public static String getCachedPassphrase(Context context, long keyId) {
|
||||||
if (delay > 60000) {
|
// try to get real key id
|
||||||
delay = 60000;
|
long realId = keyId;
|
||||||
|
if (realId != Id.key.symmetric) {
|
||||||
|
PGPSecretKeyRing keyRing = PGPMain.getSecretKeyRing(keyId);
|
||||||
|
if (keyRing == null) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
PGPSecretKey masterKey = PGPHelper.getMasterKey(keyRing);
|
||||||
delay = PGPMain.cleanUpCache(mPassPhraseCacheTtl, delay);
|
if (masterKey == null) {
|
||||||
// don't check too often, even if we were close
|
return null;
|
||||||
if (delay < 5000) {
|
|
||||||
delay = 5000;
|
|
||||||
}
|
}
|
||||||
|
realId = masterKey.getKeyID();
|
||||||
mCacheHandler.postDelayed(this, delay);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
static private boolean mIsRunning = false;
|
// get cached passphrase
|
||||||
|
CachedPassphrase cpp = mPassphraseCache.get(realId);
|
||||||
|
if (cpp == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// set it again to reset the cache life cycle
|
||||||
|
addCachedPassphrase(context, realId, cpp.getPassphrase());
|
||||||
|
|
||||||
|
return cpp.getPassphrase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register BroadcastReceiver that is unregistered when service is destroyed. This
|
||||||
|
* BroadcastReceiver hears on intents with ACTION_PASSPHRASE_CACHE_SERVICE to timeout
|
||||||
|
* passphrases in memory.
|
||||||
|
*/
|
||||||
|
private void registerReceiver() {
|
||||||
|
if (mIntentReceiver == null) {
|
||||||
|
mIntentReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String action = intent.getAction();
|
||||||
|
|
||||||
|
if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) {
|
||||||
|
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
||||||
|
timeout(context, keyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
|
||||||
|
LocalBroadcastManager.getInstance(this).registerReceiver(mIntentReceiver, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build pending intent that is executed by alarm manager when one passphrase times out
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param keyId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static PendingIntent buildIntent(Context context, long keyId) {
|
||||||
|
Intent intent = new Intent(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
|
||||||
|
intent.putExtra(EXTRA_KEY_ID, keyId);
|
||||||
|
PendingIntent sender = PendingIntent.getBroadcast(context, REQUEST_ID, intent,
|
||||||
|
PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
|
||||||
|
return sender;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
Log.d(Constants.TAG, "PassphraseCacheService created!");
|
||||||
|
}
|
||||||
|
|
||||||
mIsRunning = true;
|
/**
|
||||||
|
* Executed when service is started by intent
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
Log.d(Constants.TAG, "PassphraseCacheService started");
|
||||||
|
|
||||||
|
// 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(Constants.TAG, "received intent with keyId: " + keyId + ", ttl: " + ttl);
|
||||||
|
|
||||||
|
// add keyId and passphrase to memory
|
||||||
|
mPassphraseCache.put(keyId,
|
||||||
|
new CachedPassphrase(System.currentTimeMillis(), passphrase));
|
||||||
|
|
||||||
|
// register new alarm with keyId for this passphrase
|
||||||
|
long triggerTime = System.currentTimeMillis() + ttl;
|
||||||
|
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
|
||||||
|
am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, keyId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return START_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when one specific passphrase for keyId timed out
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param keyId
|
||||||
|
*/
|
||||||
|
private void timeout(Context context, long keyId) {
|
||||||
|
Log.d(Constants.TAG, "Timeout of " + keyId);
|
||||||
|
|
||||||
|
// remove passphrase corresponding to keyId from memory
|
||||||
|
mPassphraseCache.remove(keyId);
|
||||||
|
|
||||||
|
// stop whole service if no cached passphrases remaining
|
||||||
|
if (mPassphraseCache.isEmpty()) {
|
||||||
|
Log.d(Constants.TAG, "No passphrases remaining in memory, stopping service!");
|
||||||
|
stopSelf();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
Log.d(Constants.TAG, "PassphraseCacheService destroyed!");
|
||||||
mIsRunning = false;
|
|
||||||
|
LocalBroadcastManager.getInstance(this).unregisterReceiver(mIntentReceiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public class PassphraseCacheBinder extends Binder {
|
||||||
public void onStart(Intent intent, int startId) {
|
public PassphraseCacheService getService() {
|
||||||
super.onStart(intent, startId);
|
|
||||||
|
|
||||||
if (intent != null) {
|
|
||||||
mPassPhraseCacheTtl = intent.getIntExtra(EXTRA_TTL, 15);
|
|
||||||
}
|
|
||||||
if (mPassPhraseCacheTtl < 15) {
|
|
||||||
mPassPhraseCacheTtl = 15;
|
|
||||||
}
|
|
||||||
mCacheHandler.removeCallbacks(mCacheTask);
|
|
||||||
mCacheHandler.postDelayed(mCacheTask, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
static public boolean isRunning() {
|
|
||||||
return mIsRunning;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LocalBinder extends Binder {
|
|
||||||
PassphraseCacheService getService() {
|
|
||||||
return PassphraseCacheService.this;
|
return PassphraseCacheService.this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final IBinder mBinder = new PassphraseCacheBinder();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -25,6 +25,7 @@ import org.thialfihar.android.apg.helper.PGPHelper;
|
|||||||
import org.thialfihar.android.apg.helper.PGPMain;
|
import org.thialfihar.android.apg.helper.PGPMain;
|
||||||
import org.thialfihar.android.apg.service.ApgServiceHandler;
|
import org.thialfihar.android.apg.service.ApgServiceHandler;
|
||||||
import org.thialfihar.android.apg.service.ApgService;
|
import org.thialfihar.android.apg.service.ApgService;
|
||||||
|
import org.thialfihar.android.apg.service.PassphraseCacheService;
|
||||||
import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
|
import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
|
||||||
import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
|
import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
|
||||||
import org.thialfihar.android.apg.ui.dialog.LookupUnknownKeyDialogFragment;
|
import org.thialfihar.android.apg.ui.dialog.LookupUnknownKeyDialogFragment;
|
||||||
@ -513,7 +514,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
|
|||||||
|
|
||||||
// if we need a symmetric passphrase or a passphrase to use a secret key ask for it
|
// if we need a symmetric passphrase or a passphrase to use a secret key ask for it
|
||||||
if (getSecretKeyId() == Id.key.symmetric
|
if (getSecretKeyId() == Id.key.symmetric
|
||||||
|| PGPMain.getCachedPassPhrase(getSecretKeyId()) == null) {
|
|| PassphraseCacheService.getCachedPassphrase(this, getSecretKeyId()) == null) {
|
||||||
showPassphraseDialog();
|
showPassphraseDialog();
|
||||||
} else {
|
} else {
|
||||||
if (mDecryptTarget == Id.target.file) {
|
if (mDecryptTarget == Id.target.file) {
|
||||||
@ -548,7 +549,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
|
|||||||
Messenger messenger = new Messenger(returnHandler);
|
Messenger messenger = new Messenger(returnHandler);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
|
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this,
|
||||||
messenger, mSecretKeyId);
|
messenger, mSecretKeyId);
|
||||||
|
|
||||||
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
|
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
|
||||||
|
@ -30,6 +30,7 @@ import org.thialfihar.android.apg.helper.PGPMain;
|
|||||||
import org.thialfihar.android.apg.helper.Preferences;
|
import org.thialfihar.android.apg.helper.Preferences;
|
||||||
import org.thialfihar.android.apg.service.ApgServiceHandler;
|
import org.thialfihar.android.apg.service.ApgServiceHandler;
|
||||||
import org.thialfihar.android.apg.service.ApgService;
|
import org.thialfihar.android.apg.service.ApgService;
|
||||||
|
import org.thialfihar.android.apg.service.PassphraseCacheService;
|
||||||
import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
|
import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
|
||||||
import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
|
import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
|
||||||
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
|
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
|
||||||
@ -659,7 +660,8 @@ public class EncryptActivity extends SherlockFragmentActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getSecretKeyId() != 0 && PGPMain.getCachedPassPhrase(getSecretKeyId()) == null) {
|
if (getSecretKeyId() != 0
|
||||||
|
&& PassphraseCacheService.getCachedPassphrase(this, getSecretKeyId()) == null) {
|
||||||
showPassphraseDialog();
|
showPassphraseDialog();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -697,7 +699,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
|
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
|
||||||
messenger, mSecretKeyId);
|
EncryptActivity.this, messenger, mSecretKeyId);
|
||||||
|
|
||||||
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
|
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
|
||||||
} catch (PGPMain.GeneralException e) {
|
} catch (PGPMain.GeneralException e) {
|
||||||
|
@ -69,7 +69,8 @@ public class PreferencesActivity extends SherlockPreferenceActivity {
|
|||||||
mPreferences.setPassPhraseCacheTtl(Integer.parseInt(newValue.toString()));
|
mPreferences.setPassPhraseCacheTtl(Integer.parseInt(newValue.toString()));
|
||||||
|
|
||||||
// restart cache service with new ttl
|
// restart cache service with new ttl
|
||||||
PassphraseCacheService.startCacheService(PreferencesActivity.this);
|
// TODO: not needed anymore!
|
||||||
|
// PassphraseCacheService.startCacheService(PreferencesActivity.this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -21,6 +21,7 @@ import org.thialfihar.android.apg.Constants;
|
|||||||
import org.thialfihar.android.apg.Id;
|
import org.thialfihar.android.apg.Id;
|
||||||
import org.thialfihar.android.apg.helper.PGPHelper;
|
import org.thialfihar.android.apg.helper.PGPHelper;
|
||||||
import org.thialfihar.android.apg.helper.PGPMain;
|
import org.thialfihar.android.apg.helper.PGPMain;
|
||||||
|
import org.thialfihar.android.apg.service.PassphraseCacheService;
|
||||||
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
|
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
|
||||||
import org.thialfihar.android.apg.util.Log;
|
import org.thialfihar.android.apg.util.Log;
|
||||||
|
|
||||||
@ -137,7 +138,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
|
|||||||
|
|
||||||
public void checkPassPhraseAndEdit() {
|
public void checkPassPhraseAndEdit() {
|
||||||
long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem);
|
long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem);
|
||||||
String passPhrase = PGPMain.getCachedPassPhrase(keyId);
|
String passPhrase = PassphraseCacheService.getCachedPassphrase(this, keyId);
|
||||||
if (passPhrase == null) {
|
if (passPhrase == null) {
|
||||||
showPassphraseDialog(keyId);
|
showPassphraseDialog(keyId);
|
||||||
} else {
|
} else {
|
||||||
@ -152,7 +153,8 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message message) {
|
public void handleMessage(Message message) {
|
||||||
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
|
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
|
||||||
String passPhrase = PGPMain.getCachedPassPhrase(secretKeyId);
|
String passPhrase = PassphraseCacheService.getCachedPassphrase(
|
||||||
|
SecretKeyListActivity.this, secretKeyId);
|
||||||
PGPMain.setEditPassPhrase(passPhrase);
|
PGPMain.setEditPassPhrase(passPhrase);
|
||||||
editKey();
|
editKey();
|
||||||
}
|
}
|
||||||
@ -164,7 +166,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
|
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
|
||||||
messenger, secretKeyId);
|
SecretKeyListActivity.this, messenger, secretKeyId);
|
||||||
|
|
||||||
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
|
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
|
||||||
} catch (PGPMain.GeneralException e) {
|
} catch (PGPMain.GeneralException e) {
|
||||||
|
@ -27,6 +27,7 @@ import org.thialfihar.android.apg.helper.PGPMain;
|
|||||||
import org.thialfihar.android.apg.helper.Preferences;
|
import org.thialfihar.android.apg.helper.Preferences;
|
||||||
import org.thialfihar.android.apg.service.ApgService;
|
import org.thialfihar.android.apg.service.ApgService;
|
||||||
import org.thialfihar.android.apg.service.ApgServiceHandler;
|
import org.thialfihar.android.apg.service.ApgServiceHandler;
|
||||||
|
import org.thialfihar.android.apg.service.PassphraseCacheService;
|
||||||
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
|
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
|
||||||
|
|
||||||
import com.actionbarsherlock.app.ActionBar;
|
import com.actionbarsherlock.app.ActionBar;
|
||||||
@ -141,7 +142,7 @@ public class SignKeyActivity extends SherlockFragmentActivity {
|
|||||||
Messenger messenger = new Messenger(returnHandler);
|
Messenger messenger = new Messenger(returnHandler);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
|
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this,
|
||||||
messenger, secretKeyId);
|
messenger, secretKeyId);
|
||||||
|
|
||||||
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
|
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
|
||||||
@ -175,7 +176,7 @@ public class SignKeyActivity extends SherlockFragmentActivity {
|
|||||||
/*
|
/*
|
||||||
* get the user's passphrase for this key (if required)
|
* get the user's passphrase for this key (if required)
|
||||||
*/
|
*/
|
||||||
String passphrase = PGPMain.getCachedPassPhrase(mMasterKeyId);
|
String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId);
|
||||||
if (passphrase == null) {
|
if (passphrase == null) {
|
||||||
showPassphraseDialog(mMasterKeyId);
|
showPassphraseDialog(mMasterKeyId);
|
||||||
return; // bail out; need to wait until the user has entered the passphrase
|
return; // bail out; need to wait until the user has entered the passphrase
|
||||||
|
@ -31,6 +31,7 @@ import org.thialfihar.android.apg.R;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.DialogInterface.OnClickListener;
|
import android.content.DialogInterface.OnClickListener;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -38,13 +39,22 @@ import android.os.Message;
|
|||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
|
|
||||||
|
import org.thialfihar.android.apg.service.PassphraseCacheService;
|
||||||
import org.thialfihar.android.apg.util.Log;
|
import org.thialfihar.android.apg.util.Log;
|
||||||
|
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.WindowManager.LayoutParams;
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.TextView.OnEditorActionListener;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class PassphraseDialogFragment extends DialogFragment {
|
public class PassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
||||||
|
|
||||||
private Messenger mMessenger;
|
private Messenger mMessenger;
|
||||||
|
|
||||||
@ -53,6 +63,8 @@ public class PassphraseDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
public static final int MESSAGE_OKAY = 1;
|
public static final int MESSAGE_OKAY = 1;
|
||||||
|
|
||||||
|
private EditText mPassphraseEditText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of this dialog fragment
|
* Creates new instance of this dialog fragment
|
||||||
*
|
*
|
||||||
@ -63,11 +75,11 @@ public class PassphraseDialogFragment extends DialogFragment {
|
|||||||
* @return
|
* @return
|
||||||
* @throws GeneralException
|
* @throws GeneralException
|
||||||
*/
|
*/
|
||||||
public static PassphraseDialogFragment newInstance(Messenger messenger, long secretKeyId)
|
public static PassphraseDialogFragment newInstance(Context context, Messenger messenger,
|
||||||
throws GeneralException {
|
long secretKeyId) throws GeneralException {
|
||||||
// check if secret key has a passphrase
|
// check if secret key has a passphrase
|
||||||
if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) {
|
if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) {
|
||||||
if (!hasPassphrase(secretKeyId)) {
|
if (!hasPassphrase(context, secretKeyId)) {
|
||||||
throw new PGPMain.GeneralException("No passphrase! No passphrase dialog needed!");
|
throw new PGPMain.GeneralException("No passphrase! No passphrase dialog needed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,7 +100,7 @@ public class PassphraseDialogFragment extends DialogFragment {
|
|||||||
* @param secretKeyId
|
* @param secretKeyId
|
||||||
* @return true if it has a passphrase
|
* @return true if it has a passphrase
|
||||||
*/
|
*/
|
||||||
private static boolean hasPassphrase(long secretKeyId) {
|
private static boolean hasPassphrase(Context context, long secretKeyId) {
|
||||||
// check if the key has no passphrase
|
// check if the key has no passphrase
|
||||||
try {
|
try {
|
||||||
PGPSecretKey secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
|
PGPSecretKey secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
|
||||||
@ -101,7 +113,7 @@ public class PassphraseDialogFragment extends DialogFragment {
|
|||||||
Log.d(Constants.TAG, "Key has no passphrase! Caches empty passphrase!");
|
Log.d(Constants.TAG, "Key has no passphrase! Caches empty passphrase!");
|
||||||
|
|
||||||
// cache empty passphrase
|
// cache empty passphrase
|
||||||
PGPMain.setCachedPassPhrase(secretKey.getKeyID(), "");
|
PassphraseCacheService.addCachedPassphrase(context, secretKey.getKeyID(), "");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -112,6 +124,11 @@ public class PassphraseDialogFragment extends DialogFragment {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates dialog
|
* Creates dialog
|
||||||
*/
|
*/
|
||||||
@ -154,13 +171,13 @@ public class PassphraseDialogFragment extends DialogFragment {
|
|||||||
View view = inflater.inflate(R.layout.passphrase, null);
|
View view = inflater.inflate(R.layout.passphrase, null);
|
||||||
alert.setView(view);
|
alert.setView(view);
|
||||||
|
|
||||||
final EditText input = (EditText) view.findViewById(R.id.passphrase_passphrase);
|
mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
|
||||||
|
|
||||||
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
dismiss();
|
dismiss();
|
||||||
|
|
||||||
String passPhrase = input.getText().toString();
|
String passPhrase = mPassphraseEditText.getText().toString();
|
||||||
long keyId;
|
long keyId;
|
||||||
if (secretKey != null) {
|
if (secretKey != null) {
|
||||||
try {
|
try {
|
||||||
@ -185,7 +202,7 @@ public class PassphraseDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
// cache the new passphrase
|
// cache the new passphrase
|
||||||
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
|
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
|
||||||
PGPMain.setCachedPassPhrase(keyId, passPhrase);
|
PassphraseCacheService.addCachedPassphrase(activity, keyId, passPhrase);
|
||||||
|
|
||||||
sendMessageToHandler(MESSAGE_OKAY);
|
sendMessageToHandler(MESSAGE_OKAY);
|
||||||
}
|
}
|
||||||
@ -200,6 +217,32 @@ public class PassphraseDialogFragment extends DialogFragment {
|
|||||||
return alert.create();
|
return alert.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Bundle arg0) {
|
||||||
|
super.onActivityCreated(arg0);
|
||||||
|
|
||||||
|
// request focus and open soft keyboard
|
||||||
|
mPassphraseEditText.requestFocus();
|
||||||
|
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||||
|
|
||||||
|
mPassphraseEditText.setOnEditorActionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate the "done" button on the soft keyboard with the okay button in the view
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||||
|
if (EditorInfo.IME_ACTION_DONE == actionId) {
|
||||||
|
AlertDialog dialog = ((AlertDialog) getDialog());
|
||||||
|
Button bt = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||||
|
|
||||||
|
bt.performClick();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send message back to handler which is initialized in a activity
|
* Send message back to handler which is initialized in a activity
|
||||||
*
|
*
|
||||||
@ -218,4 +261,5 @@ public class PassphraseDialogFragment extends DialogFragment {
|
|||||||
Log.w(Constants.TAG, "Messenger is null!", e);
|
Log.w(Constants.TAG, "Messenger is null!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -29,12 +29,19 @@ import android.os.Messenger;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import org.thialfihar.android.apg.util.Log;
|
import org.thialfihar.android.apg.util.Log;
|
||||||
|
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.WindowManager.LayoutParams;
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import android.widget.TextView.OnEditorActionListener;
|
||||||
|
|
||||||
public class SetPassphraseDialogFragment extends DialogFragment {
|
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
||||||
private Messenger mMessenger;
|
private Messenger mMessenger;
|
||||||
|
|
||||||
private static final String ARG_MESSENGER = "messenger";
|
private static final String ARG_MESSENGER = "messenger";
|
||||||
@ -44,6 +51,9 @@ public class SetPassphraseDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
public static final String MESSAGE_NEW_PASSPHRASE = "new_passphrase";
|
public static final String MESSAGE_NEW_PASSPHRASE = "new_passphrase";
|
||||||
|
|
||||||
|
private EditText mPassphraseEditText;
|
||||||
|
private EditText mPassphraseAgainEditText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of this dialog fragment
|
* Creates new instance of this dialog fragment
|
||||||
*
|
*
|
||||||
@ -81,17 +91,17 @@ public class SetPassphraseDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
LayoutInflater inflater = activity.getLayoutInflater();
|
LayoutInflater inflater = activity.getLayoutInflater();
|
||||||
View view = inflater.inflate(R.layout.passphrase_repeat, null);
|
View view = inflater.inflate(R.layout.passphrase_repeat, null);
|
||||||
final EditText input1 = (EditText) view.findViewById(R.id.passphrase_passphrase);
|
|
||||||
final EditText input2 = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
|
|
||||||
|
|
||||||
alert.setView(view);
|
alert.setView(view);
|
||||||
|
|
||||||
|
mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
|
||||||
|
mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
|
||||||
|
|
||||||
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
dismiss();
|
dismiss();
|
||||||
|
|
||||||
String passPhrase1 = input1.getText().toString();
|
String passPhrase1 = mPassphraseEditText.getText().toString();
|
||||||
String passPhrase2 = input2.getText().toString();
|
String passPhrase2 = mPassphraseAgainEditText.getText().toString();
|
||||||
if (!passPhrase1.equals(passPhrase2)) {
|
if (!passPhrase1.equals(passPhrase2)) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
activity,
|
activity,
|
||||||
@ -127,6 +137,32 @@ public class SetPassphraseDialogFragment extends DialogFragment {
|
|||||||
return alert.create();
|
return alert.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Bundle arg0) {
|
||||||
|
super.onActivityCreated(arg0);
|
||||||
|
|
||||||
|
// request focus and open soft keyboard
|
||||||
|
mPassphraseEditText.requestFocus();
|
||||||
|
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||||
|
|
||||||
|
mPassphraseAgainEditText.setOnEditorActionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate the "done" button on the soft keyboard with the okay button in the view
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||||
|
if (EditorInfo.IME_ACTION_DONE == actionId) {
|
||||||
|
AlertDialog dialog = ((AlertDialog) getDialog());
|
||||||
|
Button bt = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||||
|
|
||||||
|
bt.performClick();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send message back to handler which is initialized in a activity
|
* Send message back to handler which is initialized in a activity
|
||||||
*
|
*
|
||||||
|
@ -23,6 +23,7 @@ import org.thialfihar.android.apg.helper.PGPMain;
|
|||||||
import org.thialfihar.android.apg.helper.PGPConversionHelper;
|
import org.thialfihar.android.apg.helper.PGPConversionHelper;
|
||||||
import org.thialfihar.android.apg.service.ApgServiceHandler;
|
import org.thialfihar.android.apg.service.ApgServiceHandler;
|
||||||
import org.thialfihar.android.apg.service.ApgService;
|
import org.thialfihar.android.apg.service.ApgService;
|
||||||
|
import org.thialfihar.android.apg.service.PassphraseCacheService;
|
||||||
import org.thialfihar.android.apg.ui.dialog.ProgressDialogFragment;
|
import org.thialfihar.android.apg.ui.dialog.ProgressDialogFragment;
|
||||||
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
|
import org.thialfihar.android.apg.ui.widget.Editor.EditorListener;
|
||||||
import org.thialfihar.android.apg.util.Choice;
|
import org.thialfihar.android.apg.util.Choice;
|
||||||
@ -259,7 +260,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
|||||||
String passPhrase;
|
String passPhrase;
|
||||||
if (mEditors.getChildCount() > 0) {
|
if (mEditors.getChildCount() > 0) {
|
||||||
PGPSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
|
PGPSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
|
||||||
passPhrase = PGPMain.getCachedPassPhrase(masterKey.getKeyID());
|
passPhrase = PassphraseCacheService
|
||||||
|
.getCachedPassphrase(mActivity, masterKey.getKeyID());
|
||||||
|
|
||||||
data.putByteArray(ApgService.MASTER_KEY,
|
data.putByteArray(ApgService.MASTER_KEY,
|
||||||
PGPConversionHelper.PGPSecretKeyToBytes(masterKey));
|
PGPConversionHelper.PGPSecretKeyToBytes(masterKey));
|
||||||
|
@ -20,7 +20,6 @@ import java.io.Serializable;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
Loading…
Reference in New Issue
Block a user