diff --git a/APG-API-Demo/AndroidManifest.xml b/APG-API-Demo/AndroidManifest.xml
index 4112b8a09..812b5d45e 100644
--- a/APG-API-Demo/AndroidManifest.xml
+++ b/APG-API-Demo/AndroidManifest.xml
@@ -4,8 +4,8 @@
android:versionCode="1"
android:versionName="1.0" >
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/APG-API-Demo/res/xml/base_preference.xml b/APG-API-Demo/res/xml/base_preference.xml
index 3fcd036e2..c9a34efd1 100644
--- a/APG-API-Demo/res/xml/base_preference.xml
+++ b/APG-API-Demo/res/xml/base_preference.xml
@@ -6,15 +6,18 @@
android:key="intent_demo"
android:title="Intent Demo" />
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/APG-API-Demo/src/org/thialfihar/android/apg/demo/AidlDemoActivity.java b/APG-API-Demo/src/org/thialfihar/android/apg/demo/AidlDemoActivity.java
index 7c08c0e06..65bd3caf5 100644
--- a/APG-API-Demo/src/org/thialfihar/android/apg/demo/AidlDemoActivity.java
+++ b/APG-API-Demo/src/org/thialfihar/android/apg/demo/AidlDemoActivity.java
@@ -18,9 +18,10 @@ package org.thialfihar.android.apg.demo;
import org.thialfihar.android.apg.integration.ApgData;
import org.thialfihar.android.apg.integration.ApgIntentHelper;
-import org.thialfihar.android.apg.service.IApgEncryptDecryptHandler;
-import org.thialfihar.android.apg.service.IApgHelperHandler;
-import org.thialfihar.android.apg.service.IApgService;
+import org.thialfihar.android.apg.service.IApgApiService;
+import org.thialfihar.android.apg.service.handler.IApgDecryptHandler;
+import org.thialfihar.android.apg.service.handler.IApgEncryptHandler;
+import org.thialfihar.android.apg.service.handler.IApgGetDecryptionKeyIdHandler;
import android.app.Activity;
import android.app.AlertDialog;
@@ -44,10 +45,10 @@ public class AidlDemoActivity extends Activity {
ApgIntentHelper mApgIntentHelper;
ApgData mApgData;
- private IApgService service = null;
+ private IApgApiService service = null;
private ServiceConnection svcConn = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
- service = IApgService.Stub.asInterface(binder);
+ service = IApgApiService.Stub.asInterface(binder);
}
public void onServiceDisconnected(ComponentName className) {
@@ -69,7 +70,7 @@ public class AidlDemoActivity extends Activity {
mApgIntentHelper = new ApgIntentHelper(mActivity);
mApgData = new ApgData();
- bindService(new Intent("org.thialfihar.android.apg.service.IApgService"), svcConn,
+ bindService(new Intent("org.thialfihar.android.apg.service.IApgApiService"), svcConn,
Context.BIND_AUTO_CREATE);
}
@@ -77,8 +78,8 @@ public class AidlDemoActivity extends Activity {
byte[] inputBytes = mMessageTextView.getText().toString().getBytes();
try {
- service.encryptAsymmetric(inputBytes, null, true, 0, mApgData.getEncryptionKeys(), 7,
- encryptDecryptHandler);
+ service.encryptAsymmetric(inputBytes, null, true, 0, mApgData.getPublicKeys(), 7,
+ encryptHandler);
} catch (RemoteException e) {
exceptionImplementation(-1, e.toString());
}
@@ -88,7 +89,7 @@ public class AidlDemoActivity extends Activity {
byte[] inputBytes = mCiphertextTextView.getText().toString().getBytes();
try {
- service.decryptAndVerifyAsymmetric(inputBytes, null, null, encryptDecryptHandler);
+ service.decryptAndVerifyAsymmetric(inputBytes, null, null, decryptHandler);
} catch (RemoteException e) {
exceptionImplementation(-1, e.toString());
}
@@ -116,7 +117,7 @@ public class AidlDemoActivity extends Activity {
builder.setTitle("Exception!").setMessage(error).setPositiveButton("OK", null).show();
}
- private final IApgEncryptDecryptHandler.Stub encryptDecryptHandler = new IApgEncryptDecryptHandler.Stub() {
+ private final IApgEncryptHandler.Stub encryptHandler = new IApgEncryptHandler.Stub() {
@Override
public void onException(final int exceptionId, final String message) throws RemoteException {
@@ -128,8 +129,7 @@ public class AidlDemoActivity extends Activity {
}
@Override
- public void onSuccessEncrypt(final byte[] outputBytes, String outputUri)
- throws RemoteException {
+ public void onSuccess(final byte[] outputBytes, String outputUri) throws RemoteException {
runOnUiThread(new Runnable() {
public void run() {
mApgData.setEncryptedData(new String(outputBytes));
@@ -138,8 +138,21 @@ public class AidlDemoActivity extends Activity {
});
}
+ };
+
+ private final IApgDecryptHandler.Stub decryptHandler = new IApgDecryptHandler.Stub() {
+
@Override
- public void onSuccessDecrypt(final byte[] outputBytes, String outputUri, boolean signature,
+ public void onException(final int exceptionId, final String message) throws RemoteException {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ exceptionImplementation(exceptionId, message);
+ }
+ });
+ }
+
+ @Override
+ public void onSuccess(final byte[] outputBytes, String outputUri, boolean signature,
long signatureKeyId, String signatureUserId, boolean signatureSuccess,
boolean signatureUnknown) throws RemoteException {
runOnUiThread(new Runnable() {
@@ -153,7 +166,7 @@ public class AidlDemoActivity extends Activity {
};
- private final IApgHelperHandler.Stub helperHandler = new IApgHelperHandler.Stub() {
+ private final IApgGetDecryptionKeyIdHandler.Stub helperHandler = new IApgGetDecryptionKeyIdHandler.Stub() {
@Override
public void onException(final int exceptionId, final String message) throws RemoteException {
@@ -165,7 +178,7 @@ public class AidlDemoActivity extends Activity {
}
@Override
- public void onSuccessGetDecryptionKey(long arg0, boolean arg1) throws RemoteException {
+ public void onSuccess(long arg0, boolean arg1) throws RemoteException {
// TODO Auto-generated method stub
}
@@ -182,7 +195,7 @@ public class AidlDemoActivity extends Activity {
}
public void selectEncryptionKeysOnClick(View view) {
- mApgIntentHelper.selectEncryptionKeys("user@example.com");
+ mApgIntentHelper.selectPublicKeys("user@example.com");
}
diff --git a/APG-API-Demo/src/org/thialfihar/android/apg/demo/AidlDemoActivity2.java b/APG-API-Demo/src/org/thialfihar/android/apg/demo/AidlDemoActivity2.java
new file mode 100644
index 000000000..51054f58a
--- /dev/null
+++ b/APG-API-Demo/src/org/thialfihar/android/apg/demo/AidlDemoActivity2.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.demo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.thialfihar.android.apg.integration.ApgData;
+import org.thialfihar.android.apg.integration.ApgIntentHelper;
+import org.thialfihar.android.apg.service.IApgKeyService;
+import org.thialfihar.android.apg.service.handler.IApgGetKeyringsHandler;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Base64;
+import android.view.View;
+import android.widget.TextView;
+
+public class AidlDemoActivity2 extends Activity {
+ Activity mActivity;
+
+ TextView mKeyringsTextView;
+
+ ApgIntentHelper mApgIntentHelper;
+ ApgData mApgData;
+
+ byte[] keysBytes;
+ ArrayList keysStrings;
+
+ private IApgKeyService service = null;
+ private ServiceConnection svcConn = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder binder) {
+ service = IApgKeyService.Stub.asInterface(binder);
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ service = null;
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.aidl_demo2);
+
+ mActivity = this;
+
+ mKeyringsTextView = (TextView) findViewById(R.id.aidl_demo_keyrings);
+
+ mApgIntentHelper = new ApgIntentHelper(mActivity);
+ mApgData = new ApgData();
+
+ bindService(new Intent("org.thialfihar.android.apg.service.IApgKeyService"), svcConn,
+ Context.BIND_AUTO_CREATE);
+ }
+
+ public void getKeyringsStringsOnClick(View view) {
+ try {
+ service.getPublicKeyRings(mApgData.getPublicKeys(), true, getKeyringsHandler);
+ } catch (RemoteException e) {
+ exceptionImplementation(-1, e.toString());
+ }
+ }
+
+ public void getKeyringsBytesOnClick(View view) {
+ try {
+ service.getPublicKeyRings(mApgData.getPublicKeys(), false, getKeyringsHandler);
+ } catch (RemoteException e) {
+ exceptionImplementation(-1, e.toString());
+ }
+ }
+
+ @SuppressLint("NewApi")
+ private void updateView() {
+ if (keysBytes != null) {
+ mKeyringsTextView.setText(Base64.encodeToString(keysBytes, Base64.DEFAULT));
+ } else if (keysStrings != null) {
+ mKeyringsTextView.setText("");
+ for (String output : keysStrings) {
+ mKeyringsTextView.append(output);
+ }
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+
+ unbindService(svcConn);
+ }
+
+ private void exceptionImplementation(int exceptionId, String error) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("Exception!").setMessage(error).setPositiveButton("OK", null).show();
+ }
+
+ private final IApgGetKeyringsHandler.Stub getKeyringsHandler = new IApgGetKeyringsHandler.Stub() {
+
+ @Override
+ public void onException(final int exceptionId, final String message) throws RemoteException {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ exceptionImplementation(exceptionId, message);
+ }
+ });
+ }
+
+ @Override
+ public void onSuccess(final byte[] outputBytes, final List outputStrings)
+ throws RemoteException {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ if (outputBytes != null) {
+ keysBytes = outputBytes;
+ keysStrings = null;
+ } else if (outputStrings != null) {
+ keysBytes = null;
+ keysStrings = (ArrayList) outputStrings;
+ }
+ updateView();
+ }
+ });
+
+ }
+
+ };
+
+ public void selectEncryptionKeysOnClick(View view) {
+ mApgIntentHelper.selectPublicKeys("user@example.com");
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // this updates the mApgData object to the result of the methods
+ boolean result = mApgIntentHelper.onActivityResult(requestCode, resultCode, data, mApgData);
+ if (result) {
+ updateView();
+ }
+
+ // continue with other activity results
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+}
diff --git a/APG-API-Demo/src/org/thialfihar/android/apg/demo/BaseActivity.java b/APG-API-Demo/src/org/thialfihar/android/apg/demo/BaseActivity.java
index 66c3a9a0e..5e2108c50 100644
--- a/APG-API-Demo/src/org/thialfihar/android/apg/demo/BaseActivity.java
+++ b/APG-API-Demo/src/org/thialfihar/android/apg/demo/BaseActivity.java
@@ -29,8 +29,9 @@ public class BaseActivity extends PreferenceActivity {
private Activity mActivity;
private Preference mIntentDemo;
- private Preference mAidlDemo;
private Preference mContentProviderDemo;
+ private Preference mAidlDemo;
+ private Preference mAidlDemo2;
/**
* Called when the activity is first created.
@@ -46,8 +47,9 @@ public class BaseActivity extends PreferenceActivity {
// find preferences
mIntentDemo = (Preference) findPreference("intent_demo");
- mAidlDemo = (Preference) findPreference("aidl_demo");
mContentProviderDemo = (Preference) findPreference("content_provider_demo");
+ mAidlDemo = (Preference) findPreference("aidl_demo");
+ mAidlDemo2 = (Preference) findPreference("aidl_demo2");
mIntentDemo.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
@@ -58,6 +60,15 @@ public class BaseActivity extends PreferenceActivity {
}
});
+ mContentProviderDemo.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ startActivity(new Intent(mActivity, ContentProviderDemoActivity.class));
+
+ return false;
+ }
+ });
+
mAidlDemo.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
@@ -67,14 +78,15 @@ public class BaseActivity extends PreferenceActivity {
}
});
- mContentProviderDemo.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ mAidlDemo2.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
- startActivity(new Intent(mActivity, ContentProviderDemoActivity.class));
+ startActivity(new Intent(mActivity, AidlDemoActivity2.class));
return false;
}
});
+
}
}
diff --git a/APG-API-Demo/src/org/thialfihar/android/apg/demo/IntentDemoActivity.java b/APG-API-Demo/src/org/thialfihar/android/apg/demo/IntentDemoActivity.java
index b707e48a8..b789dccb1 100644
--- a/APG-API-Demo/src/org/thialfihar/android/apg/demo/IntentDemoActivity.java
+++ b/APG-API-Demo/src/org/thialfihar/android/apg/demo/IntentDemoActivity.java
@@ -65,17 +65,17 @@ public class IntentDemoActivity extends Activity {
}
public void selectEncryptionKeysOnClick(View view) {
- mApgIntentHelper.selectEncryptionKeys("user@example.com");
+ mApgIntentHelper.selectPublicKeys("user@example.com");
}
public void encryptOnClick(View view) {
- mApgIntentHelper.encrypt(mMessageTextView.getText().toString(),
- mApgData.getEncryptionKeys(), mApgData.getSignatureKeyId(), false);
+ mApgIntentHelper.encrypt(mMessageTextView.getText().toString(), mApgData.getPublicKeys(),
+ mApgData.getSecretKeyId(), false);
}
public void encryptAndReturnOnClick(View view) {
- mApgIntentHelper.encrypt(mMessageTextView.getText().toString(),
- mApgData.getEncryptionKeys(), mApgData.getSignatureKeyId(), true);
+ mApgIntentHelper.encrypt(mMessageTextView.getText().toString(), mApgData.getPublicKeys(),
+ mApgData.getSecretKeyId(), true);
}
public void decryptOnClick(View view) {
diff --git a/APG/src/org/thialfihar/android/apg/service/IApgService.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgApiService.aidl
similarity index 89%
rename from APG/src/org/thialfihar/android/apg/service/IApgService.aidl
rename to APG-API-Lib/src/org/thialfihar/android/apg/service/IApgApiService.aidl
index 98c08c62b..277ce6722 100644
--- a/APG/src/org/thialfihar/android/apg/service/IApgService.aidl
+++ b/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgApiService.aidl
@@ -16,15 +16,15 @@
package org.thialfihar.android.apg.service;
-import org.thialfihar.android.apg.service.IApgEncryptSignHandler;
-import org.thialfihar.android.apg.service.IApgDecryptVerifyHandler;
-import org.thialfihar.android.apg.service.IApgHelperHandler;
+import org.thialfihar.android.apg.service.handler.IApgEncryptHandler;
+import org.thialfihar.android.apg.service.handler.IApgDecryptHandler;
+import org.thialfihar.android.apg.service.handler.IApgGetDecryptionKeyIdHandler;
/**
* All methods are oneway, which means they are asynchronous and non-blocking.
* Results are returned into given Handler, which has to be implemented on client side.
*/
-interface IApgService {
+interface IApgApiService {
/**
* Encrypt
@@ -50,7 +50,7 @@ interface IApgService {
*/
oneway void encryptAsymmetric(in byte[] inputBytes, in String inputUri, in boolean useAsciiArmor,
in int compression, in long[] encryptionKeyIds, in int symmetricEncryptionAlgorithm,
- in IApgEncryptSignHandler handler);
+ in IApgEncryptHandler handler);
/**
* Same as encryptAsymmetric but using a passphrase for symmetric encryption
@@ -60,7 +60,7 @@ interface IApgService {
*/
oneway void encryptSymmetric(in byte[] inputBytes, in String inputUri, in boolean useAsciiArmor,
in int compression, in String encryptionPassphrase, in int symmetricEncryptionAlgorithm,
- in IApgEncryptSignHandler handler);
+ in IApgEncryptHandler handler);
/**
* Encrypt and sign
@@ -97,7 +97,7 @@ interface IApgService {
in boolean useAsciiArmor, in int compression, in long[] encryptionKeyIds,
in int symmetricEncryptionAlgorithm, in long signatureKeyId, in int signatureHashAlgorithm,
in boolean signatureForceV3, in String signaturePassphrase,
- in IApgEncryptSignHandler handler);
+ in IApgEncryptHandler handler);
/**
* Same as encryptAndSignAsymmetric but using a passphrase for symmetric encryption
@@ -109,7 +109,7 @@ interface IApgService {
in boolean useAsciiArmor, in int compression, in String encryptionPassphrase,
in int symmetricEncryptionAlgorithm, in long signatureKeyId, in int signatureHashAlgorithm,
in boolean signatureForceV3, in String signaturePassphrase,
- in IApgEncryptSignHandler handler);
+ in IApgEncryptHandler handler);
/**
* Decrypts and verifies given input bytes. If no signature is present this method
@@ -125,7 +125,7 @@ interface IApgService {
* Handler where to return results to after successful encryption
*/
oneway void decryptAndVerifyAsymmetric(in byte[] inputBytes, in String inputUri,
- in String keyPassphrase, in IApgDecryptVerifyHandler handler);
+ in String keyPassphrase, in IApgDecryptHandler handler);
/**
* Same as decryptAndVerifyAsymmetric but for symmetric decryption.
@@ -134,13 +134,13 @@ interface IApgService {
* Passphrase to decrypt
*/
oneway void decryptAndVerifySymmetric(in byte[] inputBytes, in String inputUri,
- in String encryptionPassphrase, in IApgDecryptVerifyHandler handler);
+ in String encryptionPassphrase, in IApgDecryptHandler handler);
/**
*
*/
- oneway void getDecryptionKey(in byte[] inputBytes, in String inputUri,
- in IApgHelperHandler handler);
+ oneway void getDecryptionKeyId(in byte[] inputBytes, in String inputUri,
+ in IApgGetDecryptionKeyIdHandler handler);
}
\ No newline at end of file
diff --git a/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgEncryptDecryptHandler.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgEncryptDecryptHandler.aidl
deleted file mode 100644
index ff6b7254c..000000000
--- a/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgEncryptDecryptHandler.aidl
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.thialfihar.android.apg.service;
-
-interface IApgEncryptDecryptHandler {
- /**
- * Either output or streamUri is given. One of them is null
- *
- */
- oneway void onSuccessEncrypt(in byte[] outputBytes, in String outputUri);
-
- oneway void onSuccessDecrypt(in byte[] outputBytes, in String outputUri, in boolean signature,
- in long signatureKeyId, in String signatureUserId, in boolean signatureSuccess,
- in boolean signatureUnknown);
-
-
- oneway void onException(in int exceptionNumber, in String message);
-}
\ No newline at end of file
diff --git a/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgHelperHandler.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgHelperHandler.aidl
deleted file mode 100644
index bb405329a..000000000
--- a/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgHelperHandler.aidl
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.thialfihar.android.apg.service;
-
-interface IApgHelperHandler {
-
- oneway void onSuccessGetDecryptionKey(in long secretKeyId, in boolean symmetric);
-
-
- oneway void onException(in int exceptionNumber, in String message);
-}
\ No newline at end of file
diff --git a/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgKeyService.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgKeyService.aidl
new file mode 100644
index 000000000..12ecddc17
--- /dev/null
+++ b/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgKeyService.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service;
+
+import org.thialfihar.android.apg.service.handler.IApgGetKeyringsHandler;
+
+/**
+ * All methods are oneway, which means they are asynchronous and non-blocking.
+ * Results are returned into given Handler, which has to be implemented on client side.
+ */
+interface IApgKeyService {
+
+ oneway void getPublicKeyRings(in long[] masterKeyIds, in boolean asAsciiArmoredStringArray,
+ in IApgGetKeyringsHandler handler);
+
+ oneway void getSecretKeyRings(in long[] masterKeyIds, in boolean asAsciiArmoredStringArray,
+ in IApgGetKeyringsHandler handler);
+}
\ No newline at end of file
diff --git a/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgSignVerifyHandler.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgSignVerifyHandler.aidl
deleted file mode 100644
index 1375d1548..000000000
--- a/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgSignVerifyHandler.aidl
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.thialfihar.android.apg.service;
-
-interface IApgSignVerifyHandler {
- oneway void onSuccessSign(in byte[] outputBytes, in String outputUri);
-
- oneway void onSuccessVerify(in boolean signature, in long signatureKeyId,
- in String signatureUserId, in boolean signatureSuccess, in boolean signatureUnknown);
-
-
- oneway void onException(in int exceptionNumber, in String message);
-}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/IApgDecryptVerifyHandler.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgDecryptHandler.aidl
similarity index 69%
rename from APG/src/org/thialfihar/android/apg/service/IApgDecryptVerifyHandler.aidl
rename to APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgDecryptHandler.aidl
index ad74340bf..feb56bce6 100644
--- a/APG/src/org/thialfihar/android/apg/service/IApgDecryptVerifyHandler.aidl
+++ b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgDecryptHandler.aidl
@@ -14,17 +14,14 @@
* limitations under the License.
*/
-package org.thialfihar.android.apg.service;
+package org.thialfihar.android.apg.service.handler;
-interface IApgDecryptVerifyHandler {
+interface IApgDecryptHandler {
- oneway void onSuccessDecrypt(in byte[] outputBytes, in String outputUri, in boolean signature,
+ oneway void onSuccess(in byte[] outputBytes, in String outputUri, in boolean signature,
in long signatureKeyId, in String signatureUserId, in boolean signatureSuccess,
in boolean signatureUnknown);
-
- oneway void onSuccessVerify(in boolean signature, in long signatureKeyId,
- in String signatureUserId, in boolean signatureSuccess, in boolean signatureUnknown);
-
-
+
+
oneway void onException(in int exceptionNumber, in String message);
}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/IApgEncryptSignHandler.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgEncryptHandler.aidl
similarity index 76%
rename from APG/src/org/thialfihar/android/apg/service/IApgEncryptSignHandler.aidl
rename to APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgEncryptHandler.aidl
index ea3e2ae86..be0317715 100644
--- a/APG/src/org/thialfihar/android/apg/service/IApgEncryptSignHandler.aidl
+++ b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgEncryptHandler.aidl
@@ -14,17 +14,15 @@
* limitations under the License.
*/
-package org.thialfihar.android.apg.service;
+package org.thialfihar.android.apg.service.handler;
-interface IApgEncryptSignHandler {
+interface IApgEncryptHandler {
/**
* Either output or streamUri is given. One of them is null
*
*/
- oneway void onSuccessEncrypt(in byte[] outputBytes, in String outputUri);
-
- oneway void onSuccessSign(in byte[] outputBytes, in String outputUri);
-
-
+ oneway void onSuccess(in byte[] outputBytes, in String outputUri);
+
+
oneway void onException(in int exceptionNumber, in String message);
}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/IApgHelperHandler.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgGetDecryptionKeyIdHandler.aidl
similarity index 80%
rename from APG/src/org/thialfihar/android/apg/service/IApgHelperHandler.aidl
rename to APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgGetDecryptionKeyIdHandler.aidl
index 29ff2dd3e..020a80b99 100644
--- a/APG/src/org/thialfihar/android/apg/service/IApgHelperHandler.aidl
+++ b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgGetDecryptionKeyIdHandler.aidl
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package org.thialfihar.android.apg.service;
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgGetDecryptionKeyIdHandler {
+
+ oneway void onSuccess(in long secretKeyId, in boolean symmetric);
-interface IApgHelperHandler {
- oneway void onSuccessGetDecryptionKey(in long secretKeyId, in boolean symmetric);
-
-
oneway void onException(in int exceptionNumber, in String message);
}
\ No newline at end of file
diff --git a/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgGetKeyringsHandler.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgGetKeyringsHandler.aidl
new file mode 100644
index 000000000..ffa9d0d2d
--- /dev/null
+++ b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgGetKeyringsHandler.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgGetKeyringsHandler {
+ /**
+ * Either outputBytes or outputString is given. One of them is null
+ *
+ */
+ oneway void onSuccess(in byte[] outputBytes, in List outputString);
+
+
+ oneway void onException(in int exceptionNumber, in String message);
+}
\ No newline at end of file
diff --git a/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgSignHandler.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgSignHandler.aidl
new file mode 100644
index 000000000..cf91e8bc4
--- /dev/null
+++ b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgSignHandler.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgSignHandler {
+ /**
+ * Either output or streamUri is given. One of them is null
+ *
+ */
+ oneway void onSuccess(in byte[] outputBytes, in String outputUri);
+
+
+ oneway void onException(in int exceptionNumber, in String message);
+}
\ No newline at end of file
diff --git a/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgVerifyHandler.aidl b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgVerifyHandler.aidl
new file mode 100644
index 000000000..6baaec758
--- /dev/null
+++ b/APG-API-Lib/src/org/thialfihar/android/apg/service/handler/IApgVerifyHandler.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgVerifyHandler {
+
+ oneway void onSuccess(in boolean signature, in long signatureKeyId,
+ in String signatureUserId, in boolean signatureSuccess, in boolean signatureUnknown);
+
+
+ oneway void onException(in int exceptionNumber, in String message);
+}
\ No newline at end of file
diff --git a/APG/AndroidManifest.xml b/APG/AndroidManifest.xml
index ea5dcb1f8..800655f8b 100644
--- a/APG/AndroidManifest.xml
+++ b/APG/AndroidManifest.xml
@@ -60,9 +60,9 @@
android:label="@string/permission_group_label" />
+ android:process=":remoteapi" >
-
+
+
+
+
+
+
+
+
+ android:readPermission="org.thialfihar.android.apg.permission.ACCESS_API" />
Mail Inbox
- Manage Public Keys
- Manage Secret Keys
- Select Public Key
- Select Secret Key
+ Manage Public Keyrings
+ Manage Secret Keyrings
+ Select Public Keyring
+ Select Secret KeyringEncryptDecryptPassphraseCreate Key
- Edit Key
- Create Key
+ Edit Keyring
+ Create KeyringPreferencesKey Server PreferenceChange Passphrase
@@ -37,16 +37,16 @@
"Send Mail…"Encrypt To FileDecrypt To File
- Import Keys
- Export Key
- Export Keys
+ Import Keyrings
+ Export Keyring
+ Export KeyringsKey Not FoundGetting StartedQuery Key ServerExport to Key ServerUnknown Signature KeyImport from QR Code
- Sign Key
+ Sign KeyringAboutHelp
@@ -86,21 +86,21 @@
AboutDelete Account
- Manage Public Keys
- Manage Secret Keys
+ Manage Public Keyrings
+ Manage Secret KeyringsSettings
- Import Keys
- Export All Keys
- Export Key
- Delete Key
- Create Key
- Edit Key
+ Import Keyrings
+ Export All Keyrings
+ Export Keyring
+ Delete Keyring
+ Create Keyring
+ Edit KeyringSearchHelpKey ServerUpdate from ServerExport To Server
- Share public key with QR Code
+ Share public keyring with QR CodeScan QR CodeSign Key
@@ -135,7 +135,7 @@
NameCommentEmail
- Send Key to Server?
+ Send Keyring to Server?Select1 SelectedSelected
@@ -201,32 +201,31 @@
Successfully encrypted.Successfully encrypted to clipboard.Enter the passphrase twice.
- Select at least one encryption key.
- Select at least one encryption key or a signature key.
+ Select at least one encryption keyring.
+ Select at least one encryption keyring or a signature keyring.Please specify which file to encrypt to.\nWARNING! File will be overwritten if it exists.Please specify which file to decrypt to.\nWARNING! File will be overwritten if it exists.
- Please specify which file to import keys from. (.asc or .gpg)
+ Please specify which file to import keyrings from. (.asc or .gpg)Please specify which file to export to.\nWARNING! File will be overwritten if it exists.
- Please specify which file to export to.\nWARNING! You are about to export SECRET keys.\nWARNING! File will be overwritten if it exists.
- Do you really want to delete the key \'%s\'?\nYou can\'t undo this!
- Do you really want to delete the SECRET key \'%s\'?\nYou can\'t undo this!
- Successfully added %1$s key(s) and updated %2$s key(s).
- Successfully added %s key(s).
- Successfully updated %s key(s).
- No keys added or updated.
- Successfully exported 1 key.
- Successfully exported %s keys.
- No keys exported.
+ Please specify which file to export to.\nWARNING! You are about to export SECRET keyrings.\nWARNING! File will be overwritten if it exists.
+ Do you really want to delete the keyring \'%s\'?\nYou can\'t undo this!
+ Do you really want to delete the SECRET keyring \'%s\'?\nYou can\'t undo this!
+ Successfully added %1$s keyring(s) and updated %2$s keyring(s).
+ Successfully added %s keyring(s).
+ Successfully updated %s keyring(s).
+ No keyrings added or updated.
+ Successfully exported 1 keyring.
+ Successfully exported %s keyrings.
+ No keyrings exported.Note: only subkeys support ElGamal, and for ElGamal the nearest keysize of 1536, 2048, 3072, 4096, or 8192 will be used.Couldn\'t find key %08X.Found %s key(s).Unknown signature, touch to look up key.
- Key editing is still kind of beta.%s bad secret key(s) ignored. Perhaps you exported with the option\n --export-secret-subkeys\nMake sure you export with\n --export-secret-keys\ninstead.
- Unknown key %s, do you want to try finding it on a keyserver?
- Successfully sent key to server
- Successfully signed key
- Successfully validated and imported key
+ Unknown keyring %s, do you want to try finding it on a keyserver?
+ Successfully sent keyring to server
+ Successfully signed keyring
+ Successfully validated and imported keyringLong press one entry in this list to show more options!This list is empty!
@@ -274,12 +273,11 @@
certifying master key…building master key ring…adding sub keys…
- saving key ring…
- importing secret keys…
- importing public keys…
- reloading keys…
- exporting key…
- exporting keys…
+ saving key keyring…
+ importing secret keyrings…
+ importing public keyrings…
+ exporting keyring…
+ exporting keyrings…extracting signature key…extracting key…preparing streams…
@@ -301,18 +299,18 @@
APGPermissions to use APG
- Read key details of public and secret keys (The keys themselves can NOT be read.)
- Read key details of public and secret keys stored in APG, such as key ID and user IDs. The keys themselves can NOT be read.
- Encrypt/Sign/Decrypt/Create keys without user interaction
- Encrypt/Sign/Decrypt/Create keys (by using Intents or Remote Service) without user interaction
+ Encrypt/Sign/Decrypt/Create keys without user interaction, Read key details of public and secret keys (The keys themselves can NOT be read.)
+ Encrypt/Sign/Decrypt/Create keys (by using Intents or Remote Service) without user interaction. Read key details of public and secret keys stored in APG, such as key ID and user IDs. The keys themselves can NOT be read.
+ Import/Export actual public and secret keys
+ Import and export actual private and public keys directly without user uinteraction.EncryptDecrypt
- Import Public Keys
- Import Secret Keys
- Search Public Keys
- Search Secret Keys
+ Import Public Keyrings
+ Import Secret Keyrings
+ Search Public Keyrings
+ Search Secret KeyringsFilter: \"%s\"
@@ -324,8 +322,8 @@
- Manage Public Keys
- My Secret Keys
+ Manage Public Keyrings
+ My Secret KeyringsEncryptDecryptHelp
@@ -338,14 +336,14 @@
Version:
- Import key (only locally)
- Import, Sign, and upload key
- Scan qr code again
+ Import keyring (only locally)
+ Import, Sign, and upload keyring
+ Scan QR Code againFinishAPG: Decrypt File
- APG: Import Key
+ APG: Import KeyringAPG: EncryptAPG: Decrypt
diff --git a/APG/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java b/APG/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java
index 040ff2a9e..7fee97882 100644
--- a/APG/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java
+++ b/APG/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java
@@ -18,17 +18,24 @@ package org.thialfihar.android.apg.helper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
+import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.spongycastle.openpgp.PGPUtil;
import org.thialfihar.android.apg.Constants;
+import org.thialfihar.android.apg.provider.ProviderHelper;
import org.thialfihar.android.apg.util.Log;
+import android.content.Context;
+
public class PGPConversionHelper {
/**
@@ -134,4 +141,17 @@ public class PGPConversionHelper {
return null;
}
}
+
+ public static PGPKeyRing decodeKeyRing(InputStream is) throws IOException {
+ InputStream in = PGPUtil.getDecoderStream(is);
+ PGPObjectFactory objectFactory = new PGPObjectFactory(in);
+ Object obj = objectFactory.nextObject();
+
+ if (obj instanceof PGPKeyRing) {
+ return (PGPKeyRing) obj;
+ }
+
+ return null;
+ }
+
}
diff --git a/APG/src/org/thialfihar/android/apg/helper/PGPHelper.java b/APG/src/org/thialfihar/android/apg/helper/PGPHelper.java
index b566cffa0..1571ed023 100644
--- a/APG/src/org/thialfihar/android/apg/helper/PGPHelper.java
+++ b/APG/src/org/thialfihar/android/apg/helper/PGPHelper.java
@@ -20,9 +20,11 @@ package org.thialfihar.android.apg.helper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.Locale;
import java.util.Vector;
import org.spongycastle.bcpg.ArmoredOutputStream;
@@ -38,24 +40,17 @@ import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
import org.spongycastle.openpgp.PGPUtil;
import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.R;
+import org.thialfihar.android.apg.provider.ApgContract.KeyRings;
import org.thialfihar.android.apg.provider.ProviderHelper;
import org.thialfihar.android.apg.util.IterableIterator;
import org.thialfihar.android.apg.util.Log;
import android.content.Context;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.net.Uri;
public class PGPHelper {
- public static PGPKeyRing decodeKeyRing(InputStream is) throws IOException {
- InputStream in = PGPUtil.getDecoderStream(is);
- PGPObjectFactory objectFactory = new PGPObjectFactory(in);
- Object obj = objectFactory.nextObject();
-
- if (obj instanceof PGPKeyRing) {
- return (PGPKeyRing) obj;
- }
-
- return null;
- }
public static Date getCreationDate(PGPPublicKey key) {
return key.getCreationTime();
@@ -191,7 +186,8 @@ public class PGPHelper {
}
public static PGPPublicKey getEncryptPublicKey(Context context, long masterKeyId) {
- PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(context, masterKeyId);
+ PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(context,
+ masterKeyId);
if (keyRing == null) {
Log.e(Constants.TAG, "keyRing is null!");
return null;
@@ -205,7 +201,8 @@ public class PGPHelper {
}
public static PGPSecretKey getSigningKey(Context context, long masterKeyId) {
- PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context, masterKeyId);
+ PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context,
+ masterKeyId);
if (keyRing == null) {
return null;
}
@@ -374,7 +371,7 @@ public class PGPHelper {
} else if (i != 0 && i % 2 == 0) {
fingerPrint += " ";
}
- String chunk = Integer.toHexString((fp[i] + 256) % 256).toUpperCase();
+ String chunk = Integer.toHexString((fp[i] + 256) % 256).toUpperCase(Locale.US);
while (chunk.length() < 2) {
chunk = "0" + chunk;
}
@@ -385,37 +382,6 @@ public class PGPHelper {
}
- public static String getPubkeyAsArmoredString(Context context, long keyId) {
- PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, keyId);
- // if it is no public key get it from your own keys...
- if (key == null) {
- PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId);
- if (secretKey == null) {
- Log.e(Constants.TAG, "Key could not be found!");
- return null;
- }
- key = secretKey.getPublicKey();
- }
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ArmoredOutputStream aos = new ArmoredOutputStream(bos);
- aos.setHeader("Version", PGPMain.getFullVersion(context));
-
- String armouredKey = null;
- try {
- aos.write(key.getEncoded());
- aos.close();
-
- armouredKey = bos.toString("UTF-8");
- } catch (IOException e) {
- Log.e(Constants.TAG, "Problems while encoding key as armored string", e);
- }
-
- Log.d(Constants.TAG, "key:" + armouredKey);
-
- return armouredKey;
- }
-
public static String getFingerPrint(Context context, long keyId) {
PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, keyId);
// if it is no public key get it from your own keys...
@@ -432,7 +398,7 @@ public class PGPHelper {
}
public static String getSmallFingerPrint(long keyId) {
- String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase();
+ String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US);
while (fingerPrint.length() < 8) {
fingerPrint = "0" + fingerPrint;
}
@@ -449,4 +415,5 @@ public class PGPHelper {
String s1 = data.substring(0, len - 8);
return (Long.parseLong(s1, 16) << 32) | Long.parseLong(s2, 16);
}
+
}
diff --git a/APG/src/org/thialfihar/android/apg/helper/PGPMain.java b/APG/src/org/thialfihar/android/apg/helper/PGPMain.java
index bf76901a1..cb4326f88 100644
--- a/APG/src/org/thialfihar/android/apg/helper/PGPMain.java
+++ b/APG/src/org/thialfihar/android/apg/helper/PGPMain.java
@@ -564,7 +564,7 @@ public class PGPMain {
int oldKeys = 0;
int badKeys = 0;
try {
- PGPKeyRing keyring = PGPHelper.decodeKeyRing(bufferedInput);
+ PGPKeyRing keyring = PGPConversionHelper.decodeKeyRing(bufferedInput);
while (keyring != null) {
int status = Integer.MIN_VALUE; // out of bounds value
@@ -592,7 +592,7 @@ public class PGPMain {
// TODO: needed?
// obj = objectFactory.nextObject();
- keyring = PGPHelper.decodeKeyRing(bufferedInput);
+ keyring = PGPConversionHelper.decodeKeyRing(bufferedInput);
}
} catch (EOFException e) {
// nothing to do, we are done
@@ -652,6 +652,42 @@ public class PGPMain {
return returnData;
}
+ public static Bundle getKeyRings(Context context, long[] masterKeyIds,
+ OutputStream outStream, ProgressDialogUpdater progress) throws ApgGeneralException,
+ FileNotFoundException, PGPException, IOException {
+ Bundle returnData = new Bundle();
+
+ ArmoredOutputStream out = new ArmoredOutputStream(outStream);
+ out.setHeader("Version", getFullVersion(context));
+
+ int numKeys = 0;
+ for (int i = 0; i < masterKeyIds.length; ++i) {
+ updateProgress(progress, i * 100 / masterKeyIds.length, 100);
+
+ // try to get it as a PGPPublicKeyRing, if that fails try to get it as a SecretKeyRing
+ PGPPublicKeyRing publicKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(context,
+ masterKeyIds[i]);
+ if (publicKeyRing != null) {
+ publicKeyRing.encode(out);
+ } else {
+ PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByRowId(context,
+ masterKeyIds[i]);
+ if (secretKeyRing != null) {
+ secretKeyRing.encode(out);
+ } else {
+ continue;
+ }
+ }
+ ++numKeys;
+ }
+ out.close();
+ returnData.putInt(ApgIntentService.RESULT_EXPORT, numKeys);
+
+ updateProgress(progress, R.string.progress_done, 100, 100);
+
+ return returnData;
+ }
+
/**
* Encrypt and Sign data
*
diff --git a/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java b/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java
index 611b647e6..125b557a3 100644
--- a/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java
+++ b/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java
@@ -16,10 +16,12 @@
package org.thialfihar.android.apg.provider;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
+import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
@@ -28,6 +30,7 @@ import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.helper.PGPConversionHelper;
import org.thialfihar.android.apg.helper.PGPHelper;
+import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.provider.ApgContract.KeyRings;
import org.thialfihar.android.apg.provider.ApgContract.UserIds;
import org.thialfihar.android.apg.provider.ApgContract.Keys;
@@ -40,6 +43,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
+import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.RemoteException;
@@ -469,16 +473,38 @@ public class ProviderHelper {
cr.delete(KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)), null, null);
}
+ /**
+ * Get master key id of keyring by its row id
+ *
+ * @param context
+ * @param keyRingRowId
+ * @return
+ */
public static long getPublicMasterKeyId(Context context, long keyRingRowId) {
Uri queryUri = KeyRings.buildPublicKeyRingsUri(String.valueOf(keyRingRowId));
return getMasterKeyId(context, queryUri, keyRingRowId);
}
+ /**
+ * Get master key id of keyring by its row id
+ *
+ * @param context
+ * @param keyRingRowId
+ * @return
+ */
public static long getSecretMasterKeyId(Context context, long keyRingRowId) {
Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId));
return getMasterKeyId(context, queryUri, keyRingRowId);
}
+ /**
+ * Private helper method to get master key id of keyring by its row id
+ *
+ * @param context
+ * @param queryUri
+ * @param keyRingRowId
+ * @return
+ */
private static long getMasterKeyId(Context context, Uri queryUri, long keyRingRowId) {
String[] projection = new String[] { KeyRings.MASTER_KEY_ID };
@@ -499,4 +525,135 @@ public class ProviderHelper {
return masterKeyId;
}
+ public static ArrayList getPublicKeyRingsAsArmoredString(Context context,
+ long[] masterKeyIds) {
+ return getKeyRingsAsArmoredString(context, KeyRings.buildPublicKeyRingsUri(), masterKeyIds);
+ }
+
+ public static ArrayList getSecretKeyRingsAsArmoredString(Context context,
+ long[] masterKeyIds) {
+ return getKeyRingsAsArmoredString(context, KeyRings.buildSecretKeyRingsUri(), masterKeyIds);
+ }
+
+ private static ArrayList getKeyRingsAsArmoredString(Context context, Uri uri,
+ long[] masterKeyIds) {
+ ArrayList output = new ArrayList();
+
+ if (masterKeyIds != null && masterKeyIds.length > 0) {
+
+ Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, uri, masterKeyIds);
+
+ if (cursor != null) {
+ int masterIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID);
+ int dataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA);
+ if (cursor.moveToFirst()) {
+ do {
+ Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol));
+
+ // get actual keyring data blob and write it to ByteArrayOutputStream
+ try {
+ Object keyRing = null;
+ byte[] data = cursor.getBlob(dataCol);
+ if (data != null) {
+ keyRing = PGPConversionHelper.BytesToPGPKeyRing(data);
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ArmoredOutputStream aos = new ArmoredOutputStream(bos);
+ aos.setHeader("Version", PGPMain.getFullVersion(context));
+
+ if (keyRing instanceof PGPSecretKeyRing) {
+ aos.write(((PGPSecretKeyRing) keyRing).getEncoded());
+ } else if (keyRing instanceof PGPPublicKeyRing) {
+ aos.write(((PGPPublicKeyRing) keyRing).getEncoded());
+ }
+ aos.close();
+
+ String armoredKey = bos.toString("UTF-8");
+
+ Log.d(Constants.TAG, "armouredKey:" + armoredKey);
+
+ output.add(armoredKey);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IOException", e);
+ }
+ } while (cursor.moveToNext());
+ }
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+
+ } else {
+ Log.e(Constants.TAG, "No master keys given!");
+ }
+
+ return output;
+ }
+
+ public static byte[] getPublicKeyRingsAsByteArray(Context context, long[] masterKeyIds) {
+ return getKeyRingsAsByteArray(context, KeyRings.buildPublicKeyRingsUri(), masterKeyIds);
+ }
+
+ public static byte[] getSecretKeyRingsAsByteArray(Context context, long[] masterKeyIds) {
+ return getKeyRingsAsByteArray(context, KeyRings.buildSecretKeyRingsUri(), masterKeyIds);
+ }
+
+ private static byte[] getKeyRingsAsByteArray(Context context, Uri uri, long[] masterKeyIds) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ if (masterKeyIds != null && masterKeyIds.length > 0) {
+
+ Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, uri, masterKeyIds);
+
+ if (cursor != null) {
+ int masterIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID);
+ int dataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA);
+ if (cursor.moveToFirst()) {
+ do {
+ Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol));
+
+ // get actual keyring data blob and write it to ByteArrayOutputStream
+ try {
+ bos.write(cursor.getBlob(dataCol));
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IOException", e);
+ }
+ } while (cursor.moveToNext());
+ }
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+
+ } else {
+ Log.e(Constants.TAG, "No master keys given!");
+ }
+
+ return bos.toByteArray();
+ }
+
+ private static Cursor getCursorWithSelectedKeyringMasterKeyIds(Context context, Uri baseUri,
+ long[] masterKeyIds) {
+ Cursor cursor = null;
+ if (masterKeyIds != null && masterKeyIds.length > 0) {
+
+ String inMasterKeyList = KeyRings.MASTER_KEY_ID + " IN (";
+ for (int i = 0; i < masterKeyIds.length; ++i) {
+ if (i != 0) {
+ inMasterKeyList += ", ";
+ }
+ inMasterKeyList += DatabaseUtils.sqlEscapeString("" + masterKeyIds[i]);
+ }
+ inMasterKeyList += ")";
+
+ cursor = context.getContentResolver().query(baseUri,
+ new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.KEY_RING_DATA },
+ inMasterKeyList, null, null);
+ }
+
+ return cursor;
+ }
}
diff --git a/APG/src/org/thialfihar/android/apg/service/ApgService.java b/APG/src/org/thialfihar/android/apg/service/ApgApiService.java
similarity index 86%
rename from APG/src/org/thialfihar/android/apg/service/ApgService.java
rename to APG/src/org/thialfihar/android/apg/service/ApgApiService.java
index a94887ba4..81d665e13 100644
--- a/APG/src/org/thialfihar/android/apg/service/ApgService.java
+++ b/APG/src/org/thialfihar/android/apg/service/ApgApiService.java
@@ -31,6 +31,9 @@ import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.helper.PGPMain.ApgGeneralException;
+import org.thialfihar.android.apg.service.handler.IApgDecryptHandler;
+import org.thialfihar.android.apg.service.handler.IApgEncryptHandler;
+import org.thialfihar.android.apg.service.handler.IApgGetDecryptionKeyIdHandler;
import org.thialfihar.android.apg.util.InputData;
import org.thialfihar.android.apg.util.Log;
@@ -47,20 +50,20 @@ import android.os.RemoteException;
* - is this service thread safe? Probably not!
*
*/
-public class ApgService extends Service {
+public class ApgApiService extends Service {
Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
- Log.d(Constants.TAG, "ApgService, onCreate()");
+ Log.d(Constants.TAG, "ApgApiService, onCreate()");
}
@Override
public void onDestroy() {
super.onDestroy();
- Log.d(Constants.TAG, "ApgService, onDestroy()");
+ Log.d(Constants.TAG, "ApgApiService, onDestroy()");
}
@Override
@@ -68,19 +71,19 @@ public class ApgService extends Service {
return mBinder;
}
- private static void writeToOutputStream(InputStream is, OutputStream os) throws IOException {
- byte[] buffer = new byte[8];
- int len = 0;
- while ((len = is.read(buffer)) != -1) {
- os.write(buffer, 0, len);
- }
- }
+ // private static void writeToOutputStream(InputStream is, OutputStream os) throws IOException {
+ // byte[] buffer = new byte[8];
+ // int len = 0;
+ // while ((len = is.read(buffer)) != -1) {
+ // os.write(buffer, 0, len);
+ // }
+ // }
private void encryptAndSignImplementation(byte[] inputBytes, String inputUri,
boolean useAsciiArmor, int compression, long[] encryptionKeyIds,
String encryptionPassphrase, int symmetricEncryptionAlgorithm, long signatureKeyId,
int signatureHashAlgorithm, boolean signatureForceV3, String signaturePassphrase,
- IApgEncryptSignHandler handler) throws RemoteException {
+ IApgEncryptHandler handler) throws RemoteException {
try {
// TODO use inputUri
@@ -128,7 +131,7 @@ public class ApgService extends Service {
byte[] outputBytes = ((ByteArrayOutputStream) output).toByteArray();
// return over handler on client side
- handler.onSuccessEncrypt(outputBytes, null);
+ handler.onSuccess(outputBytes, null);
} catch (Exception e) {
Log.e(Constants.TAG, "ApgService, Exception!", e);
@@ -141,7 +144,7 @@ public class ApgService extends Service {
}
private void decryptAndVerifyImplementation(byte[] inputBytes, String inputUri,
- String passphrase, boolean assumeSymmetric, IApgDecryptVerifyHandler handler)
+ String passphrase, boolean assumeSymmetric, IApgDecryptHandler handler)
throws RemoteException {
try {
@@ -170,7 +173,7 @@ public class ApgService extends Service {
.getBoolean(ApgIntentService.RESULT_SIGNATURE_UNKNOWN);
// return over handler on client side
- handler.onSuccessDecrypt(outputBytes, null, signature, signatureKeyId, signatureUserId,
+ handler.onSuccess(outputBytes, null, signature, signatureKeyId, signatureUserId,
signatureSuccess, signatureUnknown);
} catch (Exception e) {
Log.e(Constants.TAG, "ApgService, Exception!", e);
@@ -184,7 +187,7 @@ public class ApgService extends Service {
}
private void getDecryptionKeyImplementation(byte[] inputBytes, String inputUri,
- IApgHelperHandler handler) {
+ IApgGetDecryptionKeyIdHandler handler) {
// TODO: implement inputUri
@@ -195,20 +198,20 @@ public class ApgService extends Service {
boolean symmetric;
try {
- secretKeyId = PGPMain.getDecryptionKeyId(ApgService.this, inputStream);
+ secretKeyId = PGPMain.getDecryptionKeyId(ApgApiService.this, inputStream);
if (secretKeyId == Id.key.none) {
throw new ApgGeneralException(getString(R.string.error_noSecretKeyFound));
}
symmetric = false;
} catch (PGPMain.NoAsymmetricEncryptionException e) {
secretKeyId = Id.key.symmetric;
- if (!PGPMain.hasSymmetricEncryption(ApgService.this, inputStream)) {
+ if (!PGPMain.hasSymmetricEncryption(ApgApiService.this, inputStream)) {
throw new ApgGeneralException(getString(R.string.error_noKnownEncryptionFound));
}
symmetric = true;
}
- handler.onSuccessGetDecryptionKey(secretKeyId, symmetric);
+ handler.onSuccess(secretKeyId, symmetric);
} catch (Exception e) {
Log.e(Constants.TAG, "ApgService, Exception!", e);
@@ -227,12 +230,12 @@ public class ApgService extends Service {
*
* The real PGP code is located in PGPMain.
*/
- private final IApgService.Stub mBinder = new IApgService.Stub() {
+ private final IApgApiService.Stub mBinder = new IApgApiService.Stub() {
@Override
public void encryptAsymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor,
int compression, long[] encryptionKeyIds, int symmetricEncryptionAlgorithm,
- IApgEncryptSignHandler handler) throws RemoteException {
+ IApgEncryptHandler handler) throws RemoteException {
encryptAndSignImplementation(inputBytes, inputUri, useAsciiArmor, compression,
encryptionKeyIds, null, symmetricEncryptionAlgorithm, Id.key.none, 0, false,
@@ -242,7 +245,7 @@ public class ApgService extends Service {
@Override
public void encryptSymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor,
int compression, String encryptionPassphrase, int symmetricEncryptionAlgorithm,
- IApgEncryptSignHandler handler) throws RemoteException {
+ IApgEncryptHandler handler) throws RemoteException {
encryptAndSignImplementation(inputBytes, inputUri, useAsciiArmor, compression, null,
encryptionPassphrase, symmetricEncryptionAlgorithm, Id.key.none, 0, false,
@@ -253,7 +256,7 @@ public class ApgService extends Service {
public void encryptAndSignAsymmetric(byte[] inputBytes, String inputUri,
boolean useAsciiArmor, int compression, long[] encryptionKeyIds,
int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm,
- boolean signatureForceV3, String signaturePassphrase, IApgEncryptSignHandler handler)
+ boolean signatureForceV3, String signaturePassphrase, IApgEncryptHandler handler)
throws RemoteException {
encryptAndSignImplementation(inputBytes, inputUri, useAsciiArmor, compression,
@@ -265,7 +268,7 @@ public class ApgService extends Service {
public void encryptAndSignSymmetric(byte[] inputBytes, String inputUri,
boolean useAsciiArmor, int compression, String encryptionPassphrase,
int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm,
- boolean signatureForceV3, String signaturePassphrase, IApgEncryptSignHandler handler)
+ boolean signatureForceV3, String signaturePassphrase, IApgEncryptHandler handler)
throws RemoteException {
encryptAndSignImplementation(inputBytes, inputUri, useAsciiArmor, compression, null,
@@ -275,23 +278,22 @@ public class ApgService extends Service {
@Override
public void decryptAndVerifyAsymmetric(byte[] inputBytes, String inputUri,
- String keyPassphrase, IApgDecryptVerifyHandler handler) throws RemoteException {
+ String keyPassphrase, IApgDecryptHandler handler) throws RemoteException {
decryptAndVerifyImplementation(inputBytes, inputUri, keyPassphrase, false, handler);
}
@Override
public void decryptAndVerifySymmetric(byte[] inputBytes, String inputUri,
- String encryptionPassphrase, IApgDecryptVerifyHandler handler)
- throws RemoteException {
+ String encryptionPassphrase, IApgDecryptHandler handler) throws RemoteException {
decryptAndVerifyImplementation(inputBytes, inputUri, encryptionPassphrase, true,
handler);
}
@Override
- public void getDecryptionKey(byte[] inputBytes, String inputUri, IApgHelperHandler handler)
- throws RemoteException {
+ public void getDecryptionKeyId(byte[] inputBytes, String inputUri,
+ IApgGetDecryptionKeyIdHandler handler) throws RemoteException {
getDecryptionKeyImplementation(inputBytes, inputUri, handler);
}
diff --git a/APG/src/org/thialfihar/android/apg/service/ApgKeyService.java b/APG/src/org/thialfihar/android/apg/service/ApgKeyService.java
new file mode 100644
index 000000000..32dd84675
--- /dev/null
+++ b/APG/src/org/thialfihar/android/apg/service/ApgKeyService.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service;
+
+import java.util.ArrayList;
+
+import org.thialfihar.android.apg.Constants;
+import org.thialfihar.android.apg.provider.ProviderHelper;
+import org.thialfihar.android.apg.service.handler.IApgGetKeyringsHandler;
+import org.thialfihar.android.apg.util.Log;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+/**
+ * TODO:
+ *
+ * - is this service thread safe? Probably not!
+ *
+ */
+public class ApgKeyService extends Service {
+ Context mContext;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mContext = this;
+ Log.d(Constants.TAG, "ApgKeyService, onCreate()");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.d(Constants.TAG, "ApgKeyService, onDestroy()");
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ /**
+ * This is the implementation of the interface IApgService. All methods are oneway, meaning
+ * asynchronous and return to the client using IApgHandler.
+ *
+ * The real PGP code is located in PGPMain.
+ */
+ private final IApgKeyService.Stub mBinder = new IApgKeyService.Stub() {
+
+ @Override
+ public void getPublicKeyRings(long[] masterKeyIds, boolean asAsciiArmoredStringArray,
+ IApgGetKeyringsHandler handler) throws RemoteException {
+ if (asAsciiArmoredStringArray) {
+ ArrayList output = ProviderHelper.getPublicKeyRingsAsArmoredString(
+ mContext, masterKeyIds);
+
+ handler.onSuccess(null, output);
+ } else {
+ byte[] outputBytes = ProviderHelper.getPublicKeyRingsAsByteArray(mContext,
+ masterKeyIds);
+ handler.onSuccess(outputBytes, null);
+ }
+ }
+
+ @Override
+ public void getSecretKeyRings(long[] masterKeyIds, boolean asAsciiArmoredStringArray,
+ IApgGetKeyringsHandler handler) throws RemoteException {
+ if (asAsciiArmoredStringArray) {
+ ArrayList output = ProviderHelper.getSecretKeyRingsAsArmoredString(
+ mContext, masterKeyIds);
+
+ handler.onSuccess(null, output);
+ } else {
+ byte[] outputBytes = ProviderHelper.getSecretKeyRingsAsByteArray(mContext,
+ masterKeyIds);
+ handler.onSuccess(outputBytes, null);
+ }
+
+ }
+
+ };
+
+ /**
+ * As we can not throw an exception through Android RPC, we assign identifiers to the exception
+ * types.
+ *
+ * @param e
+ * @return
+ */
+ // private int getExceptionId(Exception e) {
+ // if (e instanceof NoSuchProviderException) {
+ // return 0;
+ // } else if (e instanceof NoSuchAlgorithmException) {
+ // return 1;
+ // } else if (e instanceof SignatureException) {
+ // return 2;
+ // } else if (e instanceof IOException) {
+ // return 3;
+ // } else if (e instanceof ApgGeneralException) {
+ // return 4;
+ // } else if (e instanceof PGPException) {
+ // return 5;
+ // } else {
+ // return -1;
+ // }
+ // }
+
+}
diff --git a/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgService.aidl b/APG/src/org/thialfihar/android/apg/service/IApgApiService.aidl
similarity index 79%
rename from APG-API-Lib/src/org/thialfihar/android/apg/service/IApgService.aidl
rename to APG/src/org/thialfihar/android/apg/service/IApgApiService.aidl
index 71c6a9e42..277ce6722 100644
--- a/APG-API-Lib/src/org/thialfihar/android/apg/service/IApgService.aidl
+++ b/APG/src/org/thialfihar/android/apg/service/IApgApiService.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.thialfihar.android.apg.service;
-import org.thialfihar.android.apg.service.IApgEncryptDecryptHandler;
-import org.thialfihar.android.apg.service.IApgSignVerifyHandler;
-import org.thialfihar.android.apg.service.IApgHelperHandler;
+import org.thialfihar.android.apg.service.handler.IApgEncryptHandler;
+import org.thialfihar.android.apg.service.handler.IApgDecryptHandler;
+import org.thialfihar.android.apg.service.handler.IApgGetDecryptionKeyIdHandler;
/**
* All methods are oneway, which means they are asynchronous and non-blocking.
* Results are returned into given Handler, which has to be implemented on client side.
*/
-interface IApgService {
+interface IApgApiService {
/**
* Encrypt
@@ -34,7 +50,7 @@ interface IApgService {
*/
oneway void encryptAsymmetric(in byte[] inputBytes, in String inputUri, in boolean useAsciiArmor,
in int compression, in long[] encryptionKeyIds, in int symmetricEncryptionAlgorithm,
- in IApgEncryptDecryptHandler handler);
+ in IApgEncryptHandler handler);
/**
* Same as encryptAsymmetric but using a passphrase for symmetric encryption
@@ -44,7 +60,7 @@ interface IApgService {
*/
oneway void encryptSymmetric(in byte[] inputBytes, in String inputUri, in boolean useAsciiArmor,
in int compression, in String encryptionPassphrase, in int symmetricEncryptionAlgorithm,
- in IApgEncryptDecryptHandler handler);
+ in IApgEncryptHandler handler);
/**
* Encrypt and sign
@@ -81,7 +97,7 @@ interface IApgService {
in boolean useAsciiArmor, in int compression, in long[] encryptionKeyIds,
in int symmetricEncryptionAlgorithm, in long signatureKeyId, in int signatureHashAlgorithm,
in boolean signatureForceV3, in String signaturePassphrase,
- in IApgEncryptDecryptHandler handler);
+ in IApgEncryptHandler handler);
/**
* Same as encryptAndSignAsymmetric but using a passphrase for symmetric encryption
@@ -93,7 +109,7 @@ interface IApgService {
in boolean useAsciiArmor, in int compression, in String encryptionPassphrase,
in int symmetricEncryptionAlgorithm, in long signatureKeyId, in int signatureHashAlgorithm,
in boolean signatureForceV3, in String signaturePassphrase,
- in IApgEncryptDecryptHandler handler);
+ in IApgEncryptHandler handler);
/**
* Decrypts and verifies given input bytes. If no signature is present this method
@@ -109,7 +125,7 @@ interface IApgService {
* Handler where to return results to after successful encryption
*/
oneway void decryptAndVerifyAsymmetric(in byte[] inputBytes, in String inputUri,
- in String keyPassphrase, in IApgEncryptDecryptHandler handler);
+ in String keyPassphrase, in IApgDecryptHandler handler);
/**
* Same as decryptAndVerifyAsymmetric but for symmetric decryption.
@@ -118,13 +134,13 @@ interface IApgService {
* Passphrase to decrypt
*/
oneway void decryptAndVerifySymmetric(in byte[] inputBytes, in String inputUri,
- in String encryptionPassphrase, in IApgEncryptDecryptHandler handler);
+ in String encryptionPassphrase, in IApgDecryptHandler handler);
/**
*
*/
- oneway void getDecryptionKey(in byte[] inputBytes, in String inputUri,
- in IApgHelperHandler handler);
+ oneway void getDecryptionKeyId(in byte[] inputBytes, in String inputUri,
+ in IApgGetDecryptionKeyIdHandler handler);
}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/IApgKeyService.aidl b/APG/src/org/thialfihar/android/apg/service/IApgKeyService.aidl
new file mode 100644
index 000000000..12ecddc17
--- /dev/null
+++ b/APG/src/org/thialfihar/android/apg/service/IApgKeyService.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service;
+
+import org.thialfihar.android.apg.service.handler.IApgGetKeyringsHandler;
+
+/**
+ * All methods are oneway, which means they are asynchronous and non-blocking.
+ * Results are returned into given Handler, which has to be implemented on client side.
+ */
+interface IApgKeyService {
+
+ oneway void getPublicKeyRings(in long[] masterKeyIds, in boolean asAsciiArmoredStringArray,
+ in IApgGetKeyringsHandler handler);
+
+ oneway void getSecretKeyRings(in long[] masterKeyIds, in boolean asAsciiArmoredStringArray,
+ in IApgGetKeyringsHandler handler);
+}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/handler/IApgDecryptHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgDecryptHandler.aidl
new file mode 100644
index 000000000..feb56bce6
--- /dev/null
+++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgDecryptHandler.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgDecryptHandler {
+
+ oneway void onSuccess(in byte[] outputBytes, in String outputUri, in boolean signature,
+ in long signatureKeyId, in String signatureUserId, in boolean signatureSuccess,
+ in boolean signatureUnknown);
+
+
+ oneway void onException(in int exceptionNumber, in String message);
+}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/handler/IApgEncryptHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgEncryptHandler.aidl
new file mode 100644
index 000000000..be0317715
--- /dev/null
+++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgEncryptHandler.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgEncryptHandler {
+ /**
+ * Either output or streamUri is given. One of them is null
+ *
+ */
+ oneway void onSuccess(in byte[] outputBytes, in String outputUri);
+
+
+ oneway void onException(in int exceptionNumber, in String message);
+}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/handler/IApgGetDecryptionKeyIdHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgGetDecryptionKeyIdHandler.aidl
new file mode 100644
index 000000000..020a80b99
--- /dev/null
+++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgGetDecryptionKeyIdHandler.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgGetDecryptionKeyIdHandler {
+
+ oneway void onSuccess(in long secretKeyId, in boolean symmetric);
+
+
+ oneway void onException(in int exceptionNumber, in String message);
+}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/handler/IApgGetKeyringsHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgGetKeyringsHandler.aidl
new file mode 100644
index 000000000..ffa9d0d2d
--- /dev/null
+++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgGetKeyringsHandler.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgGetKeyringsHandler {
+ /**
+ * Either outputBytes or outputString is given. One of them is null
+ *
+ */
+ oneway void onSuccess(in byte[] outputBytes, in List outputString);
+
+
+ oneway void onException(in int exceptionNumber, in String message);
+}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/handler/IApgSignHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgSignHandler.aidl
new file mode 100644
index 000000000..cf91e8bc4
--- /dev/null
+++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgSignHandler.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgSignHandler {
+ /**
+ * Either output or streamUri is given. One of them is null
+ *
+ */
+ oneway void onSuccess(in byte[] outputBytes, in String outputUri);
+
+
+ oneway void onException(in int exceptionNumber, in String message);
+}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/service/handler/IApgVerifyHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgVerifyHandler.aidl
new file mode 100644
index 000000000..6baaec758
--- /dev/null
+++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgVerifyHandler.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg.service.handler;
+
+interface IApgVerifyHandler {
+
+ oneway void onSuccess(in boolean signature, in long signatureKeyId,
+ in String signatureUserId, in boolean signatureSuccess, in boolean signatureUnknown);
+
+
+ oneway void onException(in int exceptionNumber, in String message);
+}
\ No newline at end of file
diff --git a/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java b/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java
index 12a0bb131..0d12f5fe4 100644
--- a/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java
+++ b/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java
@@ -17,9 +17,10 @@
package org.thialfihar.android.apg.ui;
+import java.util.ArrayList;
+
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
-import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.provider.ProviderHelper;
import org.thialfihar.android.apg.provider.ApgContract.KeyRings;
import org.thialfihar.android.apg.provider.ApgContract.UserIds;
@@ -87,25 +88,21 @@ public class KeyListSecretFragment extends KeyListFragment implements
int groupPosition = ExpandableListView.getPackedPositionGroup(expInfo.packedPosition);
long keyRingRowId = getExpandableListAdapter().getGroupId(groupPosition);
+ // get master key id using row id
+ long masterKeyId = ProviderHelper
+ .getSecretMasterKeyId(mKeyListSecretActivity, keyRingRowId);
+
switch (item.getItemId()) {
case Id.menu.edit:
- // TODO: do it better directly with keyRingRowId?
- long masterKeyId = ProviderHelper.getSecretMasterKeyId(mKeyListSecretActivity,
- keyRingRowId);
-
mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId);
- return true;
+ return true;
case Id.menu.share_qr_code:
- // TODO: do it better directly with keyRingRowId?
- long masterKeyId2 = ProviderHelper.getSecretMasterKeyId(mKeyListSecretActivity,
- keyRingRowId);
+ ArrayList keyringArmored = ProviderHelper.getPublicKeyRingsAsArmoredString(
+ mKeyListSecretActivity, new long[] { masterKeyId });
+ new IntentIntegrator(mKeyListSecretActivity).shareText(keyringArmored.get(0));
- String msg = PGPHelper.getPubkeyAsArmoredString(mKeyListSecretActivity, masterKeyId2);
-
- new IntentIntegrator(mKeyListSecretActivity).shareText(msg);
return true;
-
default:
return super.onContextItemSelected(item);
diff --git a/README.md b/README.md
index ec38a7e09..86be161c6 100644
--- a/README.md
+++ b/README.md
@@ -62,11 +62,15 @@ See http://docs.oseems.com/general/application/eclipse/fix-gc-overhead-limit-exc
## Basic goals
-* Never (even with permissions) give out actual PGPSecretKey/PGPSecretKeyRing blobs
* Intents without permissions should only work based on user interaction (e.g. click a button in a dialog)
Android primitives to exchange data: Intent, Intent with return values, Send (also an Intent), Content Provider, AIDL
+## Permission
+
+* ACCESS_API: Encrypt/Sign/Decrypt/Create keys without user interaction (intents, remote service), Read key information (not the actual keys)(content provider)
+* ACCESS_KEYS: get and import actual public and secret keys (remote service)
+
## Intents
### Without permission
@@ -92,16 +96,13 @@ Android primitives to exchange data: Intent, Intent with return values, Send (al
## Content Provider
* The whole content provider requires a permission (only read)
-* Don't give out blobs
+* Don't give out blobs (keys can be accessed by ACCESS_KEYS via remote service)
* Make an internal and external content provider (or pathes with )
* Look at android:grantUriPermissions especially for ApgServiceBlobProvider
* Only give out android:readPermission
-## Remote Service
+## ApgApiService (Remote Service)
+* ACCESS_API
-* The whole service requires the permission ACCESS_API
-
-## Resulting permission
-
-* READ_KEY_DATABASE: Read key information (not the actual keys)(content provider)
-* ACCESS_API: Encrypt/Sign/Decrypt/Create keys without user interaction (intents, remote service)
\ No newline at end of file
+## ApgKeyService (Remote Service)
+* ACCESS_KEYS
\ No newline at end of file