diff options
author | Dominik Schürmann <dominik@dominikschuermann.de> | 2012-12-14 18:22:03 +0100 |
---|---|---|
committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2012-12-14 18:22:03 +0100 |
commit | be4e3a10b008dfb33caf593b6e68bb7018c2a41c (patch) | |
tree | 781e16e6964cc2482f9eeac7e123659b5bafded8 /APG/src/org/thialfihar | |
parent | 2dcaad3d3b6f8757f01e4abd2295431f24cdfed5 (diff) | |
download | open-keychain-be4e3a10b008dfb33caf593b6e68bb7018c2a41c.tar.gz open-keychain-be4e3a10b008dfb33caf593b6e68bb7018c2a41c.tar.bz2 open-keychain-be4e3a10b008dfb33caf593b6e68bb7018c2a41c.zip |
AIDL API changes
Diffstat (limited to 'APG/src/org/thialfihar')
15 files changed, 534 insertions, 121 deletions
diff --git a/APG/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java b/APG/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java index 040ff2a9e..7fee97882 100644 --- a/APG/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java +++ b/APG/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java @@ -18,17 +18,24 @@ package org.thialfihar.android.apg.helper; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; +import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPObjectFactory; +import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; +import org.spongycastle.openpgp.PGPUtil; import org.thialfihar.android.apg.Constants; +import org.thialfihar.android.apg.provider.ProviderHelper; import org.thialfihar.android.apg.util.Log; +import android.content.Context; + public class PGPConversionHelper { /** @@ -134,4 +141,17 @@ public class PGPConversionHelper { return null; } } + + public static PGPKeyRing decodeKeyRing(InputStream is) throws IOException { + InputStream in = PGPUtil.getDecoderStream(is); + PGPObjectFactory objectFactory = new PGPObjectFactory(in); + Object obj = objectFactory.nextObject(); + + if (obj instanceof PGPKeyRing) { + return (PGPKeyRing) obj; + } + + return null; + } + } diff --git a/APG/src/org/thialfihar/android/apg/helper/PGPHelper.java b/APG/src/org/thialfihar/android/apg/helper/PGPHelper.java index b566cffa0..1571ed023 100644 --- a/APG/src/org/thialfihar/android/apg/helper/PGPHelper.java +++ b/APG/src/org/thialfihar/android/apg/helper/PGPHelper.java @@ -20,9 +20,11 @@ package org.thialfihar.android.apg.helper; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.Locale; import java.util.Vector; import org.spongycastle.bcpg.ArmoredOutputStream; @@ -38,24 +40,17 @@ import org.spongycastle.openpgp.PGPSignatureSubpacketVector; import org.spongycastle.openpgp.PGPUtil; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.R; +import org.thialfihar.android.apg.provider.ApgContract.KeyRings; import org.thialfihar.android.apg.provider.ProviderHelper; import org.thialfihar.android.apg.util.IterableIterator; import org.thialfihar.android.apg.util.Log; import android.content.Context; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.net.Uri; public class PGPHelper { - public static PGPKeyRing decodeKeyRing(InputStream is) throws IOException { - InputStream in = PGPUtil.getDecoderStream(is); - PGPObjectFactory objectFactory = new PGPObjectFactory(in); - Object obj = objectFactory.nextObject(); - - if (obj instanceof PGPKeyRing) { - return (PGPKeyRing) obj; - } - - return null; - } public static Date getCreationDate(PGPPublicKey key) { return key.getCreationTime(); @@ -191,7 +186,8 @@ public class PGPHelper { } public static PGPPublicKey getEncryptPublicKey(Context context, long masterKeyId) { - PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(context, masterKeyId); + PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(context, + masterKeyId); if (keyRing == null) { Log.e(Constants.TAG, "keyRing is null!"); return null; @@ -205,7 +201,8 @@ public class PGPHelper { } public static PGPSecretKey getSigningKey(Context context, long masterKeyId) { - PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context, masterKeyId); + PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context, + masterKeyId); if (keyRing == null) { return null; } @@ -374,7 +371,7 @@ public class PGPHelper { } else if (i != 0 && i % 2 == 0) { fingerPrint += " "; } - String chunk = Integer.toHexString((fp[i] + 256) % 256).toUpperCase(); + String chunk = Integer.toHexString((fp[i] + 256) % 256).toUpperCase(Locale.US); while (chunk.length() < 2) { chunk = "0" + chunk; } @@ -385,37 +382,6 @@ public class PGPHelper { } - public static String getPubkeyAsArmoredString(Context context, long keyId) { - PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, keyId); - // if it is no public key get it from your own keys... - if (key == null) { - PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId); - if (secretKey == null) { - Log.e(Constants.TAG, "Key could not be found!"); - return null; - } - key = secretKey.getPublicKey(); - } - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ArmoredOutputStream aos = new ArmoredOutputStream(bos); - aos.setHeader("Version", PGPMain.getFullVersion(context)); - - String armouredKey = null; - try { - aos.write(key.getEncoded()); - aos.close(); - - armouredKey = bos.toString("UTF-8"); - } catch (IOException e) { - Log.e(Constants.TAG, "Problems while encoding key as armored string", e); - } - - Log.d(Constants.TAG, "key:" + armouredKey); - - return armouredKey; - } - public static String getFingerPrint(Context context, long keyId) { PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, keyId); // if it is no public key get it from your own keys... @@ -432,7 +398,7 @@ public class PGPHelper { } public static String getSmallFingerPrint(long keyId) { - String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(); + String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US); while (fingerPrint.length() < 8) { fingerPrint = "0" + fingerPrint; } @@ -449,4 +415,5 @@ public class PGPHelper { String s1 = data.substring(0, len - 8); return (Long.parseLong(s1, 16) << 32) | Long.parseLong(s2, 16); } + } diff --git a/APG/src/org/thialfihar/android/apg/helper/PGPMain.java b/APG/src/org/thialfihar/android/apg/helper/PGPMain.java index bf76901a1..cb4326f88 100644 --- a/APG/src/org/thialfihar/android/apg/helper/PGPMain.java +++ b/APG/src/org/thialfihar/android/apg/helper/PGPMain.java @@ -564,7 +564,7 @@ public class PGPMain { int oldKeys = 0; int badKeys = 0; try { - PGPKeyRing keyring = PGPHelper.decodeKeyRing(bufferedInput); + PGPKeyRing keyring = PGPConversionHelper.decodeKeyRing(bufferedInput); while (keyring != null) { int status = Integer.MIN_VALUE; // out of bounds value @@ -592,7 +592,7 @@ public class PGPMain { // TODO: needed? // obj = objectFactory.nextObject(); - keyring = PGPHelper.decodeKeyRing(bufferedInput); + keyring = PGPConversionHelper.decodeKeyRing(bufferedInput); } } catch (EOFException e) { // nothing to do, we are done @@ -652,6 +652,42 @@ public class PGPMain { return returnData; } + public static Bundle getKeyRings(Context context, long[] masterKeyIds, + OutputStream outStream, ProgressDialogUpdater progress) throws ApgGeneralException, + FileNotFoundException, PGPException, IOException { + Bundle returnData = new Bundle(); + + ArmoredOutputStream out = new ArmoredOutputStream(outStream); + out.setHeader("Version", getFullVersion(context)); + + int numKeys = 0; + for (int i = 0; i < masterKeyIds.length; ++i) { + updateProgress(progress, i * 100 / masterKeyIds.length, 100); + + // try to get it as a PGPPublicKeyRing, if that fails try to get it as a SecretKeyRing + PGPPublicKeyRing publicKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(context, + masterKeyIds[i]); + if (publicKeyRing != null) { + publicKeyRing.encode(out); + } else { + PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByRowId(context, + masterKeyIds[i]); + if (secretKeyRing != null) { + secretKeyRing.encode(out); + } else { + continue; + } + } + ++numKeys; + } + out.close(); + returnData.putInt(ApgIntentService.RESULT_EXPORT, numKeys); + + updateProgress(progress, R.string.progress_done, 100, 100); + + return returnData; + } + /** * Encrypt and Sign data * diff --git a/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java b/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java index 611b647e6..125b557a3 100644 --- a/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java +++ b/APG/src/org/thialfihar/android/apg/provider/ProviderHelper.java @@ -16,10 +16,12 @@ package org.thialfihar.android.apg.provider; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Date; +import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKeyRing; @@ -28,6 +30,7 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.helper.PGPConversionHelper; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.provider.ApgContract.KeyRings; import org.thialfihar.android.apg.provider.ApgContract.UserIds; import org.thialfihar.android.apg.provider.ApgContract.Keys; @@ -40,6 +43,7 @@ import android.content.ContentValues; import android.content.Context; import android.content.OperationApplicationException; import android.database.Cursor; +import android.database.DatabaseUtils; import android.net.Uri; import android.os.RemoteException; @@ -469,16 +473,38 @@ public class ProviderHelper { cr.delete(KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)), null, null); } + /** + * Get master key id of keyring by its row id + * + * @param context + * @param keyRingRowId + * @return + */ public static long getPublicMasterKeyId(Context context, long keyRingRowId) { Uri queryUri = KeyRings.buildPublicKeyRingsUri(String.valueOf(keyRingRowId)); return getMasterKeyId(context, queryUri, keyRingRowId); } + /** + * Get master key id of keyring by its row id + * + * @param context + * @param keyRingRowId + * @return + */ public static long getSecretMasterKeyId(Context context, long keyRingRowId) { Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId)); return getMasterKeyId(context, queryUri, keyRingRowId); } + /** + * Private helper method to get master key id of keyring by its row id + * + * @param context + * @param queryUri + * @param keyRingRowId + * @return + */ private static long getMasterKeyId(Context context, Uri queryUri, long keyRingRowId) { String[] projection = new String[] { KeyRings.MASTER_KEY_ID }; @@ -499,4 +525,135 @@ public class ProviderHelper { return masterKeyId; } + public static ArrayList<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; + } } diff --git a/APG/src/org/thialfihar/android/apg/service/ApgService.java b/APG/src/org/thialfihar/android/apg/service/ApgApiService.java index a94887ba4..81d665e13 100644 --- a/APG/src/org/thialfihar/android/apg/service/ApgService.java +++ b/APG/src/org/thialfihar/android/apg/service/ApgApiService.java @@ -31,6 +31,9 @@ import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.PGPMain.ApgGeneralException; +import org.thialfihar.android.apg.service.handler.IApgDecryptHandler; +import org.thialfihar.android.apg.service.handler.IApgEncryptHandler; +import org.thialfihar.android.apg.service.handler.IApgGetDecryptionKeyIdHandler; import org.thialfihar.android.apg.util.InputData; import org.thialfihar.android.apg.util.Log; @@ -47,20 +50,20 @@ import android.os.RemoteException; * - is this service thread safe? Probably not! * */ -public class ApgService extends Service { +public class ApgApiService extends Service { Context mContext; @Override public void onCreate() { super.onCreate(); mContext = this; - Log.d(Constants.TAG, "ApgService, onCreate()"); + Log.d(Constants.TAG, "ApgApiService, onCreate()"); } @Override public void onDestroy() { super.onDestroy(); - Log.d(Constants.TAG, "ApgService, onDestroy()"); + Log.d(Constants.TAG, "ApgApiService, onDestroy()"); } @Override @@ -68,19 +71,19 @@ public class ApgService extends Service { return mBinder; } - private static void writeToOutputStream(InputStream is, OutputStream os) throws IOException { - byte[] buffer = new byte[8]; - int len = 0; - while ((len = is.read(buffer)) != -1) { - os.write(buffer, 0, len); - } - } + // private static void writeToOutputStream(InputStream is, OutputStream os) throws IOException { + // byte[] buffer = new byte[8]; + // int len = 0; + // while ((len = is.read(buffer)) != -1) { + // os.write(buffer, 0, len); + // } + // } private void encryptAndSignImplementation(byte[] inputBytes, String inputUri, boolean useAsciiArmor, int compression, long[] encryptionKeyIds, String encryptionPassphrase, int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm, boolean signatureForceV3, String signaturePassphrase, - IApgEncryptSignHandler handler) throws RemoteException { + IApgEncryptHandler handler) throws RemoteException { try { // TODO use inputUri @@ -128,7 +131,7 @@ public class ApgService extends Service { byte[] outputBytes = ((ByteArrayOutputStream) output).toByteArray(); // return over handler on client side - handler.onSuccessEncrypt(outputBytes, null); + handler.onSuccess(outputBytes, null); } catch (Exception e) { Log.e(Constants.TAG, "ApgService, Exception!", e); @@ -141,7 +144,7 @@ public class ApgService extends Service { } private void decryptAndVerifyImplementation(byte[] inputBytes, String inputUri, - String passphrase, boolean assumeSymmetric, IApgDecryptVerifyHandler handler) + String passphrase, boolean assumeSymmetric, IApgDecryptHandler handler) throws RemoteException { try { @@ -170,7 +173,7 @@ public class ApgService extends Service { .getBoolean(ApgIntentService.RESULT_SIGNATURE_UNKNOWN); // return over handler on client side - handler.onSuccessDecrypt(outputBytes, null, signature, signatureKeyId, signatureUserId, + handler.onSuccess(outputBytes, null, signature, signatureKeyId, signatureUserId, signatureSuccess, signatureUnknown); } catch (Exception e) { Log.e(Constants.TAG, "ApgService, Exception!", e); @@ -184,7 +187,7 @@ public class ApgService extends Service { } private void getDecryptionKeyImplementation(byte[] inputBytes, String inputUri, - IApgHelperHandler handler) { + IApgGetDecryptionKeyIdHandler handler) { // TODO: implement inputUri @@ -195,20 +198,20 @@ public class ApgService extends Service { boolean symmetric; try { - secretKeyId = PGPMain.getDecryptionKeyId(ApgService.this, inputStream); + secretKeyId = PGPMain.getDecryptionKeyId(ApgApiService.this, inputStream); if (secretKeyId == Id.key.none) { throw new ApgGeneralException(getString(R.string.error_noSecretKeyFound)); } symmetric = false; } catch (PGPMain.NoAsymmetricEncryptionException e) { secretKeyId = Id.key.symmetric; - if (!PGPMain.hasSymmetricEncryption(ApgService.this, inputStream)) { + if (!PGPMain.hasSymmetricEncryption(ApgApiService.this, inputStream)) { throw new ApgGeneralException(getString(R.string.error_noKnownEncryptionFound)); } symmetric = true; } - handler.onSuccessGetDecryptionKey(secretKeyId, symmetric); + handler.onSuccess(secretKeyId, symmetric); } catch (Exception e) { Log.e(Constants.TAG, "ApgService, Exception!", e); @@ -227,12 +230,12 @@ public class ApgService extends Service { * * The real PGP code is located in PGPMain. */ - private final IApgService.Stub mBinder = new IApgService.Stub() { + private final IApgApiService.Stub mBinder = new IApgApiService.Stub() { @Override public void encryptAsymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor, int compression, long[] encryptionKeyIds, int symmetricEncryptionAlgorithm, - IApgEncryptSignHandler handler) throws RemoteException { + IApgEncryptHandler handler) throws RemoteException { encryptAndSignImplementation(inputBytes, inputUri, useAsciiArmor, compression, encryptionKeyIds, null, symmetricEncryptionAlgorithm, Id.key.none, 0, false, @@ -242,7 +245,7 @@ public class ApgService extends Service { @Override public void encryptSymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor, int compression, String encryptionPassphrase, int symmetricEncryptionAlgorithm, - IApgEncryptSignHandler handler) throws RemoteException { + IApgEncryptHandler handler) throws RemoteException { encryptAndSignImplementation(inputBytes, inputUri, useAsciiArmor, compression, null, encryptionPassphrase, symmetricEncryptionAlgorithm, Id.key.none, 0, false, @@ -253,7 +256,7 @@ public class ApgService extends Service { public void encryptAndSignAsymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor, int compression, long[] encryptionKeyIds, int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm, - boolean signatureForceV3, String signaturePassphrase, IApgEncryptSignHandler handler) + boolean signatureForceV3, String signaturePassphrase, IApgEncryptHandler handler) throws RemoteException { encryptAndSignImplementation(inputBytes, inputUri, useAsciiArmor, compression, @@ -265,7 +268,7 @@ public class ApgService extends Service { public void encryptAndSignSymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor, int compression, String encryptionPassphrase, int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm, - boolean signatureForceV3, String signaturePassphrase, IApgEncryptSignHandler handler) + boolean signatureForceV3, String signaturePassphrase, IApgEncryptHandler handler) throws RemoteException { encryptAndSignImplementation(inputBytes, inputUri, useAsciiArmor, compression, null, @@ -275,23 +278,22 @@ public class ApgService extends Service { @Override public void decryptAndVerifyAsymmetric(byte[] inputBytes, String inputUri, - String keyPassphrase, IApgDecryptVerifyHandler handler) throws RemoteException { + String keyPassphrase, IApgDecryptHandler handler) throws RemoteException { decryptAndVerifyImplementation(inputBytes, inputUri, keyPassphrase, false, handler); } @Override public void decryptAndVerifySymmetric(byte[] inputBytes, String inputUri, - String encryptionPassphrase, IApgDecryptVerifyHandler handler) - throws RemoteException { + String encryptionPassphrase, IApgDecryptHandler handler) throws RemoteException { decryptAndVerifyImplementation(inputBytes, inputUri, encryptionPassphrase, true, handler); } @Override - public void getDecryptionKey(byte[] inputBytes, String inputUri, IApgHelperHandler handler) - throws RemoteException { + public void getDecryptionKeyId(byte[] inputBytes, String inputUri, + IApgGetDecryptionKeyIdHandler handler) throws RemoteException { getDecryptionKeyImplementation(inputBytes, inputUri, handler); } diff --git a/APG/src/org/thialfihar/android/apg/service/ApgKeyService.java b/APG/src/org/thialfihar/android/apg/service/ApgKeyService.java new file mode 100644 index 000000000..32dd84675 --- /dev/null +++ b/APG/src/org/thialfihar/android/apg/service/ApgKeyService.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2012 Dominik Schürmann <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; + // } + // } + +} diff --git a/APG/src/org/thialfihar/android/apg/service/IApgService.aidl b/APG/src/org/thialfihar/android/apg/service/IApgApiService.aidl index 98c08c62b..277ce6722 100644 --- a/APG/src/org/thialfihar/android/apg/service/IApgService.aidl +++ b/APG/src/org/thialfihar/android/apg/service/IApgApiService.aidl @@ -16,15 +16,15 @@ package org.thialfihar.android.apg.service; -import org.thialfihar.android.apg.service.IApgEncryptSignHandler; -import org.thialfihar.android.apg.service.IApgDecryptVerifyHandler; -import org.thialfihar.android.apg.service.IApgHelperHandler; +import org.thialfihar.android.apg.service.handler.IApgEncryptHandler; +import org.thialfihar.android.apg.service.handler.IApgDecryptHandler; +import org.thialfihar.android.apg.service.handler.IApgGetDecryptionKeyIdHandler; /** * All methods are oneway, which means they are asynchronous and non-blocking. * Results are returned into given Handler, which has to be implemented on client side. */ -interface IApgService { +interface IApgApiService { /** * Encrypt @@ -50,7 +50,7 @@ interface IApgService { */ oneway void encryptAsymmetric(in byte[] inputBytes, in String inputUri, in boolean useAsciiArmor, in int compression, in long[] encryptionKeyIds, in int symmetricEncryptionAlgorithm, - in IApgEncryptSignHandler handler); + in IApgEncryptHandler handler); /** * Same as encryptAsymmetric but using a passphrase for symmetric encryption @@ -60,7 +60,7 @@ interface IApgService { */ oneway void encryptSymmetric(in byte[] inputBytes, in String inputUri, in boolean useAsciiArmor, in int compression, in String encryptionPassphrase, in int symmetricEncryptionAlgorithm, - in IApgEncryptSignHandler handler); + in IApgEncryptHandler handler); /** * Encrypt and sign @@ -97,7 +97,7 @@ interface IApgService { in boolean useAsciiArmor, in int compression, in long[] encryptionKeyIds, in int symmetricEncryptionAlgorithm, in long signatureKeyId, in int signatureHashAlgorithm, in boolean signatureForceV3, in String signaturePassphrase, - in IApgEncryptSignHandler handler); + in IApgEncryptHandler handler); /** * Same as encryptAndSignAsymmetric but using a passphrase for symmetric encryption @@ -109,7 +109,7 @@ interface IApgService { in boolean useAsciiArmor, in int compression, in String encryptionPassphrase, in int symmetricEncryptionAlgorithm, in long signatureKeyId, in int signatureHashAlgorithm, in boolean signatureForceV3, in String signaturePassphrase, - in IApgEncryptSignHandler handler); + in IApgEncryptHandler handler); /** * Decrypts and verifies given input bytes. If no signature is present this method @@ -125,7 +125,7 @@ interface IApgService { * Handler where to return results to after successful encryption */ oneway void decryptAndVerifyAsymmetric(in byte[] inputBytes, in String inputUri, - in String keyPassphrase, in IApgDecryptVerifyHandler handler); + in String keyPassphrase, in IApgDecryptHandler handler); /** * Same as decryptAndVerifyAsymmetric but for symmetric decryption. @@ -134,13 +134,13 @@ interface IApgService { * Passphrase to decrypt */ oneway void decryptAndVerifySymmetric(in byte[] inputBytes, in String inputUri, - in String encryptionPassphrase, in IApgDecryptVerifyHandler handler); + in String encryptionPassphrase, in IApgDecryptHandler handler); /** * */ - oneway void getDecryptionKey(in byte[] inputBytes, in String inputUri, - in IApgHelperHandler handler); + oneway void getDecryptionKeyId(in byte[] inputBytes, in String inputUri, + in IApgGetDecryptionKeyIdHandler handler); }
\ No newline at end of file diff --git a/APG/src/org/thialfihar/android/apg/service/IApgKeyService.aidl b/APG/src/org/thialfihar/android/apg/service/IApgKeyService.aidl new file mode 100644 index 000000000..12ecddc17 --- /dev/null +++ b/APG/src/org/thialfihar/android/apg/service/IApgKeyService.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2012 Dominik Schürmann <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); +}
\ No newline at end of file diff --git a/APG/src/org/thialfihar/android/apg/service/IApgDecryptVerifyHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgDecryptHandler.aidl index ad74340bf..feb56bce6 100644 --- a/APG/src/org/thialfihar/android/apg/service/IApgDecryptVerifyHandler.aidl +++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgDecryptHandler.aidl @@ -14,17 +14,14 @@ * limitations under the License. */ -package org.thialfihar.android.apg.service; +package org.thialfihar.android.apg.service.handler; -interface IApgDecryptVerifyHandler { +interface IApgDecryptHandler { - oneway void onSuccessDecrypt(in byte[] outputBytes, in String outputUri, in boolean signature, + oneway void onSuccess(in byte[] outputBytes, in String outputUri, in boolean signature, in long signatureKeyId, in String signatureUserId, in boolean signatureSuccess, in boolean signatureUnknown); - - oneway void onSuccessVerify(in boolean signature, in long signatureKeyId, - in String signatureUserId, in boolean signatureSuccess, in boolean signatureUnknown); - - + + oneway void onException(in int exceptionNumber, in String message); }
\ No newline at end of file diff --git a/APG/src/org/thialfihar/android/apg/service/IApgEncryptSignHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgEncryptHandler.aidl index ea3e2ae86..be0317715 100644 --- a/APG/src/org/thialfihar/android/apg/service/IApgEncryptSignHandler.aidl +++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgEncryptHandler.aidl @@ -14,17 +14,15 @@ * limitations under the License. */ -package org.thialfihar.android.apg.service; +package org.thialfihar.android.apg.service.handler; -interface IApgEncryptSignHandler { +interface IApgEncryptHandler { /** * Either output or streamUri is given. One of them is null * */ - oneway void onSuccessEncrypt(in byte[] outputBytes, in String outputUri); - - oneway void onSuccessSign(in byte[] outputBytes, in String outputUri); - - + oneway void onSuccess(in byte[] outputBytes, in String outputUri); + + oneway void onException(in int exceptionNumber, in String message); }
\ No newline at end of file diff --git a/APG/src/org/thialfihar/android/apg/service/IApgHelperHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgGetDecryptionKeyIdHandler.aidl index 29ff2dd3e..020a80b99 100644 --- a/APG/src/org/thialfihar/android/apg/service/IApgHelperHandler.aidl +++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgGetDecryptionKeyIdHandler.aidl @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.thialfihar.android.apg.service; +package org.thialfihar.android.apg.service.handler; + +interface IApgGetDecryptionKeyIdHandler { + + oneway void onSuccess(in long secretKeyId, in boolean symmetric); -interface IApgHelperHandler { - oneway void onSuccessGetDecryptionKey(in long secretKeyId, in boolean symmetric); - - oneway void onException(in int exceptionNumber, in String message); }
\ No newline at end of file diff --git a/APG/src/org/thialfihar/android/apg/service/handler/IApgGetKeyringsHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgGetKeyringsHandler.aidl new file mode 100644 index 000000000..ffa9d0d2d --- /dev/null +++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgGetKeyringsHandler.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 Dominik Schürmann <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); +}
\ No newline at end of file diff --git a/APG/src/org/thialfihar/android/apg/service/handler/IApgSignHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgSignHandler.aidl new file mode 100644 index 000000000..cf91e8bc4 --- /dev/null +++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgSignHandler.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 Dominik Schürmann <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); +}
\ No newline at end of file diff --git a/APG/src/org/thialfihar/android/apg/service/handler/IApgVerifyHandler.aidl b/APG/src/org/thialfihar/android/apg/service/handler/IApgVerifyHandler.aidl new file mode 100644 index 000000000..6baaec758 --- /dev/null +++ b/APG/src/org/thialfihar/android/apg/service/handler/IApgVerifyHandler.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2012 Dominik Schürmann <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); +}
\ No newline at end of file diff --git a/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java b/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java index 12a0bb131..0d12f5fe4 100644 --- a/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java +++ b/APG/src/org/thialfihar/android/apg/ui/KeyListSecretFragment.java @@ -17,9 +17,10 @@ package org.thialfihar.android.apg.ui; +import java.util.ArrayList; + import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; -import org.thialfihar.android.apg.helper.PGPHelper; import org.thialfihar.android.apg.provider.ProviderHelper; import org.thialfihar.android.apg.provider.ApgContract.KeyRings; import org.thialfihar.android.apg.provider.ApgContract.UserIds; @@ -87,25 +88,21 @@ public class KeyListSecretFragment extends KeyListFragment implements int groupPosition = ExpandableListView.getPackedPositionGroup(expInfo.packedPosition); long keyRingRowId = getExpandableListAdapter().getGroupId(groupPosition); + // get master key id using row id + long masterKeyId = ProviderHelper + .getSecretMasterKeyId(mKeyListSecretActivity, keyRingRowId); + switch (item.getItemId()) { case Id.menu.edit: - // TODO: do it better directly with keyRingRowId? - long masterKeyId = ProviderHelper.getSecretMasterKeyId(mKeyListSecretActivity, - keyRingRowId); - mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId); - return true; + return true; case Id.menu.share_qr_code: - // TODO: do it better directly with keyRingRowId? - long masterKeyId2 = ProviderHelper.getSecretMasterKeyId(mKeyListSecretActivity, - keyRingRowId); - - String msg = PGPHelper.getPubkeyAsArmoredString(mKeyListSecretActivity, masterKeyId2); + ArrayList<String> keyringArmored = ProviderHelper.getPublicKeyRingsAsArmoredString( + mKeyListSecretActivity, new long[] { masterKeyId }); + new IntentIntegrator(mKeyListSecretActivity).shareText(keyringArmored.get(0)); - new IntentIntegrator(mKeyListSecretActivity).shareText(msg); return true; - default: return super.onContextItemSelected(item); |