AIDL API changes

This commit is contained in:
Dominik Schürmann 2012-12-14 18:22:03 +01:00
parent 2dcaad3d3b
commit be4e3a10b0
36 changed files with 1113 additions and 275 deletions

View File

@ -4,8 +4,8 @@
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="org.thialfihar.android.apg.permission.READ_KEY_DATABASE" />
<uses-permission android:name="org.thialfihar.android.apg.permission.ACCESS_API" />
<uses-permission android:name="org.thialfihar.android.apg.permission.ACCESS_KEYS" />
<uses-sdk
android:minSdkVersion="7"
@ -29,7 +29,11 @@
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".AidlDemoActivity"
android:label="Aidl Demo"
android:label="Aidl Demo (ACCESS_API permission)"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".AidlDemoActivity2"
android:label="Aidl Demo (ACCESS_KEYS permission)"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".ContentProviderDemoActivity"

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button
android:id="@+id/aidl_demo_select_encryption_key"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="selectEncryptionKeysOnClick"
android:text="Select encryption key(s)" />
<EditText
android:id="@+id/aidl_demo_keyrings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="keyrings output"
android:textAppearance="@android:style/TextAppearance.Small" />
<Button
android:id="@+id/aidl_demo_get_keyrings_strings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="getKeyringsStringsOnClick"
android:text="getKeyrings as Strings" />
<Button
android:id="@+id/aidl_demo_get_keyrings_bytes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="getKeyringsBytesOnClick"
android:text="getKeyringsBytes" />
</LinearLayout>
</ScrollView>

View File

@ -6,15 +6,18 @@
android:key="intent_demo"
android:title="Intent Demo" />
</PreferenceCategory>
<PreferenceCategory android:title="AIDL" >
<Preference
android:key="aidl_demo"
android:title="AIDL Demo" />
</PreferenceCategory>
<PreferenceCategory android:title="Content Provider" >
<Preference
android:key="content_provider_demo"
android:title="Content Provider Demo" />
</PreferenceCategory>
<PreferenceCategory android:title="AIDL" >
<Preference
android:key="aidl_demo"
android:title="AIDL Demo (ACCESS_API permission)" />
<Preference
android:key="aidl_demo2"
android:title="AIDL Demo (ACCESS_KEYS permission)" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -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");
}

View File

@ -0,0 +1,166 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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<String> 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<String> outputStrings)
throws RemoteException {
runOnUiThread(new Runnable() {
public void run() {
if (outputBytes != null) {
keysBytes = outputBytes;
keysStrings = null;
} else if (outputStrings != null) {
keysBytes = null;
keysStrings = (ArrayList<String>) 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);
}
}

View File

@ -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;
}
});
}
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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<String> outputString);
oneway void onException(in int exceptionNumber, in String message);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -60,9 +60,9 @@
android:label="@string/permission_group_label" />
<permission
android:name="org.thialfihar.android.apg.permission.READ_KEY_DATABASE"
android:description="@string/permission_read_key_database_description"
android:label="@string/permission_read_key_database_label"
android:name="org.thialfihar.android.apg.permission.ACCESS_KEYS"
android:description="@string/permission_access_keys_description"
android:label="@string/permission_access_keys_label"
android:permissionGroup="org.thialfihar.android.apg.permission-group.APG"
android:protectionLevel="dangerous" />
<permission
@ -346,13 +346,27 @@
<service android:name=".service.PassphraseCacheService" />
<service android:name=".service.ApgIntentService" />
<service
android:name=".service.ApgService"
android:name="org.thialfihar.android.apg.service.ApgApiService"
android:enabled="true"
android:exported="true"
android:permission="org.thialfihar.android.apg.permission.ACCESS_API"
android:process=":remote" >
android:process=":remoteapi" >
<intent-filter>
<action android:name="org.thialfihar.android.apg.service.IApgService" />
<action android:name="org.thialfihar.android.apg.service.IApgApiService" />
</intent-filter>
<meta-data
android:name="api_version"
android:value="3" />
</service>
<service
android:name="org.thialfihar.android.apg.service.ApgKeyService"
android:enabled="true"
android:exported="true"
android:permission="org.thialfihar.android.apg.permission.ACCESS_KEYS"
android:process=":remotekeys" >
<intent-filter>
<action android:name="org.thialfihar.android.apg.service.IApgKeyService" />
</intent-filter>
<meta-data
@ -367,7 +381,7 @@
<provider
android:name=".provider.ApgProviderExternal"
android:authorities="org.thialfihar.android.apg"
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DATABASE" />
android:readPermission="org.thialfihar.android.apg.permission.ACCESS_API" />
<!-- TODO: authority! -->
<provider

View File

@ -20,16 +20,16 @@
<!-- title_lowerCase: capitalized words, no punctuation -->
<string name="title_mailInbox">Mail Inbox</string>
<string name="title_managePublicKeys">Manage Public Keys</string>
<string name="title_manageSecretKeys">Manage Secret Keys</string>
<string name="title_selectRecipients">Select Public Key</string>
<string name="title_selectSignature">Select Secret Key</string>
<string name="title_managePublicKeys">Manage Public Keyrings</string>
<string name="title_manageSecretKeys">Manage Secret Keyrings</string>
<string name="title_selectRecipients">Select Public Keyring</string>
<string name="title_selectSignature">Select Secret Keyring</string>
<string name="title_encrypt">Encrypt</string>
<string name="title_decrypt">Decrypt</string>
<string name="title_authentication">Passphrase</string>
<string name="title_createKey">Create Key</string>
<string name="title_editKey">Edit Key</string>
<string name="title_createKey">Create Key</string>
<string name="title_editKey">Edit Keyring</string>
<string name="title_createKey">Create Keyring</string>
<string name="title_preferences">Preferences</string>
<string name="title_keyServerPreference">Key Server Preference</string>
<string name="title_changePassPhrase">Change Passphrase</string>
@ -37,16 +37,16 @@
<string name="title_sendEmail">"Send Mail…"</string>
<string name="title_encryptToFile">Encrypt To File</string>
<string name="title_decryptToFile">Decrypt To File</string>
<string name="title_importKeys">Import Keys</string>
<string name="title_exportKey">Export Key</string>
<string name="title_exportKeys">Export Keys</string>
<string name="title_importKeys">Import Keyrings</string>
<string name="title_exportKey">Export Keyring</string>
<string name="title_exportKeys">Export Keyrings</string>
<string name="title_keyNotFound">Key Not Found</string>
<string name="title_help">Getting Started</string>
<string name="title_keyServerQuery">Query Key Server</string>
<string name="title_sendKey">Export to Key Server</string>
<string name="title_unknownSignatureKey">Unknown Signature Key</string>
<string name="title_importFromQRCode">Import from QR Code</string>
<string name="title_signKey">Sign Key</string>
<string name="title_signKey">Sign Keyring</string>
<string name="title_about">About</string>
<string name="title_help">Help</string>
@ -86,21 +86,21 @@
<!-- menu_lowerCase: capitalized words, no punctuation -->
<string name="menu_about">About</string>
<string name="menu_deleteAccount">Delete Account</string>
<string name="menu_managePublicKeys">Manage Public Keys</string>
<string name="menu_manageSecretKeys">Manage Secret Keys</string>
<string name="menu_managePublicKeys">Manage Public Keyrings</string>
<string name="menu_manageSecretKeys">Manage Secret Keyrings</string>
<string name="menu_preferences">Settings</string>
<string name="menu_importKeys">Import Keys</string>
<string name="menu_exportKeys">Export All Keys</string>
<string name="menu_exportKey">Export Key</string>
<string name="menu_deleteKey">Delete Key</string>
<string name="menu_createKey">Create Key</string>
<string name="menu_editKey">Edit Key</string>
<string name="menu_importKeys">Import Keyrings</string>
<string name="menu_exportKeys">Export All Keyrings</string>
<string name="menu_exportKey">Export Keyring</string>
<string name="menu_deleteKey">Delete Keyring</string>
<string name="menu_createKey">Create Keyring</string>
<string name="menu_editKey">Edit Keyring</string>
<string name="menu_search">Search</string>
<string name="menu_help">Help</string>
<string name="menu_keyServer">Key Server</string>
<string name="menu_updateKey">Update from Server</string>
<string name="menu_exportKeyToServer">Export To Server</string>
<string name="menu_share">Share public key with QR Code</string>
<string name="menu_share">Share public keyring with QR Code</string>
<string name="menu_scanQRCode">Scan QR Code</string>
<string name="menu_signKey">Sign Key</string>
@ -135,7 +135,7 @@
<string name="label_name">Name</string>
<string name="label_comment">Comment</string>
<string name="label_email">Email</string>
<string name="label_sendKey">Send Key to Server?</string>
<string name="label_sendKey">Send Keyring to Server?</string>
<string name="noKeysSelected">Select</string>
<string name="oneKeySelected">1 Selected</string>
<string name="nKeysSelected">Selected</string>
@ -201,32 +201,31 @@
<string name="encryptionSuccessful">Successfully encrypted.</string>
<string name="encryptionToClipboardSuccessful">Successfully encrypted to clipboard.</string>
<string name="enterPassPhraseTwice">Enter the passphrase twice.</string>
<string name="selectEncryptionKey">Select at least one encryption key.</string>
<string name="selectEncryptionOrSignatureKey">Select at least one encryption key or a signature key.</string>
<string name="selectEncryptionKey">Select at least one encryption keyring.</string>
<string name="selectEncryptionOrSignatureKey">Select at least one encryption keyring or a signature keyring.</string>
<string name="specifyFileToEncryptTo">Please specify which file to encrypt to.\nWARNING! File will be overwritten if it exists.</string>
<string name="specifyFileToDecryptTo">Please specify which file to decrypt to.\nWARNING! File will be overwritten if it exists.</string>
<string name="specifyFileToImportFrom">Please specify which file to import keys from. (.asc or .gpg)</string>
<string name="specifyFileToImportFrom">Please specify which file to import keyrings from. (.asc or .gpg)</string>
<string name="specifyFileToExportTo">Please specify which file to export to.\nWARNING! File will be overwritten if it exists.</string>
<string name="specifyFileToExportSecretKeysTo">Please specify which file to export to.\nWARNING! You are about to export SECRET keys.\nWARNING! File will be overwritten if it exists.</string>
<string name="keyDeletionConfirmation">Do you really want to delete the key \'%s\'?\nYou can\'t undo this!</string>
<string name="secretKeyDeletionConfirmation">Do you really want to delete the SECRET key \'%s\'?\nYou can\'t undo this!</string>
<string name="keysAddedAndUpdated">Successfully added %1$s key(s) and updated %2$s key(s).</string>
<string name="keysAdded">Successfully added %s key(s).</string>
<string name="keysUpdated">Successfully updated %s key(s).</string>
<string name="noKeysAddedOrUpdated">No keys added or updated.</string>
<string name="keyExported">Successfully exported 1 key.</string>
<string name="keysExported">Successfully exported %s keys.</string>
<string name="noKeysExported">No keys exported.</string>
<string name="specifyFileToExportSecretKeysTo">Please specify which file to export to.\nWARNING! You are about to export SECRET keyrings.\nWARNING! File will be overwritten if it exists.</string>
<string name="keyDeletionConfirmation">Do you really want to delete the keyring \'%s\'?\nYou can\'t undo this!</string>
<string name="secretKeyDeletionConfirmation">Do you really want to delete the SECRET keyring \'%s\'?\nYou can\'t undo this!</string>
<string name="keysAddedAndUpdated">Successfully added %1$s keyring(s) and updated %2$s keyring(s).</string>
<string name="keysAdded">Successfully added %s keyring(s).</string>
<string name="keysUpdated">Successfully updated %s keyring(s).</string>
<string name="noKeysAddedOrUpdated">No keyrings added or updated.</string>
<string name="keyExported">Successfully exported 1 keyring.</string>
<string name="keysExported">Successfully exported %s keyrings.</string>
<string name="noKeysExported">No keyrings exported.</string>
<string name="keyCreationElGamalInfo">Note: only subkeys support ElGamal, and for ElGamal the nearest keysize of 1536, 2048, 3072, 4096, or 8192 will be used.</string>
<string name="keyNotFound">Couldn\'t find key %08X.</string>
<string name="keysFound">Found %s key(s).</string>
<string name="unknownSignatureKeyTouchToLookUp">Unknown signature, touch to look up key.</string>
<string name="keyEditingIsBeta">Key editing is still kind of beta.</string>
<string name="badKeysEncountered">%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.</string>
<string name="lookupUnknownKey">Unknown key %s, do you want to try finding it on a keyserver?</string>
<string name="keySendSuccess">Successfully sent key to server</string>
<string name="keySignSuccess">Successfully signed key</string>
<string name="qrScanImportSuccess">Successfully validated and imported key</string>
<string name="lookupUnknownKey">Unknown keyring %s, do you want to try finding it on a keyserver?</string>
<string name="keySendSuccess">Successfully sent keyring to server</string>
<string name="keySignSuccess">Successfully signed keyring</string>
<string name="qrScanImportSuccess">Successfully validated and imported keyring</string>
<string name="listInformation">Long press one entry in this list to show more options!</string>
<string name="listEmpty">This list is empty!</string>
@ -274,12 +273,11 @@
<string name="progress_certifyingMasterKey">certifying master key…</string>
<string name="progress_buildingMasterKeyRing">building master key ring…</string>
<string name="progress_addingSubKeys">adding sub keys…</string>
<string name="progress_savingKeyRing">saving key ring…</string>
<string name="progress_importingSecretKeys">importing secret keys…</string>
<string name="progress_importingPublicKeys">importing public keys…</string>
<string name="progress_reloadingKeys">reloading keys…</string>
<string name="progress_exportingKey">exporting key…</string>
<string name="progress_exportingKeys">exporting keys…</string>
<string name="progress_savingKeyRing">saving key keyring…</string>
<string name="progress_importingSecretKeys">importing secret keyrings…</string>
<string name="progress_importingPublicKeys">importing public keyrings…</string>
<string name="progress_exportingKey">exporting keyring…</string>
<string name="progress_exportingKeys">exporting keyrings…</string>
<string name="progress_extractingSignatureKey">extracting signature key…</string>
<string name="progress_extractingKey">extracting key…</string>
<string name="progress_preparingStreams">preparing streams…</string>
@ -301,18 +299,18 @@
<!-- permission strings -->
<string name="permission_group_label">APG</string>
<string name="permission_group_description">Permissions to use APG</string>
<string name="permission_read_key_database_label">Read key details of public and secret keys (The keys themselves can NOT be read.)</string>
<string name="permission_read_key_database_description">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.</string>
<string name="permission_access_api_label">Encrypt/Sign/Decrypt/Create keys without user interaction</string>
<string name="permission_access_api_description">Encrypt/Sign/Decrypt/Create keys (by using Intents or Remote Service) without user interaction</string>
<string name="permission_access_api_label">Encrypt/Sign/Decrypt/Create keys without user interaction, Read key details of public and secret keys (The keys themselves can NOT be read.)</string>
<string name="permission_access_api_description">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.</string>
<string name="permission_access_keys_label">Import/Export actual public and secret keys</string>
<string name="permission_access_keys_description">Import and export actual private and public keys directly without user uinteraction.</string>
<!-- action strings -->
<string name="action_encrypt">Encrypt</string>
<string name="action_decrypt">Decrypt</string>
<string name="action_importPublic">Import Public Keys</string>
<string name="action_importSecret">Import Secret Keys</string>
<string name="hint_publicKeys">Search Public Keys</string>
<string name="hint_secretKeys">Search Secret Keys</string>
<string name="action_importPublic">Import Public Keyrings</string>
<string name="action_importSecret">Import Secret Keyrings</string>
<string name="hint_publicKeys">Search Public Keyrings</string>
<string name="hint_secretKeys">Search Secret Keyrings</string>
<string name="filterInfo">Filter: \"%s\"</string>
<!-- misc -->
@ -324,8 +322,8 @@
<!-- Dashboard -->
<string name="dashboard_manage_keys">Manage Public Keys</string>
<string name="dashboard_my_keys">My Secret Keys</string>
<string name="dashboard_manage_keys">Manage Public Keyrings</string>
<string name="dashboard_my_keys">My Secret Keyrings</string>
<string name="dashboard_encrypt">Encrypt</string>
<string name="dashboard_decrypt">Decrypt</string>
<string name="dashboard_help">Help</string>
@ -338,14 +336,14 @@
<string name="help_about_version">Version:</string>
<!-- Import from QR Code -->
<string name="import_from_qr_code_import">Import key (only locally)</string>
<string name="import_from_qr_code_import_sign_and_upload">Import, Sign, and upload key</string>
<string name="import_from_qr_code_scan_again">Scan qr code again</string>
<string name="import_from_qr_code_import">Import keyring (only locally)</string>
<string name="import_from_qr_code_import_sign_and_upload">Import, Sign, and upload keyring</string>
<string name="import_from_qr_code_scan_again">Scan QR Code again</string>
<string name="import_from_qr_code_finish">Finish</string>
<!-- Intent labels -->
<string name="intent_decrypt_file">APG: Decrypt File</string>
<string name="intent_import_key">APG: Import Key</string>
<string name="intent_import_key">APG: Import Keyring</string>
<string name="intent_send_encrypt">APG: Encrypt</string>
<string name="intent_send_decrypt">APG: Decrypt</string>

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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
*

View File

@ -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<String> getPublicKeyRingsAsArmoredString(Context context,
long[] masterKeyIds) {
return getKeyRingsAsArmoredString(context, KeyRings.buildPublicKeyRingsUri(), masterKeyIds);
}
public static ArrayList<String> getSecretKeyRingsAsArmoredString(Context context,
long[] masterKeyIds) {
return getKeyRingsAsArmoredString(context, KeyRings.buildSecretKeyRingsUri(), masterKeyIds);
}
private static ArrayList<String> getKeyRingsAsArmoredString(Context context, Uri uri,
long[] masterKeyIds) {
ArrayList<String> output = new ArrayList<String>();
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;
}
}

View File

@ -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);
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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<String> 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<String> 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;
// }
// }
}

View File

@ -1,14 +1,30 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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<String> outputString);
oneway void onException(in int exceptionNumber, in String message);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
*
* 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);
}

View File

@ -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<String> 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);

View File

@ -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 <path-permission>)
* 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)
## ApgKeyService (Remote Service)
* ACCESS_KEYS