working on externalizing encrypt methods into the service
This commit is contained in:
@@ -64,6 +64,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
|
||||
import org.thialfihar.android.apg.Id.return_value;
|
||||
import org.thialfihar.android.apg.KeyServer.AddKeyException;
|
||||
import org.thialfihar.android.apg.passphrase.CachedPassPhrase;
|
||||
import org.thialfihar.android.apg.provider.DataProvider;
|
||||
import org.thialfihar.android.apg.provider.Database;
|
||||
import org.thialfihar.android.apg.provider.KeyRings;
|
||||
@@ -2289,7 +2290,7 @@ public class Apg {
|
||||
return result;
|
||||
}
|
||||
|
||||
static long getLengthOfStream(InputStream in) throws IOException {
|
||||
public static long getLengthOfStream(InputStream in) throws IOException {
|
||||
long size = 0;
|
||||
long n = 0;
|
||||
byte dummy[] = new byte[0x10000];
|
||||
|
||||
18
org_apg/src/org/thialfihar/android/apg/ApgApplication.java
Normal file
18
org_apg/src/org/thialfihar/android/apg/ApgApplication.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package org.thialfihar.android.apg;
|
||||
|
||||
import org.thialfihar.android.apg.passphrase.PassphraseCacheService;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Intent;
|
||||
|
||||
public class ApgApplication extends Application {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
/** Start passphrase cache service */
|
||||
PassphraseCacheService.startCacheService(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.thialfihar.android.apg.R;
|
||||
import org.thialfihar.android.apg.Apg.GeneralException;
|
||||
@@ -26,7 +27,10 @@ import org.thialfihar.android.apg.Apg.GeneralException;
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
|
||||
public class DataDestination {
|
||||
public class DataDestination implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6478075911319320498L;
|
||||
|
||||
private String mStreamFilename;
|
||||
private String mFilename;
|
||||
private int mMode = Id.mode.undefined;
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.thialfihar.android.apg.R;
|
||||
import org.thialfihar.android.apg.Apg.GeneralException;
|
||||
@@ -28,7 +29,10 @@ import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
|
||||
public class DataSource {
|
||||
public class DataSource implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2377217399907415255L;
|
||||
|
||||
private Uri mContentUri = null;
|
||||
private String mText = null;
|
||||
private byte[] mData = null;
|
||||
@@ -51,6 +55,10 @@ public class DataSource {
|
||||
}
|
||||
}
|
||||
|
||||
public Uri getUri() {
|
||||
return mContentUri;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
mText = text;
|
||||
mData = null;
|
||||
@@ -71,6 +79,17 @@ public class DataSource {
|
||||
return mData != null || mContentUri != null;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
byte[] bytes = null;
|
||||
if (mData != null) {
|
||||
bytes = mData;
|
||||
} else {
|
||||
bytes = mText.getBytes();
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public InputData getInputData(Context context, boolean withSize) throws GeneralException,
|
||||
FileNotFoundException, IOException {
|
||||
InputStream in = null;
|
||||
|
||||
@@ -22,6 +22,10 @@ import android.content.SharedPreferences;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Singelton Implementation of a Preference Helper
|
||||
*
|
||||
*/
|
||||
public class Preferences {
|
||||
private static Preferences mPreferences;
|
||||
private SharedPreferences mSharedPreferences;
|
||||
|
||||
@@ -14,12 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg;
|
||||
package org.thialfihar.android.apg.passphrase;
|
||||
|
||||
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.Apg;
|
||||
import org.thialfihar.android.apg.Id;
|
||||
import org.thialfihar.android.apg.R;
|
||||
|
||||
import android.app.Activity;
|
||||
@@ -35,7 +37,7 @@ import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class AskForSecretKeyPassPhrase {
|
||||
public class AskForPassphrase {
|
||||
public static interface PassPhraseCallbackInterface {
|
||||
void passPhraseCallback(long keyId, String passPhrase);
|
||||
}
|
||||
@@ -107,6 +109,10 @@ public class AskForSecretKeyPassPhrase {
|
||||
} else {
|
||||
keyId = Id.key.symmetric;
|
||||
}
|
||||
|
||||
// cache again
|
||||
Apg.setCachedPassPhrase(keyId, passPhrase);
|
||||
// return by callback
|
||||
cb.passPhraseCallback(keyId, passPhrase);
|
||||
}
|
||||
});
|
||||
@@ -126,6 +132,9 @@ public class AskForSecretKeyPassPhrase {
|
||||
if (testKey != null) {
|
||||
Log.d("APG", "Key has no passphrase!");
|
||||
|
||||
// cache null
|
||||
Apg.setCachedPassPhrase(secretKey.getKeyID(), null);
|
||||
// return by callback
|
||||
cb.passPhraseCallback(secretKey.getKeyID(), null);
|
||||
|
||||
return null;
|
||||
@@ -12,7 +12,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg;
|
||||
package org.thialfihar.android.apg.passphrase;
|
||||
|
||||
public class CachedPassPhrase {
|
||||
public final long timestamp;
|
||||
@@ -12,11 +12,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg.service;
|
||||
package org.thialfihar.android.apg.passphrase;
|
||||
|
||||
import org.thialfihar.android.apg.Apg;
|
||||
import org.thialfihar.android.apg.Preferences;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
@@ -27,6 +29,12 @@ public class PassphraseCacheService extends Service {
|
||||
|
||||
public static final String EXTRA_TTL = "ttl";
|
||||
|
||||
public static void startCacheService(Context context) {
|
||||
Intent intent = new Intent(context, PassphraseCacheService.class);
|
||||
intent.putExtra(PassphraseCacheService.EXTRA_TTL, Preferences.getPreferences(context).getPassPhraseCacheTtl());
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
private int mPassPhraseCacheTtl = 15;
|
||||
private Handler mCacheHandler = new Handler();
|
||||
private Runnable mCacheTask = new Runnable() {
|
||||
@@ -12,7 +12,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg.provider;
|
||||
package org.thialfihar.android.apg.provider.blob;
|
||||
|
||||
import org.thialfihar.android.apg.service.ApgService2;
|
||||
|
||||
@@ -26,43 +26,47 @@ import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
public class ApgServiceBlobDatabase extends SQLiteOpenHelper {
|
||||
|
||||
|
||||
private static final String TAG = "ApgServiceBlobDatabase";
|
||||
|
||||
private static final int VERSION = 1;
|
||||
private static final String NAME = "apg_service_blob_data";
|
||||
private static final String TABLE = "data";
|
||||
|
||||
|
||||
public ApgServiceBlobDatabase(Context context) {
|
||||
super(context, NAME, null, VERSION);
|
||||
if(ApgService2.LOCAL_LOGD) Log.d(TAG, "constructor called");
|
||||
if (ApgService2.LOCAL_LOGD)
|
||||
Log.d(TAG, "constructor called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
if(ApgService2.LOCAL_LOGD) Log.d(TAG, "onCreate() called");
|
||||
db.execSQL("create table " + TABLE + " ( _id integer primary key autoincrement," +
|
||||
"key text not null)");
|
||||
if (ApgService2.LOCAL_LOGD)
|
||||
Log.d(TAG, "onCreate() called");
|
||||
db.execSQL("create table " + TABLE + " ( _id integer primary key autoincrement,"
|
||||
+ "key text not null)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if(ApgService2.LOCAL_LOGD) Log.d(TAG, "onUpgrade() called");
|
||||
if (ApgService2.LOCAL_LOGD)
|
||||
Log.d(TAG, "onUpgrade() called");
|
||||
// no upgrade necessary yet
|
||||
}
|
||||
|
||||
|
||||
public Uri insert(ContentValues vals) {
|
||||
if(ApgService2.LOCAL_LOGD) Log.d(TAG, "insert() called");
|
||||
if (ApgService2.LOCAL_LOGD)
|
||||
Log.d(TAG, "insert() called");
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
long newId = db.insert(TABLE, null, vals);
|
||||
return ContentUris.withAppendedId(ApgServiceBlobProvider.CONTENT_URI, newId);
|
||||
}
|
||||
|
||||
|
||||
public Cursor query(String id, String key) {
|
||||
if(ApgService2.LOCAL_LOGD) Log.d(TAG, "query() called");
|
||||
if (ApgService2.LOCAL_LOGD)
|
||||
Log.d(TAG, "query() called");
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
return db.query(TABLE, new String[] {"_id"},
|
||||
"_id = ? and key = ?", new String[] {id, key},
|
||||
null, null, null);
|
||||
return db.query(TABLE, new String[] { "_id" }, "_id = ? and key = ?", new String[] { id,
|
||||
key }, null, null, null);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.thialfihar.android.apg.provider;
|
||||
package org.thialfihar.android.apg.provider.blob;
|
||||
|
||||
import org.thialfihar.android.apg.Constants;
|
||||
import org.thialfihar.android.apg.service.ApgService2;
|
||||
@@ -0,0 +1,42 @@
|
||||
//package org.thialfihar.android.apg.provider.blob;
|
||||
//
|
||||
//import android.net.Uri;
|
||||
//import android.provider.BaseColumns;
|
||||
//
|
||||
//public class BlobContract {
|
||||
//
|
||||
// interface BlobColumns {
|
||||
// String DATA = "data";
|
||||
// }
|
||||
//
|
||||
// public static final String CONTENT_AUTHORITY = "org.thialfihar.android.apg";
|
||||
//
|
||||
// private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
|
||||
//
|
||||
// public static final String PATH_BLOB = "blob";
|
||||
//
|
||||
// public static class Blobs implements BlobColumns, BaseColumns {
|
||||
// public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(PATH_BLOB)
|
||||
// .build();
|
||||
//
|
||||
// /** Use if multiple items get returned */
|
||||
// public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.apg.blob";
|
||||
//
|
||||
// /** Use if a single item is returned */
|
||||
// public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.apg.blob";
|
||||
//
|
||||
// /** Default "ORDER BY" clause. */
|
||||
// public static final String DEFAULT_SORT = BaseColumns._ID + " ASC";
|
||||
//
|
||||
// public static Uri buildUri(String id) {
|
||||
// return CONTENT_URI.buildUpon().appendPath(id).build();
|
||||
// }
|
||||
//
|
||||
// public static String getId(Uri uri) {
|
||||
// return uri.getLastPathSegment();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private BlobContract() {
|
||||
// }
|
||||
//}
|
||||
@@ -39,10 +39,6 @@ public class ApgHandler extends Handler {
|
||||
public static final String DATA_MESSAGE = "message";
|
||||
public static final String DATA_MESSAGE_ID = "message_id";
|
||||
|
||||
// possible data keys as result from service
|
||||
public static final String RESULT_NEW_KEY = "new_key";
|
||||
public static final String RESULT_NEW_KEY2 = "new_key2";
|
||||
|
||||
Activity mActivity;
|
||||
ProgressDialogFragment mProgressDialogFragment;
|
||||
|
||||
|
||||
@@ -16,19 +16,37 @@
|
||||
|
||||
package org.thialfihar.android.apg.service;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.thialfihar.android.apg.Apg;
|
||||
import org.thialfihar.android.apg.Constants;
|
||||
import org.thialfihar.android.apg.DataDestination;
|
||||
import org.thialfihar.android.apg.DataSource;
|
||||
import org.thialfihar.android.apg.Id;
|
||||
import org.thialfihar.android.apg.InputData;
|
||||
import org.thialfihar.android.apg.Preferences;
|
||||
import org.thialfihar.android.apg.ProgressDialogUpdater;
|
||||
import org.thialfihar.android.apg.R;
|
||||
import org.thialfihar.android.apg.Apg.GeneralException;
|
||||
import org.thialfihar.android.apg.provider.DataProvider;
|
||||
import org.thialfihar.android.apg.util.Utils;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
@@ -37,7 +55,7 @@ import android.util.Log;
|
||||
/**
|
||||
* 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
|
||||
* doing it.
|
||||
* after doing them.
|
||||
*/
|
||||
// TODO: ProgressDialogUpdater rework???
|
||||
public class ApgService extends IntentService implements ProgressDialogUpdater {
|
||||
@@ -62,11 +80,40 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
||||
public static final String PASSPHRASE = "passphrase";
|
||||
public static final String MASTER_KEY = "master_key";
|
||||
|
||||
// encrypt
|
||||
public static final String SECRET_KEY_ID = "secret_key_id";
|
||||
// public static final String DATA_SOURCE = "data_source";
|
||||
// public static final String DATA_DESTINATION = "data_destination";
|
||||
public static final String USE_ASCII_AMOR = "use_ascii_amor";
|
||||
// public static final String ENCRYPTION_TARGET = "encryption_target";
|
||||
public static final String ENCRYPTION_KEYS_IDS = "encryption_keys_ids";
|
||||
public static final String SIGNATURE_KEY_ID = "signature_key_id";
|
||||
public static final String COMPRESSION_ID = "compression_id";
|
||||
public static final String GENERATE_SIGNATURE = "generate_signature";
|
||||
public static final String SIGN_ONLY = "sign_only";
|
||||
public static final String BYTES = "bytes";
|
||||
public static final String FILE_URI = "file_uri";
|
||||
public static final String OUTPUT_FILENAME = "output_filename";
|
||||
public static final String PROVIDER_URI = "provider_uri";
|
||||
|
||||
// possible ints for EXTRA_ACTION
|
||||
public static final int ACTION_SAVE_KEYRING = 1;
|
||||
public static final int ACTION_GENERATE_KEY = 2;
|
||||
public static final int ACTION_GENERATE_DEFAULT_RSA_KEYS = 3;
|
||||
|
||||
public static final int ACTION_ENCRYPT_SIGN_BYTES = 4;
|
||||
public static final int ACTION_ENCRYPT_SIGN_FILE = 5;
|
||||
public static final int ACTION_ENCRYPT_SIGN_STREAM = 6;
|
||||
|
||||
// possible data keys as result
|
||||
public static final String RESULT_NEW_KEY = "new_key";
|
||||
public static final String RESULT_NEW_KEY2 = "new_key2";
|
||||
public static final String RESULT_SIGNATURE_DATA = "signatureData";
|
||||
public static final String RESULT_SIGNATURE_TEXT = "signatureText";
|
||||
public static final String RESULT_ENCRYPTED_MESSAGE = "encryptedMessage";
|
||||
public static final String RESULT_ENCRYPTED_DATA = "encryptedData";
|
||||
public static final String RESULT_URI = "resultUri";
|
||||
|
||||
Messenger mMessenger;
|
||||
|
||||
public ApgService() {
|
||||
@@ -82,26 +129,19 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
Bundle extras = intent.getExtras();
|
||||
if (extras == null) {
|
||||
Log.e(Constants.TAG, "Extra bundle is null!");
|
||||
Log.e(Constants.TAG, "Extras bundle is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!extras.containsKey(EXTRA_MESSENGER)) {
|
||||
Log.e(Constants.TAG, "Extra bundle must contain a messenger!");
|
||||
if (!(extras.containsKey(EXTRA_MESSENGER) || extras.containsKey(EXTRA_DATA) || extras
|
||||
.containsKey(EXTRA_ACTION))) {
|
||||
Log.e(Constants.TAG,
|
||||
"Extra bundle must contain a messenger, a data bundle, and an action!");
|
||||
return;
|
||||
}
|
||||
|
||||
mMessenger = (Messenger) extras.get(EXTRA_MESSENGER);
|
||||
|
||||
if (!extras.containsKey(EXTRA_DATA)) {
|
||||
Log.e(Constants.TAG, "Extra bundle must contain data bundle!");
|
||||
return;
|
||||
}
|
||||
Bundle data = extras.getBundle(EXTRA_DATA);
|
||||
|
||||
if (!extras.containsKey(EXTRA_ACTION)) {
|
||||
Log.e(Constants.TAG, "Extra bundle must contain a action!");
|
||||
return;
|
||||
}
|
||||
int action = extras.getInt(EXTRA_ACTION);
|
||||
|
||||
// execute action from extra bundle
|
||||
@@ -155,9 +195,8 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
||||
|
||||
// Output
|
||||
Bundle resultData = new Bundle();
|
||||
resultData.putByteArray(ApgHandler.RESULT_NEW_KEY,
|
||||
Utils.PGPSecretKeyRingToBytes(newKeyRing));
|
||||
sendMessageToHandler(ApgHandler.MESSAGE_OKAY, null, resultData);
|
||||
resultData.putByteArray(RESULT_NEW_KEY, Utils.PGPSecretKeyRingToBytes(newKeyRing));
|
||||
sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData);
|
||||
} catch (Exception e) {
|
||||
sendErrorToHandler(e);
|
||||
}
|
||||
@@ -178,13 +217,263 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
||||
|
||||
// Output
|
||||
Bundle resultData = new Bundle();
|
||||
resultData.putByteArray(ApgHandler.RESULT_NEW_KEY,
|
||||
resultData.putByteArray(RESULT_NEW_KEY,
|
||||
Utils.PGPSecretKeyRingToBytes(masterKeyRing));
|
||||
resultData.putByteArray(ApgHandler.RESULT_NEW_KEY2,
|
||||
Utils.PGPSecretKeyRingToBytes(subKeyRing));
|
||||
sendMessageToHandler(ApgHandler.MESSAGE_OKAY, null, resultData);
|
||||
resultData.putByteArray(RESULT_NEW_KEY2, Utils.PGPSecretKeyRingToBytes(subKeyRing));
|
||||
sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData);
|
||||
} catch (Exception e) {
|
||||
Log.e(Constants.TAG, "Creating initial key failed: +" + e);
|
||||
sendErrorToHandler(e);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ACTION_ENCRYPT_SIGN_BYTES:
|
||||
|
||||
try {
|
||||
// Input
|
||||
long secretKeyId = data.getLong(SECRET_KEY_ID);
|
||||
String passphrase = data.getString(PASSPHRASE);
|
||||
|
||||
byte[] bytes = data.getByteArray(BYTES);
|
||||
|
||||
boolean useAsciiArmour = data.getBoolean(USE_ASCII_AMOR);
|
||||
long encryptionKeyIds[] = data.getLongArray(ENCRYPTION_KEYS_IDS);
|
||||
long signatureKeyId = data.getLong(SIGNATURE_KEY_ID);
|
||||
int compressionId = data.getInt(COMPRESSION_ID);
|
||||
boolean generateSignature = data.getBoolean(GENERATE_SIGNATURE);
|
||||
boolean signOnly = data.getBoolean(SIGN_ONLY);
|
||||
|
||||
// Operation
|
||||
ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
|
||||
int inLength = bytes.length;
|
||||
|
||||
InputData inputData = new InputData(inStream, inLength);
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
|
||||
if (generateSignature) {
|
||||
Apg.generateSignature(this, inputData, outStream, useAsciiArmour, false,
|
||||
secretKeyId, Apg.getCachedPassPhrase(secretKeyId), Preferences
|
||||
.getPreferences(this).getDefaultHashAlgorithm(), Preferences
|
||||
.getPreferences(this).getForceV3Signatures(), this);
|
||||
} else if (signOnly) {
|
||||
Apg.signText(this, inputData, outStream, secretKeyId, Apg
|
||||
.getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this)
|
||||
.getDefaultHashAlgorithm(), Preferences.getPreferences(this)
|
||||
.getForceV3Signatures(), this);
|
||||
} else {
|
||||
Apg.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds,
|
||||
signatureKeyId, Apg.getCachedPassPhrase(signatureKeyId), this,
|
||||
Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(),
|
||||
Preferences.getPreferences(this).getDefaultHashAlgorithm(),
|
||||
compressionId, Preferences.getPreferences(this).getForceV3Signatures(),
|
||||
passphrase);
|
||||
}
|
||||
|
||||
outStream.close();
|
||||
|
||||
// Output
|
||||
Bundle resultData = new Bundle();
|
||||
|
||||
// if (encryptionTarget != Id.target.file) {
|
||||
// if (out instanceof ByteArrayOutputStream) {
|
||||
if (useAsciiArmour) {
|
||||
String output = new String(outStream.toByteArray());
|
||||
if (generateSignature) {
|
||||
resultData.putString(RESULT_SIGNATURE_TEXT, output);
|
||||
} else {
|
||||
resultData.putString(RESULT_ENCRYPTED_MESSAGE, output);
|
||||
}
|
||||
} else {
|
||||
byte output[] = outStream.toByteArray();
|
||||
if (generateSignature) {
|
||||
resultData.putByteArray(RESULT_SIGNATURE_DATA, output);
|
||||
} else {
|
||||
resultData.putByteArray(RESULT_ENCRYPTED_DATA, output);
|
||||
}
|
||||
}
|
||||
// } else if (out instanceof FileOutputStream) {
|
||||
// String fileName = dataDestination.getStreamFilename();
|
||||
// String uri = "content://" + DataProvider.AUTHORITY + "/data/" + fileName;
|
||||
// resultData.putString(RESULT_URI, uri);
|
||||
// } else {
|
||||
// sendErrorToHandler(new Apg.GeneralException("No output-data found."));
|
||||
// }
|
||||
// }
|
||||
|
||||
sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData);
|
||||
} catch (Exception e) {
|
||||
sendErrorToHandler(e);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ACTION_ENCRYPT_SIGN_FILE:
|
||||
try {
|
||||
// Input
|
||||
long secretKeyId = data.getLong(SECRET_KEY_ID);
|
||||
String passphrase = data.getString(PASSPHRASE);
|
||||
|
||||
Uri fileUri = Uri.parse(data.getString(FILE_URI));
|
||||
String outputFilename = data.getString(OUTPUT_FILENAME);
|
||||
|
||||
boolean useAsciiArmour = data.getBoolean(USE_ASCII_AMOR);
|
||||
long encryptionKeyIds[] = data.getLongArray(ENCRYPTION_KEYS_IDS);
|
||||
long signatureKeyId = data.getLong(SIGNATURE_KEY_ID);
|
||||
int compressionId = data.getInt(COMPRESSION_ID);
|
||||
boolean generateSignature = data.getBoolean(GENERATE_SIGNATURE);
|
||||
boolean signOnly = data.getBoolean(SIGN_ONLY);
|
||||
|
||||
// InputStream
|
||||
long inLength = -1;
|
||||
FileInputStream inStream = null;
|
||||
if (fileUri.getScheme().equals("file")) {
|
||||
// get the rest after "file://"
|
||||
String path = Uri.decode(fileUri.toString().substring(7));
|
||||
if (path.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
|
||||
if (!Environment.getExternalStorageState()
|
||||
.equals(Environment.MEDIA_MOUNTED)) {
|
||||
sendErrorToHandler(new GeneralException(
|
||||
getString(R.string.error_externalStorageNotReady)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
inStream = new FileInputStream(path);
|
||||
File file = new File(path);
|
||||
inLength = file.length();
|
||||
}
|
||||
|
||||
InputData inputData = new InputData(inStream, inLength);
|
||||
|
||||
// OutputStream
|
||||
if (outputFilename.startsWith(Environment.getExternalStorageDirectory()
|
||||
.getAbsolutePath())) {
|
||||
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
sendErrorToHandler(new GeneralException(
|
||||
getString(R.string.error_externalStorageNotReady)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
FileOutputStream outStream = new FileOutputStream(outputFilename);
|
||||
|
||||
// Operation
|
||||
if (generateSignature) {
|
||||
Apg.generateSignature(this, inputData, outStream, useAsciiArmour, true,
|
||||
secretKeyId, Apg.getCachedPassPhrase(secretKeyId), Preferences
|
||||
.getPreferences(this).getDefaultHashAlgorithm(), Preferences
|
||||
.getPreferences(this).getForceV3Signatures(), this);
|
||||
} else if (signOnly) {
|
||||
Apg.signText(this, inputData, outStream, secretKeyId, Apg
|
||||
.getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this)
|
||||
.getDefaultHashAlgorithm(), Preferences.getPreferences(this)
|
||||
.getForceV3Signatures(), this);
|
||||
} else {
|
||||
Apg.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds,
|
||||
signatureKeyId, Apg.getCachedPassPhrase(signatureKeyId), this,
|
||||
Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(),
|
||||
Preferences.getPreferences(this).getDefaultHashAlgorithm(),
|
||||
compressionId, Preferences.getPreferences(this).getForceV3Signatures(),
|
||||
passphrase);
|
||||
}
|
||||
|
||||
outStream.close();
|
||||
|
||||
sendMessageToHandler(ApgHandler.MESSAGE_OKAY);
|
||||
} catch (Exception e) {
|
||||
sendErrorToHandler(e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTION_ENCRYPT_SIGN_STREAM:
|
||||
try {
|
||||
// Input
|
||||
long secretKeyId = data.getLong(SECRET_KEY_ID);
|
||||
String passphrase = data.getString(PASSPHRASE);
|
||||
|
||||
Uri providerUri = Uri.parse(data.getString(PROVIDER_URI));
|
||||
|
||||
boolean useAsciiArmour = data.getBoolean(USE_ASCII_AMOR);
|
||||
long encryptionKeyIds[] = data.getLongArray(ENCRYPTION_KEYS_IDS);
|
||||
long signatureKeyId = data.getLong(SIGNATURE_KEY_ID);
|
||||
int compressionId = data.getInt(COMPRESSION_ID);
|
||||
boolean generateSignature = data.getBoolean(GENERATE_SIGNATURE);
|
||||
boolean signOnly = data.getBoolean(SIGN_ONLY);
|
||||
|
||||
// InputStream
|
||||
InputStream in = getContentResolver().openInputStream(providerUri);
|
||||
long inLength = Apg.getLengthOfStream(in);
|
||||
|
||||
InputData inputData = new InputData(in, inLength);
|
||||
|
||||
// OutputStream
|
||||
String streamFilename = null;
|
||||
try {
|
||||
while (true) {
|
||||
streamFilename = Apg.generateRandomString(32);
|
||||
if (streamFilename == null) {
|
||||
throw new Apg.GeneralException("couldn't generate random file name");
|
||||
}
|
||||
openFileInput(streamFilename).close();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
// found a name that isn't used yet
|
||||
}
|
||||
FileOutputStream outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE);
|
||||
|
||||
// Operation
|
||||
|
||||
if (generateSignature) {
|
||||
Apg.generateSignature(this, inputData, outStream, useAsciiArmour, true,
|
||||
secretKeyId, Apg.getCachedPassPhrase(secretKeyId), Preferences
|
||||
.getPreferences(this).getDefaultHashAlgorithm(), Preferences
|
||||
.getPreferences(this).getForceV3Signatures(), this);
|
||||
} else if (signOnly) {
|
||||
Apg.signText(this, inputData, outStream, secretKeyId, Apg
|
||||
.getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this)
|
||||
.getDefaultHashAlgorithm(), Preferences.getPreferences(this)
|
||||
.getForceV3Signatures(), this);
|
||||
} else {
|
||||
Apg.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds,
|
||||
signatureKeyId, Apg.getCachedPassPhrase(signatureKeyId), this,
|
||||
Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(),
|
||||
Preferences.getPreferences(this).getDefaultHashAlgorithm(),
|
||||
compressionId, Preferences.getPreferences(this).getForceV3Signatures(),
|
||||
passphrase);
|
||||
}
|
||||
|
||||
outStream.close();
|
||||
|
||||
// Output
|
||||
Bundle resultData = new Bundle();
|
||||
|
||||
// if (encryptionTarget != Id.target.file) {
|
||||
// if (out instanceof ByteArrayOutputStream) {
|
||||
// if (useAsciiArmour) {
|
||||
// String output = new String(outStream.toByteArray());
|
||||
// if (generateSignature) {
|
||||
// resultData.putString(RESULT_SIGNATURE_TEXT, output);
|
||||
// } else {
|
||||
// resultData.putString(RESULT_ENCRYPTED_MESSAGE, output);
|
||||
// }
|
||||
// } else {
|
||||
// byte output[] = outStream.toByteArray();
|
||||
// if (generateSignature) {
|
||||
// resultData.putByteArray(RESULT_SIGNATURE_DATA, output);
|
||||
// } else {
|
||||
// resultData.putByteArray(RESULT_ENCRYPTED_DATA, output);
|
||||
// }
|
||||
// }
|
||||
// } else if (out instanceof FileOutputStream) {
|
||||
// String fileName = dataDestination.getStreamFilename();
|
||||
String uri = "content://" + DataProvider.AUTHORITY + "/data/" + streamFilename;
|
||||
resultData.putString(RESULT_URI, uri);
|
||||
// } else {
|
||||
// sendErrorToHandler(new Apg.GeneralException("No output-data found."));
|
||||
// }
|
||||
// }
|
||||
|
||||
sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData);
|
||||
} catch (Exception e) {
|
||||
sendErrorToHandler(e);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -223,6 +512,10 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessageToHandler(Integer arg1, Bundle data) {
|
||||
sendMessageToHandler(arg1, null, data);
|
||||
}
|
||||
|
||||
private void sendMessageToHandler(Integer arg1) {
|
||||
sendMessageToHandler(arg1, null, null);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.thialfihar.android.apg.R;
|
||||
import org.thialfihar.android.apg.service.IApgService2.Stub;
|
||||
import org.thialfihar.android.apg.Id.database;
|
||||
import org.thialfihar.android.apg.R.string;
|
||||
import org.thialfihar.android.apg.passphrase.PassphraseCacheService;
|
||||
import org.thialfihar.android.apg.provider.KeyRings;
|
||||
import org.thialfihar.android.apg.provider.Keys;
|
||||
import org.thialfihar.android.apg.provider.UserIds;
|
||||
@@ -50,9 +51,8 @@ import android.util.Log;
|
||||
/**
|
||||
* ATTENTION:
|
||||
*
|
||||
* This is the old ApgService used as remote service over aidl interface.
|
||||
* It will be reworked!
|
||||
*
|
||||
* This is the old ApgService used as remote service over aidl interface. It will be reworked!
|
||||
*
|
||||
*/
|
||||
public class ApgService2 extends PassphraseCacheService {
|
||||
private final static String TAG = "ApgService";
|
||||
|
||||
@@ -22,13 +22,13 @@ import java.io.IOException;
|
||||
|
||||
import org.thialfihar.android.apg.R;
|
||||
import org.thialfihar.android.apg.Apg;
|
||||
import org.thialfihar.android.apg.AskForSecretKeyPassPhrase;
|
||||
import org.thialfihar.android.apg.Constants;
|
||||
import org.thialfihar.android.apg.Id;
|
||||
import org.thialfihar.android.apg.PausableThread;
|
||||
import org.thialfihar.android.apg.Preferences;
|
||||
import org.thialfihar.android.apg.ProgressDialogUpdater;
|
||||
import org.thialfihar.android.apg.service.PassphraseCacheService;
|
||||
import org.thialfihar.android.apg.passphrase.AskForPassphrase;
|
||||
import org.thialfihar.android.apg.passphrase.PassphraseCacheService;
|
||||
|
||||
import com.actionbarsherlock.app.ActionBar;
|
||||
import com.actionbarsherlock.app.SherlockActivity;
|
||||
@@ -50,7 +50,7 @@ import android.support.v4.app.Fragment;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class BaseActivity extends SherlockFragmentActivity implements Runnable,
|
||||
ProgressDialogUpdater, AskForSecretKeyPassPhrase.PassPhraseCallbackInterface {
|
||||
ProgressDialogUpdater, AskForPassphrase.PassPhraseCallbackInterface {
|
||||
|
||||
private ProgressDialog mProgressDialog = null;
|
||||
private PausableThread mRunningThread = null;
|
||||
@@ -76,6 +76,7 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable,
|
||||
actionBar.setDisplayShowTitleEnabled(true);
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// not needed later:
|
||||
mPreferences = Preferences.getPreferences(this);
|
||||
|
||||
Apg.initialize(this);
|
||||
@@ -88,14 +89,14 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable,
|
||||
}
|
||||
}
|
||||
|
||||
startCacheService(this, mPreferences);
|
||||
// startCacheService(this, mPreferences);
|
||||
}
|
||||
|
||||
public static void startCacheService(Activity activity, Preferences preferences) {
|
||||
Intent intent = new Intent(activity, PassphraseCacheService.class);
|
||||
intent.putExtra(PassphraseCacheService.EXTRA_TTL, preferences.getPassPhraseCacheTtl());
|
||||
activity.startService(intent);
|
||||
}
|
||||
// public static void startCacheService(Activity activity, Preferences preferences) {
|
||||
// Intent intent = new Intent(activity, PassphraseCacheService.class);
|
||||
// intent.putExtra(PassphraseCacheService.EXTRA_TTL, preferences.getPassPhraseCacheTtl());
|
||||
// activity.startService(intent);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
@@ -177,7 +178,7 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable,
|
||||
switch (id) {
|
||||
|
||||
case Id.dialog.pass_phrase: {
|
||||
return AskForSecretKeyPassPhrase.createDialog(this, getSecretKeyId(), this);
|
||||
return AskForPassphrase.createDialog(this, getSecretKeyId(), this);
|
||||
}
|
||||
|
||||
case Id.dialog.pass_phrases_do_not_match: {
|
||||
@@ -373,6 +374,7 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable,
|
||||
}
|
||||
|
||||
public void passPhraseCallback(long keyId, String passPhrase) {
|
||||
// TODO: Not needed anymore, now implemented in AskForSecretKeyPass
|
||||
Apg.setCachedPassPhrase(keyId, passPhrase);
|
||||
}
|
||||
|
||||
|
||||
@@ -207,10 +207,10 @@ public class EditKeyActivity extends SherlockFragmentActivity {
|
||||
Bundle data = message.getData();
|
||||
PGPSecretKeyRing masterKeyRing = Utils
|
||||
.BytesToPGPSecretKeyRing(data
|
||||
.getByteArray(ApgHandler.RESULT_NEW_KEY));
|
||||
.getByteArray(ApgService.RESULT_NEW_KEY));
|
||||
PGPSecretKeyRing subKeyRing = Utils
|
||||
.BytesToPGPSecretKeyRing(data
|
||||
.getByteArray(ApgHandler.RESULT_NEW_KEY2));
|
||||
.getByteArray(ApgService.RESULT_NEW_KEY2));
|
||||
|
||||
// add master key
|
||||
Iterator<PGPSecretKey> masterIt = masterKeyRing.getSecretKeys();
|
||||
@@ -419,14 +419,10 @@ public class EditKeyActivity extends SherlockFragmentActivity {
|
||||
Bundle data = new Bundle();
|
||||
data.putString(ApgService.CURRENT_PASSPHRASE, mCurrentPassPhrase);
|
||||
data.putString(ApgService.NEW_PASSPHRASE, mNewPassPhrase);
|
||||
|
||||
data.putSerializable(ApgService.USER_IDS, getUserIds(mUserIdsView));
|
||||
|
||||
Vector<PGPSecretKey> keys = getKeys(mKeysView);
|
||||
data.putByteArray(ApgService.KEYS, Utils.PGPSecretKeyListToBytes(keys));
|
||||
|
||||
data.putSerializable(ApgService.KEYS_USAGES, getKeysUsages(mKeysView));
|
||||
|
||||
data.putLong(ApgService.MASTER_KEY_ID, getMasterKeyId());
|
||||
|
||||
intent.putExtra(ApgService.EXTRA_DATA, data);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.thialfihar.android.apg.ui;
|
||||
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPPublicKey;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
@@ -27,22 +26,28 @@ import org.thialfihar.android.apg.DataDestination;
|
||||
import org.thialfihar.android.apg.DataSource;
|
||||
import org.thialfihar.android.apg.FileDialog;
|
||||
import org.thialfihar.android.apg.Id;
|
||||
import org.thialfihar.android.apg.InputData;
|
||||
import org.thialfihar.android.apg.provider.DataProvider;
|
||||
import org.thialfihar.android.apg.Preferences;
|
||||
import org.thialfihar.android.apg.passphrase.AskForPassphrase;
|
||||
import org.thialfihar.android.apg.service.ApgHandler;
|
||||
import org.thialfihar.android.apg.service.ApgService;
|
||||
import org.thialfihar.android.apg.util.Choice;
|
||||
import org.thialfihar.android.apg.util.Compatibility;
|
||||
import org.thialfihar.android.apg.R;
|
||||
|
||||
import com.actionbarsherlock.app.ActionBar;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.animation.AnimationUtils;
|
||||
@@ -57,17 +62,11 @@ import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ViewFlipper;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.Vector;
|
||||
|
||||
public class EncryptActivity extends BaseActivity {
|
||||
public class EncryptActivity extends SherlockFragmentActivity implements
|
||||
AskForPassphrase.PassPhraseCallbackInterface {
|
||||
private Intent mIntent = null;
|
||||
private String mSubject = null;
|
||||
private String mSendTo = null;
|
||||
@@ -121,6 +120,10 @@ public class EncryptActivity extends BaseActivity {
|
||||
|
||||
private boolean mGenerateSignature = false;
|
||||
|
||||
private long mSecretKeyId = 0;
|
||||
|
||||
private ProgressDialogFragment mEncryptingDialog;
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
|
||||
@@ -266,7 +269,7 @@ public class EncryptActivity extends BaseActivity {
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
mFileCompression.setAdapter(adapter);
|
||||
|
||||
int defaultFileCompression = mPreferences.getDefaultFileCompression();
|
||||
int defaultFileCompression = Preferences.getPreferences(this).getDefaultFileCompression();
|
||||
for (int i = 0; i < choices.length; ++i) {
|
||||
if (choices[i].getId() == defaultFileCompression) {
|
||||
mFileCompression.setSelection(i);
|
||||
@@ -277,7 +280,7 @@ public class EncryptActivity extends BaseActivity {
|
||||
mDeleteAfter = (CheckBox) findViewById(R.id.deleteAfterEncryption);
|
||||
|
||||
mAsciiArmour = (CheckBox) findViewById(R.id.asciiArmour);
|
||||
mAsciiArmour.setChecked(mPreferences.getDefaultAsciiArmour());
|
||||
mAsciiArmour.setChecked(Preferences.getPreferences(this).getDefaultAsciiArmour());
|
||||
mAsciiArmour.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
guessOutputFilename();
|
||||
@@ -657,7 +660,7 @@ public class EncryptActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
public void passPhraseCallback(long keyId, String passPhrase) {
|
||||
super.passPhraseCallback(keyId, passPhrase);
|
||||
// super.passPhraseCallback(keyId, passPhrase);
|
||||
if (mEncryptTarget == Id.target.file) {
|
||||
askForOutputFilename();
|
||||
} else {
|
||||
@@ -667,122 +670,151 @@ public class EncryptActivity extends BaseActivity {
|
||||
|
||||
private void encryptStart() {
|
||||
showDialog(Id.dialog.encrypting);
|
||||
startThread();
|
||||
// startThread();
|
||||
|
||||
boolean useAsciiArmour = true;
|
||||
long encryptionKeyIds[] = null;
|
||||
long signatureKeyId = 0;
|
||||
int compressionId = 0;
|
||||
boolean signOnly = false;
|
||||
|
||||
String passPhrase = null;
|
||||
if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
|
||||
passPhrase = mPassPhrase.getText().toString();
|
||||
if (passPhrase.length() == 0) {
|
||||
passPhrase = null;
|
||||
}
|
||||
} else {
|
||||
encryptionKeyIds = mEncryptionKeyIds;
|
||||
signatureKeyId = getSecretKeyId();
|
||||
signOnly = (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0);
|
||||
}
|
||||
|
||||
fillDataSource(signOnly && !mReturnResult);
|
||||
fillDataDestination();
|
||||
|
||||
// Send all information needed to service to edit key in other thread
|
||||
Intent intent = new Intent(this, ApgService.class);
|
||||
|
||||
// fill values for this action
|
||||
Bundle data = new Bundle();
|
||||
|
||||
// choose default settings, action and data bundle by target
|
||||
if (mEncryptTarget == Id.target.file) {
|
||||
useAsciiArmour = mAsciiArmour.isChecked();
|
||||
compressionId = ((Choice) mFileCompression.getSelectedItem()).getId();
|
||||
|
||||
intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_ENCRYPT_SIGN_FILE);
|
||||
|
||||
data.putString(ApgService.FILE_URI, mDataSource.getUri().toString());
|
||||
|
||||
} else {
|
||||
useAsciiArmour = true;
|
||||
compressionId = Preferences.getPreferences(this).getDefaultMessageCompression();
|
||||
|
||||
intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_ENCRYPT_SIGN_BYTES);
|
||||
|
||||
data.putByteArray(ApgService.BYTES, mDataSource.getBytes());
|
||||
}
|
||||
|
||||
if (mOverrideAsciiArmour) {
|
||||
useAsciiArmour = mAsciiArmourDemand;
|
||||
}
|
||||
|
||||
data.putLong(ApgService.SECRET_KEY_ID, getSecretKeyId());
|
||||
data.putBoolean(ApgService.USE_ASCII_AMOR, useAsciiArmour);
|
||||
data.putLongArray(ApgService.ENCRYPTION_KEYS_IDS, encryptionKeyIds);
|
||||
data.putLong(ApgService.SIGNATURE_KEY_ID, signatureKeyId);
|
||||
data.putInt(ApgService.COMPRESSION_ID, compressionId);
|
||||
data.putBoolean(ApgService.GENERATE_SIGNATURE, mGenerateSignature);
|
||||
data.putBoolean(ApgService.SIGN_ONLY, signOnly);
|
||||
|
||||
intent.putExtra(ApgService.EXTRA_DATA, data);
|
||||
|
||||
// show progress dialog
|
||||
mEncryptingDialog = ProgressDialogFragment.newInstance(R.string.progress_encrypting,
|
||||
ProgressDialog.STYLE_HORIZONTAL);
|
||||
|
||||
// Message is received after saving is done in ApgService
|
||||
ApgHandler saveHandler = new ApgHandler(this, mEncryptingDialog) {
|
||||
public void handleMessage(Message message) {
|
||||
// handle messages by standard ApgHandler first
|
||||
super.handleMessage(message);
|
||||
|
||||
if (message.arg1 == ApgHandler.MESSAGE_OKAY) {
|
||||
// get returned data bundle
|
||||
Bundle data = message.getData();
|
||||
|
||||
String output;
|
||||
switch (mEncryptTarget) {
|
||||
case Id.target.clipboard:
|
||||
output = data.getString(ApgService.RESULT_ENCRYPTED_MESSAGE);
|
||||
Log.d(Constants.TAG, "output: " + output);
|
||||
Compatibility.copyToClipboard(EncryptActivity.this, output);
|
||||
Toast.makeText(EncryptActivity.this,
|
||||
R.string.encryptionToClipboardSuccessful, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
break;
|
||||
|
||||
case Id.target.email:
|
||||
if (mReturnResult) {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtras(data);
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
output = data.getString(ApgService.RESULT_ENCRYPTED_MESSAGE);
|
||||
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
|
||||
emailIntent.setType("text/plain; charset=utf-8");
|
||||
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
|
||||
if (mSubject != null) {
|
||||
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, mSubject);
|
||||
}
|
||||
if (mSendTo != null) {
|
||||
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
|
||||
new String[] { mSendTo });
|
||||
}
|
||||
EncryptActivity.this.startActivity(Intent.createChooser(emailIntent,
|
||||
getString(R.string.title_sendEmail)));
|
||||
break;
|
||||
|
||||
case Id.target.file:
|
||||
Toast.makeText(EncryptActivity.this, R.string.encryptionSuccessful,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
if (mDeleteAfter.isChecked()) {
|
||||
// TODO: Reimplement that!
|
||||
// setDeleteFile(mInputFilename);
|
||||
// showDialog(Id.dialog.delete_file);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// shouldn't happen
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Create a new Messenger for the communication back
|
||||
Messenger messenger = new Messenger(saveHandler);
|
||||
intent.putExtra(ApgService.EXTRA_MESSENGER, messenger);
|
||||
|
||||
mEncryptingDialog.show(getSupportFragmentManager(), "dialog");
|
||||
|
||||
// start service with intent
|
||||
startService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
String error = null;
|
||||
Bundle data = new Bundle();
|
||||
Message msg = new Message();
|
||||
public void setSecretKeyId(long id) {
|
||||
mSecretKeyId = id;
|
||||
}
|
||||
|
||||
try {
|
||||
InputData in;
|
||||
OutputStream out;
|
||||
boolean useAsciiArmour = true;
|
||||
long encryptionKeyIds[] = null;
|
||||
long signatureKeyId = 0;
|
||||
int compressionId = 0;
|
||||
boolean signOnly = false;
|
||||
|
||||
String passPhrase = null;
|
||||
if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
|
||||
passPhrase = mPassPhrase.getText().toString();
|
||||
if (passPhrase.length() == 0) {
|
||||
passPhrase = null;
|
||||
}
|
||||
} else {
|
||||
encryptionKeyIds = mEncryptionKeyIds;
|
||||
signatureKeyId = getSecretKeyId();
|
||||
signOnly = (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0);
|
||||
}
|
||||
|
||||
fillDataSource(signOnly && !mReturnResult);
|
||||
fillDataDestination();
|
||||
|
||||
// streams
|
||||
in = mDataSource.getInputData(this, true);
|
||||
out = mDataDestination.getOutputStream(this);
|
||||
|
||||
if (mEncryptTarget == Id.target.file) {
|
||||
useAsciiArmour = mAsciiArmour.isChecked();
|
||||
compressionId = ((Choice) mFileCompression.getSelectedItem()).getId();
|
||||
} else {
|
||||
useAsciiArmour = true;
|
||||
compressionId = mPreferences.getDefaultMessageCompression();
|
||||
}
|
||||
|
||||
if (mOverrideAsciiArmour) {
|
||||
useAsciiArmour = mAsciiArmourDemand;
|
||||
}
|
||||
|
||||
if (mGenerateSignature) {
|
||||
Apg.generateSignature(this, in, out, useAsciiArmour, mDataSource.isBinary(),
|
||||
getSecretKeyId(), Apg.getCachedPassPhrase(getSecretKeyId()),
|
||||
mPreferences.getDefaultHashAlgorithm(),
|
||||
mPreferences.getForceV3Signatures(), this);
|
||||
} else if (signOnly) {
|
||||
Apg.signText(this, in, out, getSecretKeyId(),
|
||||
Apg.getCachedPassPhrase(getSecretKeyId()),
|
||||
mPreferences.getDefaultHashAlgorithm(),
|
||||
mPreferences.getForceV3Signatures(), this);
|
||||
} else {
|
||||
Apg.encrypt(this, in, out, useAsciiArmour, encryptionKeyIds, signatureKeyId,
|
||||
Apg.getCachedPassPhrase(signatureKeyId), this,
|
||||
mPreferences.getDefaultEncryptionAlgorithm(),
|
||||
mPreferences.getDefaultHashAlgorithm(), compressionId,
|
||||
mPreferences.getForceV3Signatures(), passPhrase);
|
||||
}
|
||||
|
||||
out.close();
|
||||
if (mEncryptTarget != Id.target.file) {
|
||||
|
||||
if (out instanceof ByteArrayOutputStream) {
|
||||
if (useAsciiArmour) {
|
||||
String extraData = new String(((ByteArrayOutputStream) out).toByteArray());
|
||||
if (mGenerateSignature) {
|
||||
data.putString(Apg.EXTRA_SIGNATURE_TEXT, extraData);
|
||||
} else {
|
||||
data.putString(Apg.EXTRA_ENCRYPTED_MESSAGE, extraData);
|
||||
}
|
||||
} else {
|
||||
byte extraData[] = ((ByteArrayOutputStream) out).toByteArray();
|
||||
if (mGenerateSignature) {
|
||||
data.putByteArray(Apg.EXTRA_SIGNATURE_DATA, extraData);
|
||||
} else {
|
||||
data.putByteArray(Apg.EXTRA_ENCRYPTED_DATA, extraData);
|
||||
}
|
||||
}
|
||||
} else if (out instanceof FileOutputStream) {
|
||||
String fileName = mDataDestination.getStreamFilename();
|
||||
String uri = "content://" + DataProvider.AUTHORITY + "/data/" + fileName;
|
||||
data.putString(Apg.EXTRA_RESULT_URI, uri);
|
||||
} else {
|
||||
throw new Apg.GeneralException("No output-data found.");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
error = "" + e;
|
||||
} catch (PGPException e) {
|
||||
error = "" + e;
|
||||
} catch (NoSuchProviderException e) {
|
||||
error = "" + e;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
error = "" + e;
|
||||
} catch (SignatureException e) {
|
||||
error = "" + e;
|
||||
} catch (Apg.GeneralException e) {
|
||||
error = "" + e;
|
||||
}
|
||||
|
||||
data.putInt(Constants.extras.STATUS, Id.message.done);
|
||||
|
||||
if (error != null) {
|
||||
data.putString(Apg.EXTRA_ERROR, error);
|
||||
}
|
||||
|
||||
msg.setData(data);
|
||||
sendMessage(msg);
|
||||
public long getSecretKeyId() {
|
||||
return mSecretKeyId;
|
||||
}
|
||||
|
||||
private void updateView() {
|
||||
@@ -911,68 +943,6 @@ public class EncryptActivity extends BaseActivity {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doneCallback(Message msg) {
|
||||
super.doneCallback(msg);
|
||||
|
||||
removeDialog(Id.dialog.encrypting);
|
||||
|
||||
Bundle data = msg.getData();
|
||||
String error = data.getString(Apg.EXTRA_ERROR);
|
||||
if (error != null) {
|
||||
Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
switch (mEncryptTarget) {
|
||||
case Id.target.clipboard: {
|
||||
String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE);
|
||||
Compatibility.copyToClipboard(this, message);
|
||||
Toast.makeText(this, R.string.encryptionToClipboardSuccessful, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
break;
|
||||
}
|
||||
|
||||
case Id.target.email: {
|
||||
if (mReturnResult) {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtras(data);
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
String message = data.getString(Apg.EXTRA_ENCRYPTED_MESSAGE);
|
||||
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
|
||||
emailIntent.setType("text/plain; charset=utf-8");
|
||||
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
|
||||
if (mSubject != null) {
|
||||
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, mSubject);
|
||||
}
|
||||
if (mSendTo != null) {
|
||||
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { mSendTo });
|
||||
}
|
||||
EncryptActivity.this.startActivity(Intent.createChooser(emailIntent,
|
||||
getString(R.string.title_sendEmail)));
|
||||
break;
|
||||
}
|
||||
|
||||
case Id.target.file: {
|
||||
Toast.makeText(this, R.string.encryptionSuccessful, Toast.LENGTH_SHORT).show();
|
||||
if (mDeleteAfter.isChecked()) {
|
||||
setDeleteFile(mInputFilename);
|
||||
showDialog(Id.dialog.delete_file);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// shouldn't happen
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id) {
|
||||
switch (id) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.thialfihar.android.apg.Apg;
|
||||
import org.thialfihar.android.apg.Constants;
|
||||
import org.thialfihar.android.apg.Id;
|
||||
import org.thialfihar.android.apg.Preferences;
|
||||
import org.thialfihar.android.apg.passphrase.PassphraseCacheService;
|
||||
import org.thialfihar.android.apg.ui.widget.IntegerListPreference;
|
||||
import org.thialfihar.android.apg.R;
|
||||
|
||||
@@ -67,7 +68,9 @@ public class PreferencesActivity extends SherlockPreferenceActivity {
|
||||
mPassPhraseCacheTtl.setValue(newValue.toString());
|
||||
mPassPhraseCacheTtl.setSummary(mPassPhraseCacheTtl.getEntry());
|
||||
mPreferences.setPassPhraseCacheTtl(Integer.parseInt(newValue.toString()));
|
||||
BaseActivity.startCacheService(PreferencesActivity.this, mPreferences);
|
||||
|
||||
// restart cache service with new ttl
|
||||
PassphraseCacheService.startCacheService(PreferencesActivity.this);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -18,9 +18,9 @@ package org.thialfihar.android.apg.ui;
|
||||
|
||||
import org.thialfihar.android.apg.R;
|
||||
import org.thialfihar.android.apg.Apg;
|
||||
import org.thialfihar.android.apg.AskForSecretKeyPassPhrase;
|
||||
import org.thialfihar.android.apg.Constants;
|
||||
import org.thialfihar.android.apg.Id;
|
||||
import org.thialfihar.android.apg.passphrase.AskForPassphrase;
|
||||
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
@@ -135,7 +135,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
|
||||
case Id.dialog.pass_phrase: {
|
||||
long keyId = ((KeyListAdapter) mList.getExpandableListAdapter())
|
||||
.getGroupId(mSelectedItem);
|
||||
return AskForSecretKeyPassPhrase.createDialog(this, keyId, this);
|
||||
return AskForPassphrase.createDialog(this, keyId, this);
|
||||
}
|
||||
|
||||
default: {
|
||||
|
||||
@@ -285,7 +285,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
// get new key from data bundle returned from service
|
||||
Bundle data = message.getData();
|
||||
PGPSecretKeyRing newKeyRing = Utils.BytesToPGPSecretKeyRing(data
|
||||
.getByteArray(ApgHandler.RESULT_NEW_KEY));
|
||||
.getByteArray(ApgService.RESULT_NEW_KEY));
|
||||
|
||||
boolean isMasterKey = (mEditors.getChildCount() == 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user