mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-27 03:02:15 -05:00
working on externalizing encrypt methods into the service
This commit is contained in:
parent
7b61ad24d7
commit
5a51f79126
30
README.md
30
README.md
@ -2,20 +2,12 @@
|
||||
|
||||
This is a fork of Android Privacy Guard (APG) named APG+
|
||||
|
||||
I will try to reintegrate the various forks and build a new stable version, which can be released to the market.
|
||||
I will try to reintegrate the various forks and build a new stable version, which can be released to Google Play Store.
|
||||
|
||||
# Contribute
|
||||
|
||||
Fork APG+ and do a merge request. I will merge your changes back into the main project.
|
||||
|
||||
# Build using Eclipse
|
||||
|
||||
1. New -> Android Project -> Create project from existing source, choose com_actionbarsherlock
|
||||
2. New -> Android Project -> Create project from existing source, choose org_apg
|
||||
3. Add com_actionbarsherlock as Android Lib (Properties of org_apg -> Android -> Library -> add)
|
||||
4. Optional (As of Android Tools r17 the libraries are automatically added from the libs folder): Add Java libs (Properties of org_apg -> Java Build Path -> Libraries -> add all libraries from libs folder in org_apg)
|
||||
5. Now APG+ can be build
|
||||
|
||||
# Build using Ant
|
||||
|
||||
## Command Line
|
||||
@ -28,7 +20,15 @@ Fork APG+ and do a merge request. I will merge your changes back into the main p
|
||||
|
||||
sdk.dir=/opt/android-sdk
|
||||
|
||||
2. execute "ant release"
|
||||
2. execute "ant release"
|
||||
|
||||
# Build using Eclipse
|
||||
|
||||
1. New -> Android Project -> Create project from existing source, choose com_actionbarsherlock
|
||||
2. New -> Android Project -> Create project from existing source, choose org_apg
|
||||
3. Add com_actionbarsherlock as Android Lib (Properties of org_apg -> Android -> Library -> add)
|
||||
4. Optional (As of Android Tools r17 the libraries are automatically added from the libs folder): Add Java libs (Properties of org_apg -> Java Build Path -> Libraries -> add all libraries from libs folder in org_apg)
|
||||
5. Now APG+ can be build
|
||||
|
||||
# Libraries
|
||||
|
||||
@ -39,7 +39,7 @@ The Libraries are provided in the git repository.
|
||||
* android-support-v4.jar: Compatibility Lib
|
||||
* barcodescanner-android-integration-supportv4.jar: Barcode Scanner Integration
|
||||
|
||||
# Build XZing Integration Library
|
||||
## Build Barcode Scanner Integration
|
||||
|
||||
1. Checkout their SVN (see http://code.google.com/p/zxing/source/checkout)
|
||||
2. Change android-home variable in "build.properties" in the main directory to point to your Android SDK
|
||||
@ -49,11 +49,13 @@ The Libraries are provided in the git repository.
|
||||
|
||||
On error see: http://code.google.com/p/zxing/issues/detail?id=1207
|
||||
|
||||
# Build Spongy Castle
|
||||
## Build Spongy Castle
|
||||
|
||||
see https://github.com/rtyley/spongycastle
|
||||
|
||||
# Generate pressed dashboard icons
|
||||
# Notes
|
||||
|
||||
1. Open svg in Inkscape
|
||||
## Generate pressed dashboard icons
|
||||
|
||||
1. Open svg file in Inkscape
|
||||
2. Extensions -> Color -> darker (2 times!)
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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. -->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.thialfihar.android.apg"
|
||||
@ -32,7 +31,7 @@
|
||||
android:hardwareAccelerated="true"
|
||||
android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.Sherlock.Light.ForceOverflow" >
|
||||
android:theme="@style/Theme.Sherlock.Light.ForceOverflow" android:name="ApgApplication">
|
||||
<activity
|
||||
android:name=".ui.MainActivity"
|
||||
android:configChanges="keyboardHidden|orientation|keyboard"
|
||||
@ -220,10 +219,10 @@
|
||||
android:label="@string/title_about"
|
||||
android:theme="@style/Theme.Sherlock.Light.Dialog" />
|
||||
<activity
|
||||
android:name="org.thialfihar.android.apg.ui.HelpActivity"
|
||||
android:name=".ui.HelpActivity"
|
||||
android:label="@string/title_help" />
|
||||
|
||||
<service android:name=".service.PassphraseCacheService" />
|
||||
<service android:name=".service.password.PassphraseCacheService" />
|
||||
<service android:name=".service.ApgService" />
|
||||
|
||||
<!-- TODO: need to be moved into new service model -->
|
||||
@ -247,7 +246,7 @@
|
||||
android:authorities="org.thialfihar.android.apg.provider"
|
||||
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" />
|
||||
<provider
|
||||
android:name="org.thialfihar.android.apg.provider.ApgServiceBlobProvider"
|
||||
android:name=".provider.blob.ApgServiceBlobProvider"
|
||||
android:authorities="org.thialfihar.android.apg.provider.apgserviceblobprovider"
|
||||
android:permission="org.thialfihar.android.apg.permission.STORE_BLOBS" />
|
||||
</application>
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user