diff options
author | Dominik <dominik@dominikschuermann.de> | 2012-04-11 19:29:27 +0200 |
---|---|---|
committer | Dominik <dominik@dominikschuermann.de> | 2012-06-13 19:28:21 +0300 |
commit | 2f58c3d86b29c9539d5a0d20b160ac175bb00381 (patch) | |
tree | eaad5880bbd0cb1156b197cb19596a0e60c2f868 /org_apg_integration_lib/src | |
parent | e092016518f8ab7413095ffed140a732c7f751a6 (diff) | |
download | open-keychain-2f58c3d86b29c9539d5a0d20b160ac175bb00381.tar.gz open-keychain-2f58c3d86b29c9539d5a0d20b160ac175bb00381.tar.bz2 open-keychain-2f58c3d86b29c9539d5a0d20b160ac175bb00381.zip |
integration lib and demo
Diffstat (limited to 'org_apg_integration_lib/src')
4 files changed, 640 insertions, 0 deletions
diff --git a/org_apg_integration_lib/src/org/apg/integration/ApgData.java b/org_apg_integration_lib/src/org/apg/integration/ApgData.java new file mode 100644 index 000000000..759e3ca12 --- /dev/null +++ b/org_apg_integration_lib/src/org/apg/integration/ApgData.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2010-2011 K-9 Mail Contributors + * 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.apg.integration; + +import java.io.Serializable; +import java.util.Arrays; + +public class ApgData implements Serializable { + private static final long serialVersionUID = 6314045536270848410L; + protected long mEncryptionKeyIds[] = null; + protected long mSignatureKeyId = 0; + protected String mSignatureUserId = null; + protected boolean mSignatureSuccess = false; + protected boolean mSignatureUnknown = false; + protected String mDecryptedData = null; + protected String mEncryptedData = null; + + public void setSignatureKeyId(long keyId) { + mSignatureKeyId = keyId; + } + + public long getSignatureKeyId() { + return mSignatureKeyId; + } + + public void setEncryptionKeys(long keyIds[]) { + mEncryptionKeyIds = keyIds; + } + + public long[] getEncryptionKeys() { + return mEncryptionKeyIds; + } + + public boolean hasSignatureKey() { + return mSignatureKeyId != 0; + } + + public boolean hasEncryptionKeys() { + return (mEncryptionKeyIds != null) && (mEncryptionKeyIds.length > 0); + } + + public String getEncryptedData() { + return mEncryptedData; + } + + public void setEncryptedData(String data) { + mEncryptedData = data; + } + + public String getDecryptedData() { + return mDecryptedData; + } + + public void setDecryptedData(String data) { + mDecryptedData = data; + } + + public void setSignatureUserId(String userId) { + mSignatureUserId = userId; + } + + public String getSignatureUserId() { + return mSignatureUserId; + } + + public boolean getSignatureSuccess() { + return mSignatureSuccess; + } + + public void setSignatureSuccess(boolean success) { + mSignatureSuccess = success; + } + + public boolean getSignatureUnknown() { + return mSignatureUnknown; + } + + public void setSignatureUnknown(boolean unknown) { + mSignatureUnknown = unknown; + } + + @Override + public String toString() { + String output = "mEncryptionKeyIds: " + Arrays.toString(mEncryptionKeyIds) + + "\nmSignatureKeyId: " + mSignatureKeyId + "\nmSignatureUserId: " + + mSignatureUserId + "\nmSignatureSuccess: " + mSignatureSuccess + + "\nmSignatureUnknown: " + mSignatureUnknown + "\nmDecryptedData: " + + mDecryptedData + "\nmEncryptedData: " + mEncryptedData; + + return output; + } +}
\ No newline at end of file diff --git a/org_apg_integration_lib/src/org/apg/integration/ApgIntentHelper.java b/org_apg_integration_lib/src/org/apg/integration/ApgIntentHelper.java new file mode 100644 index 000000000..506ec7a5c --- /dev/null +++ b/org_apg_integration_lib/src/org/apg/integration/ApgIntentHelper.java @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2010-2011 K-9 Mail Contributors + * 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.apg.integration; + +import java.util.ArrayList; +import java.util.List; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.ContentUris; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.widget.Toast; + +public class ApgIntentHelper { + private Activity activity; + + public ApgIntentHelper(Activity activity) { + this.activity = activity; + } + + /** + * Select the signature key. + * + * @param activity + * @param pgpData + * @return success or failure + */ + public boolean selectSecretKey() { + Intent intent = new Intent(Constants.Intent.SELECT_SECRET_KEY); + intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION); + try { + activity.startActivityForResult(intent, Constants.SELECT_SECRET_KEY); + return true; + } catch (ActivityNotFoundException e) { + activityNotFound(); + return false; + } + } + + /** + * Start the encrypt activity. + * + * @param activity + * @param data + * @param pgpData + * @return success or failure + */ + public boolean encrypt(String data, long[] encryptionKeyIds, long signatureKeyId) { + Intent intent = new Intent(Constants.Intent.ENCRYPT_AND_RETURN); + intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION); + intent.setType("text/plain"); + intent.putExtra(Constants.EXTRA_TEXT, data); + intent.putExtra(Constants.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds); + intent.putExtra(Constants.EXTRA_SIGNATURE_KEY_ID, signatureKeyId); + try { + activity.startActivityForResult(intent, Constants.ENCRYPT_MESSAGE); + return true; + } catch (ActivityNotFoundException e) { + activityNotFound(); + return false; + } + } + + /** + * Start the decrypt activity. + * + * @param activity + * @param data + * @param pgpData + * @return success or failure + */ + public boolean decrypt(String data) { + Intent intent = new Intent(Constants.Intent.DECRYPT_AND_RETURN); + intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION); + intent.setType("text/plain"); + if (data == null) { + return false; + } + try { + intent.putExtra(Constants.EXTRA_TEXT, data); + activity.startActivityForResult(intent, Constants.DECRYPT_MESSAGE); + return true; + } catch (ActivityNotFoundException e) { + activityNotFound(); + return false; + } + } + + /** + * Handle the activity results that concern us. + * + * @param requestCode + * @param resultCode + * @param data + * @return handled or not + */ + public boolean onActivityResult(int requestCode, int resultCode, Intent data, ApgData apgData) { + + switch (requestCode) { + case Constants.SELECT_SECRET_KEY: + if (resultCode != Activity.RESULT_OK || data == null) { + break; + } + apgData.setSignatureKeyId(data.getLongExtra(Constants.EXTRA_KEY_ID, 0)); + apgData.setSignatureUserId(data.getStringExtra(Constants.EXTRA_USER_ID)); + break; + + case Constants.SELECT_PUBLIC_KEYS: + if (resultCode != Activity.RESULT_OK || data == null) { + apgData.setEncryptionKeys(null); + break; + } + apgData.setEncryptionKeys(data.getLongArrayExtra(Constants.EXTRA_SELECTION)); + break; + + case Constants.ENCRYPT_MESSAGE: + if (resultCode != Activity.RESULT_OK || data == null) { + apgData.setEncryptionKeys(null); + break; + } + apgData.setEncryptedData(data.getStringExtra(Constants.EXTRA_ENCRYPTED_MESSAGE)); + // this was a stupid bug in an earlier version, just gonna leave this in for an APG + // version or two + if (apgData.getEncryptedData() == null) { + apgData.setEncryptedData(data.getStringExtra(Constants.EXTRA_DECRYPTED_MESSAGE)); + } + if (apgData.getEncryptedData() != null) { + } + break; + + case Constants.DECRYPT_MESSAGE: + if (resultCode != Activity.RESULT_OK || data == null) { + break; + } + + apgData.setSignatureUserId(data.getStringExtra(Constants.EXTRA_SIGNATURE_USER_ID)); + apgData.setSignatureKeyId(data.getLongExtra(Constants.EXTRA_SIGNATURE_KEY_ID, 0)); + apgData.setSignatureSuccess(data.getBooleanExtra(Constants.EXTRA_SIGNATURE_SUCCESS, + false)); + apgData.setSignatureUnknown(data.getBooleanExtra(Constants.EXTRA_SIGNATURE_UNKNOWN, + false)); + + apgData.setDecryptedData(data.getStringExtra(Constants.EXTRA_DECRYPTED_MESSAGE)); + + break; + + default: + return false; + } + + return true; + } + + /** + * Select encryption keys. + * + * @param emails + * The emails that should be used for preselection. + * @return false when activity could not be found! + */ + public boolean selectEncryptionKeys(String emails) { + return selectEncryptionKeys(emails, null); + } + + /** + * Select encryption keys. + * + * @param emails + * The emails that should be used for preselection. + * @param apgData + * ApgData with encryption keys and signature keys preselected + * @return false when activity could not be found! + */ + public boolean selectEncryptionKeys(String emails, ApgData apgData) { + Intent intent = new Intent(Constants.Intent.SELECT_PUBLIC_KEYS); + intent.putExtra(Constants.EXTRA_INTENT_VERSION, Constants.INTENT_VERSION); + + long[] initialKeyIds = null; + if (apgData == null || !apgData.hasEncryptionKeys()) { + List<Long> keyIds = new ArrayList<Long>(); + if (apgData != null && apgData.hasSignatureKey()) { + keyIds.add(apgData.getSignatureKeyId()); + } + + try { + Uri contentUri = Uri.withAppendedPath( + Constants.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, emails); + Cursor c = activity.getContentResolver().query(contentUri, + new String[] { "master_key_id" }, null, null, null); + if (c != null) { + while (c.moveToNext()) { + keyIds.add(c.getLong(0)); + } + } + + if (c != null) { + c.close(); + } + } catch (SecurityException e) { + insufficientPermissions(); + } + if (!keyIds.isEmpty()) { + initialKeyIds = new long[keyIds.size()]; + for (int i = 0, size = keyIds.size(); i < size; ++i) { + initialKeyIds[i] = keyIds.get(i); + } + } + } else { + initialKeyIds = apgData.getEncryptionKeys(); + } + intent.putExtra(Constants.EXTRA_SELECTION, initialKeyIds); + + try { + activity.startActivityForResult(intent, Constants.SELECT_PUBLIC_KEYS); + return true; + } catch (ActivityNotFoundException e) { + activityNotFound(); + return false; + } + } + + /** + * Get secret key ids based on a given email. + * + * @param context + * @param email + * The email in question. + * @return key ids + */ + public long[] getSecretKeyIdsFromEmail(String email) { + long ids[] = null; + try { + Uri contentUri = Uri.withAppendedPath(Constants.CONTENT_URI_SECRET_KEY_RING_BY_EMAILS, + email); + Cursor c = activity.getContentResolver().query(contentUri, + new String[] { "master_key_id" }, null, null, null); + if (c != null && c.getCount() > 0) { + ids = new long[c.getCount()]; + while (c.moveToNext()) { + ids[c.getPosition()] = c.getLong(0); + } + } + + if (c != null) { + c.close(); + } + } catch (SecurityException e) { + insufficientPermissions(); + } + + return ids; + } + + /** + * Get public key ids based on a given email. + * + * @param context + * @param email + * The email in question. + * @return key ids + */ + public long[] getPublicKeyIdsFromEmail(String email) { + long ids[] = null; + try { + Uri contentUri = Uri.withAppendedPath(Constants.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, + email); + Cursor c = activity.getContentResolver().query(contentUri, + new String[] { "master_key_id" }, null, null, null); + if (c != null && c.getCount() > 0) { + ids = new long[c.getCount()]; + while (c.moveToNext()) { + ids[c.getPosition()] = c.getLong(0); + } + } + + if (c != null) { + c.close(); + } + } catch (SecurityException e) { + insufficientPermissions(); + } + + return ids; + } + + /** + * Find out if a given email has a secret key. + * + * @param context + * @param email + * The email in question. + * @return true if there is a secret key for this email. + */ + public boolean hasSecretKeyForEmail(String email) { + try { + Uri contentUri = Uri.withAppendedPath(Constants.CONTENT_URI_SECRET_KEY_RING_BY_EMAILS, + email); + Cursor c = activity.getContentResolver().query(contentUri, + new String[] { "master_key_id" }, null, null, null); + if (c != null && c.getCount() > 0) { + c.close(); + return true; + } + if (c != null) { + c.close(); + } + } catch (SecurityException e) { + insufficientPermissions(); + } + return false; + } + + /** + * Find out if a given email has a public key. + * + * @param context + * @param email + * The email in question. + * @return true if there is a public key for this email. + */ + public boolean hasPublicKeyForEmail(String email) { + try { + Uri contentUri = Uri.withAppendedPath(Constants.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, + email); + Cursor c = activity.getContentResolver().query(contentUri, + new String[] { "master_key_id" }, null, null, null); + if (c != null && c.getCount() > 0) { + c.close(); + return true; + } + if (c != null) { + c.close(); + } + } catch (SecurityException e) { + insufficientPermissions(); + } + return false; + } + + /** + * Get the user id based on the key id. + * + * @param context + * @param keyId + * @return user id + */ + public String getUserId(long keyId) { + String userId = null; + try { + Uri contentUri = ContentUris.withAppendedId( + Constants.CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID, keyId); + Cursor c = activity.getContentResolver().query(contentUri, new String[] { "user_id" }, + null, null, null); + if (c != null && c.moveToFirst()) { + userId = c.getString(0); + } + + if (c != null) { + c.close(); + } + } catch (SecurityException e) { + insufficientPermissions(); + } + + if (userId == null) { + userId = "unknown"; + } + return userId; + } + + private void activityNotFound() { + Toast.makeText(activity, "APG Activity not found! Is APG installed correctly?", + Toast.LENGTH_LONG).show(); + } + + private void insufficientPermissions() { + Toast.makeText(activity, "Permission to access APG Provider is missing!", Toast.LENGTH_LONG) + .show(); + } +} diff --git a/org_apg_integration_lib/src/org/apg/integration/Constants.java b/org_apg_integration_lib/src/org/apg/integration/Constants.java new file mode 100644 index 000000000..017f88478 --- /dev/null +++ b/org_apg_integration_lib/src/org/apg/integration/Constants.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2010-2011 K-9 Mail Contributors + * 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.apg.integration; + +import android.net.Uri; + +public class Constants { + public static final String NAME = "apg"; + + public static final String APG_PACKAGE_NAME = "org.apg"; + public static final int MIN_REQUIRED_VERSION = 50; + + public static final String AUTHORITY = "org.apg.provider"; + public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID = Uri.parse("content://" + + AUTHORITY + "/key_rings/secret/key_id/"); + public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS = Uri.parse("content://" + + AUTHORITY + "/key_rings/secret/emails/"); + + public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID = Uri.parse("content://" + + AUTHORITY + "/key_rings/public/key_id/"); + public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS = Uri.parse("content://" + + AUTHORITY + "/key_rings/public/emails/"); + + public static class Intent { + public static final String DECRYPT = APG_PACKAGE_NAME + ".intent.DECRYPT"; + public static final String ENCRYPT = APG_PACKAGE_NAME + ".intent.ENCRYPT"; + public static final String DECRYPT_FILE = APG_PACKAGE_NAME + ".intent.DECRYPT_FILE"; + public static final String ENCRYPT_FILE = APG_PACKAGE_NAME + ".intent.ENCRYPT_FILE"; + public static final String DECRYPT_AND_RETURN = APG_PACKAGE_NAME + + ".intent.DECRYPT_AND_RETURN"; + public static final String ENCRYPT_AND_RETURN = APG_PACKAGE_NAME + + ".intent.ENCRYPT_AND_RETURN"; + public static final String SELECT_PUBLIC_KEYS = APG_PACKAGE_NAME + + ".intent.SELECT_PUBLIC_KEYS"; + public static final String SELECT_SECRET_KEY = APG_PACKAGE_NAME + + ".intent.SELECT_SECRET_KEY"; + } + + public static final String EXTRA_TEXT = "text"; + public static final String EXTRA_DATA = "data"; + public static final String EXTRA_ERROR = "error"; + public static final String EXTRA_DECRYPTED_MESSAGE = "decryptedMessage"; + public static final String EXTRA_ENCRYPTED_MESSAGE = "encryptedMessage"; + public static final String EXTRA_SIGNATURE = "signature"; + public static final String EXTRA_SIGNATURE_KEY_ID = "signatureKeyId"; + public static final String EXTRA_SIGNATURE_USER_ID = "signatureUserId"; + public static final String EXTRA_SIGNATURE_SUCCESS = "signatureSuccess"; + public static final String EXTRA_SIGNATURE_UNKNOWN = "signatureUnknown"; + public static final String EXTRA_USER_ID = "userId"; + public static final String EXTRA_KEY_ID = "keyId"; + public static final String EXTRA_ENCRYPTION_KEY_IDS = "encryptionKeyIds"; + public static final String EXTRA_SELECTION = "selection"; + public static final String EXTRA_MESSAGE = "message"; + public static final String EXTRA_INTENT_VERSION = "intentVersion"; + + public static final String INTENT_VERSION = "1"; + + public static final int DECRYPT_MESSAGE = 0x21070001; + public static final int ENCRYPT_MESSAGE = 0x21070002; + public static final int SELECT_PUBLIC_KEYS = 0x21070003; + public static final int SELECT_SECRET_KEY = 0x21070004; + + // public static Pattern PGP_MESSAGE = Pattern.compile( + // ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL); + + // public static Pattern PGP_SIGNED_MESSAGE = Pattern + // .compile( + // ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*", + // Pattern.DOTALL); +} diff --git a/org_apg_integration_lib/src/org/apg/integration/Util.java b/org_apg_integration_lib/src/org/apg/integration/Util.java new file mode 100644 index 000000000..8991245f5 --- /dev/null +++ b/org_apg_integration_lib/src/org/apg/integration/Util.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010-2011 K-9 Mail Contributors + * 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.apg.integration; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager.NameNotFoundException; + +import android.widget.Toast; + +public class Util { + + /** + * Check whether APG is installed and at a high enough version. + * + * @param context + * @return whether a suitable version of APG was found + */ + public boolean isApgAvailable(Context context) { + try { + PackageInfo pi = context.getPackageManager().getPackageInfo(Constants.APG_PACKAGE_NAME, + 0); + if (pi.versionCode >= Constants.MIN_REQUIRED_VERSION) { + return true; + } else { + Toast.makeText(context, + "This APG version is not supported! Please update to a newer one!", + Toast.LENGTH_LONG).show(); + } + } catch (NameNotFoundException e) { + // not found + } + + return false; + } +} |