PendingIntent to handle user input

This commit is contained in:
Dominik Schürmann
2014-02-14 13:40:24 +01:00
parent ee2fec1759
commit acad2ba957
14 changed files with 450 additions and 355 deletions

View File

@@ -18,11 +18,14 @@ package org.sufficientlysecure.keychain.demo;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -54,6 +57,11 @@ public class OpenPgpProviderActivity extends Activity {
private OpenPgpServiceConnection mCryptoServiceConnection;
public static final int REQUEST_CODE_SIGN = 9910;
public static final int REQUEST_CODE_ENCRYPT = 9911;
public static final int REQUEST_CODE_SIGN_AND_ENC = 9912;
public static final int REQUEST_CODE_DECRYPT = 9913;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -210,30 +218,60 @@ public class OpenPgpProviderActivity extends Activity {
}
public void signOnClick(View view) {
InputStream is = null;
try {
String inputStr = mMessage.getText().toString();
InputStream is = new ByteArrayInputStream(inputStr.getBytes("UTF-8"));
is = new ByteArrayInputStream(inputStr.getBytes("UTF-8"));
final ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(mCryptoServiceConnection.getService());
api.sign(is, os);
Log.d(OpenPgpConstants.TAG, "Test #1 read result: " + os.toByteArray().length
+ " str=" + os.toString("UTF-8"));
mCiphertext.setText(os.toString("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// OpenPgpData input = new OpenPgpData(inputStr);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(mCryptoServiceConnection.getService());
api.sign(new Bundle(), is, os, new OpenPgpApi.IOpenPgpCallback() {
@Override
public void onReturn(Bundle result) {
switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
case OpenPgpConstants.RESULT_CODE_SUCCESS: {
try {
Log.d(OpenPgpConstants.TAG, "result: " + os.toByteArray().length
+ " str=" + os.toString("UTF-8"));
mCiphertext.setText(os.toString("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
break;
}
case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED: {
PendingIntent pi = result.getParcelable(OpenPgpConstants.RESULT_INTENT);
try {
OpenPgpProviderActivity.this.startIntentSenderForResult(pi.getIntentSender(),
REQUEST_CODE_SIGN, null, // or new Intent() (in billing)
0, 0, 0);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
// try {
// pi.send(OpenPgpProviderActivity.this, 42, null, new PendingIntent.OnFinished() {
//
// try {
// mCryptoServiceConnection.getService().sign(input,
// new OpenPgpData(OpenPgpData.TYPE_STRING), encryptCallback);
// } catch (RemoteException e) {
// Log.e(Constants.TAG, "CryptoProviderDemo", e);
// }
// @Override
// public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras) {
// Log.d(Constants.TAG, "onSendFinished");
// Log.d(Constants.TAG, "resultCode: " + resultCode);
//
// }
// }, null);
// } catch (PendingIntent.CanceledException e) {
// e.printStackTrace();
// }
break;
}
}
}
});
}
public void signAndEncryptOnClick(View view) {
@@ -258,6 +296,21 @@ public class OpenPgpProviderActivity extends Activity {
// }
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// super.onActivityResult(requestCode, resultCode, data);
Log.d(Constants.TAG, "onActivityResult");
switch (requestCode) {
case REQUEST_CODE_SIGN: {
Log.d(Constants.TAG, "resultCode: " + resultCode);
if (resultCode == RESULT_OK) {
signOnClick(null);
}
}
}
}
@Override
public void onDestroy() {
super.onDestroy();

View File

@@ -23,145 +23,52 @@ import org.openintents.openpgp.IOpenPgpKeyIdsCallback;
interface IOpenPgpService {
/**
* Bundle params:
* api_version 1,2,3,... (current: 1)
* ascii_armor true/false (for output)
* key_ids long[] (for encrypt method)
* General extras
* --------------
*
* params:
* int api_version (current: 1)
* boolean ascii_armor true/false (for output)
*
*
* Bundle return:
* result_code RESULT_ERROR=0 (see error), RESULT_OK=1, RESULT_USER_INTERACTION_REQUIRED=2 (execute intent and do it again with params from intent)
* signature_result OpenPgpSignatureResult
* error OpenPgpError
* intent Intent
* int result_code 0,1, or 2 (see OpenPgpConstants)
* OpenPgpSignatureResult signature_result
* OpenPgpError error
* Intent intent
*
*/
/**
* sign only
*
* params:
* String passphrase (optional)
*/
Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* encrypt
*
* params:
* long[] key_ids
* or
* String[] user_ids (= emails of recipients) (if more than one key has this user_id, an Intent is returned)
*/
Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* sign and encrypt
*
* params:
* same as in encrypt()
*/
Bundle signAndEncrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/*
------------------OLD--------------------------
*/
/**
* Sign
*
* After successful signing, callback's onSuccess will contain the resulting output.
*
* @param input
* OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri
* @param output
* Request output format by defining OpenPgpData object
*
* new OpenPgpData(OpenPgpData.TYPE_STRING)
* Returns as String
* (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53)
* new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY)
* Returns as byte[]
* new OpenPgpData(uri)
* Writes output to given Uri
* new OpenPgpData(fileDescriptor)
* Writes output to given ParcelFileDescriptor
* @param callback
* Callback where to return results
*/
//oneway void sign(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback);
/**
* Encrypt
*
* After successful encryption, callback's onSuccess will contain the resulting output.
*
* @param input
* OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri
* @param output
* Request output format by defining OpenPgpData object
*
* new OpenPgpData(OpenPgpData.TYPE_STRING)
* Returns as String
* (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53)
* new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY)
* Returns as byte[]
* new OpenPgpData(uri)
* Writes output to given Uri
* new OpenPgpData(fileDescriptor)
* Writes output to given ParcelFileDescriptor
* @param keyIds
* Key Ids of recipients. Can be retrieved with getKeyIds()
* @param callback
* Callback where to return results
*/
//oneway void encrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback);
/**
* Sign then encrypt
*
* After successful signing and encryption, callback's onSuccess will contain the resulting output.
*
* @param input
* OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri
* @param output
* Request output format by defining OpenPgpData object
*
* new OpenPgpData(OpenPgpData.TYPE_STRING)
* Returns as String
* (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53)
* new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY)
* Returns as byte[]
* new OpenPgpData(uri)
* Writes output to given Uri
* new OpenPgpData(fileDescriptor)
* Writes output to given ParcelFileDescriptor
* @param keyIds
* Key Ids of recipients. Can be retrieved with getKeyIds()
* @param callback
* Callback where to return results
*/
//oneway void signAndEncrypt(in OpenPgpData input, in OpenPgpData output, in long[] keyIds, in IOpenPgpCallback callback);
/**
* Decrypts and verifies given input bytes. This methods handles encrypted-only, signed-and-encrypted,
* and also signed-only input.
*
* After successful decryption/verification, callback's onSuccess will contain the resulting output.
* The signatureResult in onSuccess is only non-null if signed-and-encrypted or signed-only inputBytes were given.
*
* @param input
* OpenPgpData object containing String, byte[], ParcelFileDescriptor, or Uri
* @param output
* Request output format by defining OpenPgpData object
*
* new OpenPgpData(OpenPgpData.TYPE_STRING)
* Returns as String
* (OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53)
* new OpenPgpData(OpenPgpData.TYPE_BYTE_ARRAY)
* Returns as byte[]
* new OpenPgpData(uri)
* Writes output to given Uri
* new OpenPgpData(fileDescriptor)
* Writes output to given ParcelFileDescriptor
* @param callback
* Callback where to return results
*/
//oneway void decryptAndVerify(in OpenPgpData input, in OpenPgpData output, in IOpenPgpCallback callback);
/**
* Get available key ids based on given user ids
*
* @param ids
* User Ids (emails) of recipients OR key ids
* @param allowUserInteraction
* Enable user interaction to lookup and import unknown keys
* @param callback
* Callback where to return results (different type than callback in other functions!)
*/
//oneway void getKeyIds(in String[] ids, in boolean allowUserInteraction, in IOpenPgpKeyIdsCallback callback);
Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
}

View File

@@ -16,15 +16,14 @@
package org.openintents.openpgp.util;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import org.openintents.openpgp.IOpenPgpService;
import org.openintents.openpgp.OpenPgpError;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -32,11 +31,98 @@ public class OpenPgpApi {
IOpenPgpService mService;
private static final int OPERATION_SIGN = 0;
private static final int OPERATION_ENCRYPT = 1;
private static final int OPERATION_SIGN_ENCRYPT = 2;
private static final int OPERATION_DECRYPT_VERIFY = 3;
public OpenPgpApi(IOpenPgpService service) {
this.mService = service;
}
public Bundle sign(InputStream is, final OutputStream os) {
return executeApi(OPERATION_SIGN, new Bundle(), is, os);
}
public Bundle sign(Bundle params, InputStream is, final OutputStream os) {
return executeApi(OPERATION_SIGN, params, is, os);
}
public void sign(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) {
executeApiAsync(OPERATION_SIGN, params, is, os, callback);
}
public Bundle encrypt(InputStream is, final OutputStream os) {
return executeApi(OPERATION_ENCRYPT, new Bundle(), is, os);
}
public Bundle encrypt(Bundle params, InputStream is, final OutputStream os) {
return executeApi(OPERATION_ENCRYPT, params, is, os);
}
public void encrypt(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) {
executeApiAsync(OPERATION_ENCRYPT, params, is, os, callback);
}
public Bundle signAndEncrypt(InputStream is, final OutputStream os) {
return executeApi(OPERATION_SIGN_ENCRYPT, new Bundle(), is, os);
}
public Bundle signAndEncrypt(Bundle params, InputStream is, final OutputStream os) {
return executeApi(OPERATION_SIGN_ENCRYPT, params, is, os);
}
public void signAndEncrypt(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) {
executeApiAsync(OPERATION_SIGN_ENCRYPT, params, is, os, callback);
}
public Bundle decryptAndVerify(InputStream is, final OutputStream os) {
return executeApi(OPERATION_DECRYPT_VERIFY, new Bundle(), is, os);
}
public Bundle decryptAndVerify(Bundle params, InputStream is, final OutputStream os) {
return executeApi(OPERATION_DECRYPT_VERIFY, params, is, os);
}
public void decryptAndVerify(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) {
executeApiAsync(OPERATION_DECRYPT_VERIFY, params, is, os, callback);
}
public interface IOpenPgpCallback {
void onReturn(final Bundle result);
}
private class OpenPgpAsyncTask extends AsyncTask<Void, Integer, Bundle> {
int operationId;
Bundle params;
InputStream is;
OutputStream os;
IOpenPgpCallback callback;
private OpenPgpAsyncTask(int operationId, Bundle params, InputStream is, OutputStream os, IOpenPgpCallback callback) {
this.operationId = operationId;
this.params = params;
this.is = is;
this.os = os;
this.callback = callback;
}
@Override
protected Bundle doInBackground(Void... unused) {
return executeApi(operationId, params, is, os);
}
protected void onPostExecute(Bundle result) {
callback.onReturn(result);
}
}
private void executeApiAsync(int operationId, Bundle params, InputStream is, OutputStream os, IOpenPgpCallback callback) {
new OpenPgpAsyncTask(operationId, params, is, os, callback).execute((Void[]) null);
}
private Bundle executeApi(int operationId, Bundle params, InputStream is, OutputStream os) {
try {
// send the input and output pfds
ParcelFileDescriptor input = ParcelFileDescriptorUtil.pipeFrom(is,
@@ -56,24 +142,35 @@ public class OpenPgpApi {
}
});
Bundle params = new Bundle();
params.putInt(OpenPgpConstants.PARAMS_API_VERSION, OpenPgpConstants.API_VERSION);
// default result is error
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
new OpenPgpError(OpenPgpError.GENERIC_ERROR, "This should never happen!"));
// blocks until result is ready
Bundle result = mService.sign(params, input, output);
switch (operationId) {
case OPERATION_SIGN:
result = mService.sign(params, input, output);
break;
case OPERATION_ENCRYPT:
result = mService.encrypt(params, input, output);
break;
case OPERATION_SIGN_ENCRYPT:
result = mService.signAndEncrypt(params, input, output);
break;
case OPERATION_DECRYPT_VERIFY:
result = mService.decryptAndVerify(params, input, output);
break;
}
// close() is required to halt the TransferThread
output.close();
return result;
} catch (RemoteException e) {
Log.e(OpenPgpConstants.TAG, "RemoteException", e);
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage()));
return result;
} catch (IOException e) {
Log.e(OpenPgpConstants.TAG, "IOException", e);
} catch (Exception e) {
Log.e(OpenPgpConstants.TAG, "Exception", e);
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putParcelable(OpenPgpConstants.RESULT_ERRORS,

View File

@@ -42,7 +42,7 @@ public class OpenPgpConstants {
public static final int RESULT_CODE_ERROR = 0;
// success!
public static final int RESULT_CODE_SUCCESS = 1;
// execute intent and do it again with params from intent
// executeServiceMethod intent and do it again with params from intent
public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2;
}