Work on encryption in new service

This commit is contained in:
Dominik Schürmann 2013-09-06 18:36:16 +02:00
parent 9e8ee3353a
commit d6dd81d444
5 changed files with 114 additions and 65 deletions

View File

@ -735,13 +735,14 @@ public class PgpMain {
*/ */
public static void encryptAndSign(Context context, ProgressDialogUpdater progress, public static void encryptAndSign(Context context, ProgressDialogUpdater progress,
InputData data, OutputStream outStream, boolean useAsciiArmor, int compression, InputData data, OutputStream outStream, boolean useAsciiArmor, int compression,
long encryptionKeyIds[], String encryptionPassphrase, int symmetricEncryptionAlgorithm, ArrayList<Long> encryptionKeyIds, String encryptionPassphrase,
long signatureKeyId, int signatureHashAlgorithm, boolean signatureForceV3, int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm,
String signaturePassphrase) throws IOException, PgpGeneralException, PGPException, boolean signatureForceV3, String signaturePassphrase) throws IOException,
NoSuchProviderException, NoSuchAlgorithmException, SignatureException { PgpGeneralException, PGPException, NoSuchProviderException, NoSuchAlgorithmException,
SignatureException {
if (encryptionKeyIds == null) { if (encryptionKeyIds == null) {
encryptionKeyIds = new long[0]; encryptionKeyIds = new ArrayList<Long>();
} }
ArmoredOutputStream armorOut = null; ArmoredOutputStream armorOut = null;
@ -758,7 +759,7 @@ public class PgpMain {
PGPSecretKeyRing signingKeyRing = null; PGPSecretKeyRing signingKeyRing = null;
PGPPrivateKey signaturePrivateKey = null; PGPPrivateKey signaturePrivateKey = null;
if (encryptionKeyIds.length == 0 && encryptionPassphrase == null) { if (encryptionKeyIds.size() == 0 && encryptionPassphrase == null) {
throw new PgpGeneralException( throw new PgpGeneralException(
context.getString(R.string.error_noEncryptionKeysOrPassPhrase)); context.getString(R.string.error_noEncryptionKeysOrPassPhrase));
} }
@ -794,7 +795,7 @@ public class PgpMain {
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(encryptorBuilder); PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(encryptorBuilder);
if (encryptionKeyIds.length == 0) { if (encryptionKeyIds.size() == 0) {
// Symmetric encryption // Symmetric encryption
Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption"); Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption");
@ -803,8 +804,8 @@ public class PgpMain {
cPk.addMethod(symmetricEncryptionGenerator); cPk.addMethod(symmetricEncryptionGenerator);
} else { } else {
// Asymmetric encryption // Asymmetric encryption
for (int i = 0; i < encryptionKeyIds.length; ++i) { for (long id : encryptionKeyIds) {
PGPPublicKey key = PgpHelper.getEncryptPublicKey(context, encryptionKeyIds[i]); PGPPublicKey key = PgpHelper.getEncryptPublicKey(context, id);
if (key != null) { if (key != null) {
JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator = new JcePublicKeyKeyEncryptionMethodGenerator( JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator = new JcePublicKeyKeyEncryptionMethodGenerator(

View File

@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
@ -46,6 +47,7 @@ import org.openintents.crypto.ICryptoService;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
@ -108,7 +110,7 @@ public class CryptoService extends Service {
} }
private synchronized void encryptSafe(byte[] inputBytes, String[] encryptionUserIds, private synchronized void encryptSafe(byte[] inputBytes, String[] encryptionUserIds,
AppSettings appSettings, ICryptoCallback callback) throws RemoteException { ICryptoCallback callback, AppSettings appSettings) throws RemoteException {
try { try {
// build InputData and write into OutputStream // build InputData and write into OutputStream
InputStream inputStream = new ByteArrayInputStream(inputBytes); InputStream inputStream = new ByteArrayInputStream(inputBytes);
@ -117,18 +119,34 @@ public class CryptoService extends Service {
OutputStream outputStream = new ByteArrayOutputStream(); OutputStream outputStream = new ByteArrayOutputStream();
String passphrase = getCachedPassphrase(appSettings.getKeyId()); // find key ids to given emails in database
boolean manySameUserIds = false;
boolean missingUserIds = false;
ArrayList<Long> keyIds = new ArrayList<Long>();
for (String email : encryptionUserIds) {
Uri uri = KeychainContract.KeyRings.buildPublicKeyRingsByEmailsUri(email);
Cursor cur = getContentResolver().query(uri, null, null, null, null);
if (cur.moveToFirst()) {
long id = cur.getLong(cur
.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID));
keyIds.add(id);
} else {
missingUserIds = true;
Log.d(Constants.TAG, "user id missing");
}
if (cur.moveToNext()) {
manySameUserIds = true;
Log.d(Constants.TAG, "more than one user id with the same email");
}
}
// also encrypt to our self (so that we can decrypt it later!)
keyIds.add(appSettings.getKeyId());
PgpMain.encryptAndSign(mContext, null, inputData, outputStream, PgpMain.encryptAndSign(mContext, null, inputData, outputStream,
appSettings.isAsciiArmor(), appSettings.getCompression(), new long[] {}, appSettings.isAsciiArmor(), appSettings.getCompression(), keyIds, null,
"test", appSettings.getEncryptionAlgorithm(), Id.key.none, appSettings.getEncryptionAlgorithm(), Id.key.none,
appSettings.getHashAlgorithm(), true, passphrase); appSettings.getHashAlgorithm(), true, null);
// PgpMain.encryptAndSign(this, this, inputData, outputStream,
// appSettings.isAsciiArmor(),
// appSettings.getCompression(), encryptionKeyIds, encryptionPassphrase,
// appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(),
// appSettings.getHashAlgorithm(), true, passphrase);
outputStream.close(); outputStream.close();
@ -147,8 +165,22 @@ public class CryptoService extends Service {
} }
} }
private synchronized void decryptAndVerifySafe(byte[] inputBytes, ICryptoCallback callback) private synchronized void encryptAndSignSafe(byte[] inputBytes, String[] encryptionUserIds,
String signatureUserId, ICryptoCallback callback, AppSettings appSettings)
throws RemoteException { throws RemoteException {
String passphrase = getCachedPassphrase(appSettings.getKeyId());
// PgpMain.encryptAndSign(this, this, inputData, outputStream,
// appSettings.isAsciiArmor(),
// appSettings.getCompression(), encryptionKeyIds, encryptionPassphrase,
// appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(),
// appSettings.getHashAlgorithm(), true, passphrase);
}
private synchronized void decryptAndVerifySafe(byte[] inputBytes, ICryptoCallback callback,
AppSettings appSettings) throws RemoteException {
try { try {
// build InputData and write into OutputStream // build InputData and write into OutputStream
InputStream inputStream = new ByteArrayInputStream(inputBytes); InputStream inputStream = new ByteArrayInputStream(inputBytes);
@ -226,7 +258,7 @@ public class CryptoService extends Service {
@Override @Override
public void run() { public void run() {
try { try {
encryptSafe(inputBytes, encryptionUserIds, settings, callback); encryptSafe(inputBytes, encryptionUserIds, callback, settings);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(Constants.TAG, "CryptoService", e); Log.e(Constants.TAG, "CryptoService", e);
} }
@ -237,9 +269,26 @@ public class CryptoService extends Service {
} }
@Override @Override
public void encryptAndSign(byte[] inputBytes, String[] encryptionUserIds, public void encryptAndSign(final byte[] inputBytes, final String[] encryptionUserIds,
String signatureUserId, ICryptoCallback callback) throws RemoteException { final String signatureUserId, final ICryptoCallback callback)
// TODO Auto-generated method stub throws RemoteException {
final AppSettings settings = getAppSettings();
Runnable r = new Runnable() {
@Override
public void run() {
try {
encryptAndSignSafe(inputBytes, encryptionUserIds, signatureUserId,
callback, settings);
} catch (RemoteException e) {
Log.e(Constants.TAG, "CryptoService", e);
}
}
};
checkAndEnqueue(r);
} }
@ -254,12 +303,14 @@ public class CryptoService extends Service {
public void decryptAndVerify(final byte[] inputBytes, final ICryptoCallback callback) public void decryptAndVerify(final byte[] inputBytes, final ICryptoCallback callback)
throws RemoteException { throws RemoteException {
final AppSettings settings = getAppSettings();
Runnable r = new Runnable() { Runnable r = new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
decryptAndVerifySafe(inputBytes, callback); decryptAndVerifySafe(inputBytes, callback, settings);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(Constants.TAG, "CryptoService", e); Log.e(Constants.TAG, "CryptoService", e);
} }

View File

@ -103,12 +103,12 @@ public class KeychainApiService extends Service {
InputData input = new InputData(inputStream, inputLength); InputData input = new InputData(inputStream, inputLength);
OutputStream output = new ByteArrayOutputStream(); OutputStream output = new ByteArrayOutputStream();
//
PgpMain.encryptAndSign(mContext, null, input, output, useAsciiArmor, compression, // PgpMain.encryptAndSign(mContext, null, input, output, useAsciiArmor, compression,
encryptionKeyIds, encryptionPassphrase, symmetricEncryptionAlgorithm, // encryptionKeyIds, encryptionPassphrase, symmetricEncryptionAlgorithm,
signatureKeyId, signatureHashAlgorithm, signatureForceV3, signaturePassphrase); // signatureKeyId, signatureHashAlgorithm, signatureForceV3, signaturePassphrase);
//
output.close(); // output.close();
// if (isBlob) { // if (isBlob) {
// ContentResolver cr = getContentResolver(); // ContentResolver cr = getContentResolver();

View File

@ -27,6 +27,8 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKey;
@ -75,9 +77,11 @@ public class KeychainIntentService extends IntentService implements ProgressDial
public static final String ACTION_SAVE_KEYRING = Constants.INTENT_PREFIX + "SAVE_KEYRING"; public static final String ACTION_SAVE_KEYRING = Constants.INTENT_PREFIX + "SAVE_KEYRING";
public static final String ACTION_GENERATE_KEY = Constants.INTENT_PREFIX + "GENERATE_KEY"; public static final String ACTION_GENERATE_KEY = Constants.INTENT_PREFIX + "GENERATE_KEY";
public static final String ACTION_GENERATE_DEFAULT_RSA_KEYS = Constants.INTENT_PREFIX + "GENERATE_DEFAULT_RSA_KEYS"; public static final String ACTION_GENERATE_DEFAULT_RSA_KEYS = Constants.INTENT_PREFIX
+ "GENERATE_DEFAULT_RSA_KEYS";
public static final String ACTION_DELETE_FILE_SECURELY = Constants.INTENT_PREFIX + "DELETE_FILE_SECURELY"; public static final String ACTION_DELETE_FILE_SECURELY = Constants.INTENT_PREFIX
+ "DELETE_FILE_SECURELY";
public static final String ACTION_IMPORT_KEYRING = Constants.INTENT_PREFIX + "IMPORT_KEYRING"; public static final String ACTION_IMPORT_KEYRING = Constants.INTENT_PREFIX + "IMPORT_KEYRING";
public static final String ACTION_EXPORT_KEYRING = Constants.INTENT_PREFIX + "EXPORT_KEYRING"; public static final String ACTION_EXPORT_KEYRING = Constants.INTENT_PREFIX + "EXPORT_KEYRING";
@ -216,8 +220,8 @@ public class KeychainIntentService extends IntentService implements ProgressDial
return; return;
} }
if (!(extras.containsKey(EXTRA_MESSENGER) || extras.containsKey(EXTRA_DATA) || if (!(extras.containsKey(EXTRA_MESSENGER) || extras.containsKey(EXTRA_DATA) || (intent
(intent.getAction() == null))) { .getAction() == null))) {
Log.e(Constants.TAG, Log.e(Constants.TAG,
"Extra bundle must contain a messenger, a data bundle, and an action!"); "Extra bundle must contain a messenger, a data bundle, and an action!");
return; return;
@ -229,9 +233,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial
OtherHelper.logDebugBundle(data, "EXTRA_DATA"); OtherHelper.logDebugBundle(data, "EXTRA_DATA");
String action = intent.getAction(); String action = intent.getAction();
// execute action from extra bundle // execute action from extra bundle
if( ACTION_ENCRYPT_SIGN.equals(action)) { if (ACTION_ENCRYPT_SIGN.equals(action)) {
try { try {
/* Input */ /* Input */
int target = data.getInt(TARGET); int target = data.getInt(TARGET);
@ -312,6 +316,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} }
/* Operation */ /* Operation */
// convert to arraylist
ArrayList<Long> keyIdsList = new ArrayList<Long>(encryptionKeyIds.length);
for (long n : encryptionKeyIds)
keyIdsList.add(n);
if (generateSignature) { if (generateSignature) {
Log.d(Constants.TAG, "generating signature..."); Log.d(Constants.TAG, "generating signature...");
@ -329,7 +337,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} else { } else {
Log.d(Constants.TAG, "encrypt..."); Log.d(Constants.TAG, "encrypt...");
PgpMain.encryptAndSign(this, this, inputData, outStream, useAsciiArmor, PgpMain.encryptAndSign(this, this, inputData, outStream, useAsciiArmor,
compressionId, encryptionKeyIds, encryptionPassphrase, Preferences compressionId, keyIdsList, encryptionPassphrase, Preferences
.getPreferences(this).getDefaultEncryptionAlgorithm(), .getPreferences(this).getDefaultEncryptionAlgorithm(),
secretKeyId, secretKeyId,
Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences
@ -380,8 +388,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_DECRYPT_VERIFY.equals(action)) {
else if(ACTION_DECRYPT_VERIFY.equals(action)) {
try { try {
/* Input */ /* Input */
int target = data.getInt(TARGET); int target = data.getInt(TARGET);
@ -510,8 +517,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_SAVE_KEYRING.equals(action)) {
else if(ACTION_SAVE_KEYRING.equals(action)) {
try { try {
/* Input */ /* Input */
String oldPassPhrase = data.getString(SAVE_KEYRING_CURRENT_PASSPHRASE); String oldPassPhrase = data.getString(SAVE_KEYRING_CURRENT_PASSPHRASE);
@ -547,8 +553,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_GENERATE_KEY.equals(action)) {
else if(ACTION_GENERATE_KEY.equals(action)) {
try { try {
/* Input */ /* Input */
int algorithm = data.getInt(GENERATE_KEY_ALGORITHM); int algorithm = data.getInt(GENERATE_KEY_ALGORITHM);
@ -575,8 +580,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_GENERATE_DEFAULT_RSA_KEYS.equals(action)) {
else if(ACTION_GENERATE_DEFAULT_RSA_KEYS.equals(action)) {
// generate one RSA 2048 key for signing and one subkey for encrypting! // generate one RSA 2048 key for signing and one subkey for encrypting!
try { try {
/* Input */ /* Input */
@ -602,8 +606,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_DELETE_FILE_SECURELY.equals(action)) {
else if(ACTION_DELETE_FILE_SECURELY.equals(action)) {
try { try {
/* Input */ /* Input */
String deleteFile = data.getString(DELETE_FILE); String deleteFile = data.getString(DELETE_FILE);
@ -624,8 +627,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_IMPORT_KEYRING.equals(action)) {
else if(ACTION_IMPORT_KEYRING.equals(action)) {
try { try {
/* Input */ /* Input */
@ -672,8 +674,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_EXPORT_KEYRING.equals(action)) {
else if(ACTION_EXPORT_KEYRING.equals(action)) {
try { try {
/* Input */ /* Input */
@ -721,8 +722,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_UPLOAD_KEYRING.equals(action)) {
else if(ACTION_UPLOAD_KEYRING.equals(action)) {
try { try {
/* Input */ /* Input */
@ -746,8 +746,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_QUERY_KEYRING.equals(action)) {
else if(ACTION_QUERY_KEYRING.equals(action)) {
try { try {
/* Input */ /* Input */
@ -775,8 +774,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }
} } else if (ACTION_SIGN_KEYRING.equals(action)) {
else if(ACTION_SIGN_KEYRING.equals(action)) {
try { try {
/* Input */ /* Input */

View File

@ -39,11 +39,10 @@ import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.util.Choice; import org.sufficientlysecure.keychain.util.Choice;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.MenuItem;
import android.annotation.SuppressLint;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
@ -64,7 +63,6 @@ import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.widget.ViewFlipper; import android.widget.ViewFlipper;
import java.io.File; import java.io.File;
import java.util.Vector; import java.util.Vector;
@ -437,6 +435,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
* @param encryptToClipboardEnabled * @param encryptToClipboardEnabled
* @param encryptToClipboardStringRes * @param encryptToClipboardStringRes
*/ */
@SuppressLint("NewApi")
private void setActionbarButtons(boolean encryptEnabled, int encryptStringRes, private void setActionbarButtons(boolean encryptEnabled, int encryptStringRes,
boolean encryptToClipboardEnabled, int encryptToClipboardStringRes) { boolean encryptToClipboardEnabled, int encryptToClipboardStringRes) {
mEncryptEnabled = encryptEnabled; mEncryptEnabled = encryptEnabled;
@ -779,10 +778,10 @@ public class EncryptActivity extends SherlockFragmentActivity {
Intent emailIntent = new Intent(Intent.ACTION_SEND); Intent emailIntent = new Intent(Intent.ACTION_SEND);
//Type is set to text/plain so that encrypted messages can // Type is set to text/plain so that encrypted messages can
//be sent with Whatsapp, Hangouts, SMS etc... // be sent with Whatsapp, Hangouts, SMS etc...
emailIntent.setType("text/plain"); emailIntent.setType("text/plain");
emailIntent.putExtra(Intent.EXTRA_TEXT, output); emailIntent.putExtra(Intent.EXTRA_TEXT, output);
if (mSubject != null) { if (mSubject != null) {
emailIntent.putExtra(Intent.EXTRA_SUBJECT, mSubject); emailIntent.putExtra(Intent.EXTRA_SUBJECT, mSubject);