Remove most of old API

This commit is contained in:
Dominik Schürmann 2013-09-09 14:03:58 +02:00
parent 9bcf733670
commit b6a1bc770c
27 changed files with 241 additions and 1029 deletions

31
API.md
View File

@ -2,33 +2,30 @@
## Basic goals
* 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
* Intents invoked by apps that are not registered by Keychain's App API must require user interaction (e.g. click a button in a dialog to actually encrypt!)
## Without Permissions
### Intents
These Intents require user interaction!
All Intents start with ``org.sufficientlysecure.keychain.action.``
* ``android.intent.action.VIEW`` connected to .gpg and .asc files: Import Key and Decrypt
* ``android.intent.action.SEND connected to all mime types (text/plain and every binary data like files and images): Encrypt and Decrypt
* ``IMPORT``
* ``IMPORT_FROM_FILE``
* ``IMPORT_FROM_QR_CODE``
* ``IMPORT_FROM_NFC``
* ``SHARE_KEYRING``
* ``SHARE_KEYRING_WITH_QR_CODE``
* ``SHARE_KEYRING_WITH_NFC``
* ``EDIT_KEYRING``
* ``SELECT_PUBLIC_KEYRINGS``
* ``SELECT_SECRET_KEYRING``
* ``ENCRYPT``
* ``KEY_IMPORT`` with extra "keyring_bytes" or Uri in data with file schema
* ``KEY_IMPORT_FROM_QR_CODE`` without extras
* ``ENCRYPT`` TODO: explain extras (see source)
* ``ENCRYPT_FILE``
* ``DECRYPT``
* ``DECRYPT`` TODO: explain extras (see source)
* ``DECRYPT_FILE``
TODO:
- remove IMPORT, SHARE intents, simplify ENCRYPT and DECRYPT intents (include _FILE derivates like done in SEND based on file type)
- EDIT_KEYRING and CREATE_KEYRING, should be available via for registered apps
- new intent REGISTER_APP?
## App API

View File

@ -67,28 +67,6 @@
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="com.fsck.k9.permission.READ_ATTACHMENT" />
<!-- TODO: disabled, old API -->
<!-- <permission-group -->
<!-- android:name="org.sufficientlysecure.keychain.permission-group.keychain" -->
<!-- android:description="@string/permission_group_description" -->
<!-- android:icon="@drawable/icon" -->
<!-- android:label="@string/permission_group_label" /> -->
<!-- <permission -->
<!-- android:name="org.sufficientlysecure.keychain.permission.ACCESS_KEYS" -->
<!-- android:description="@string/permission_access_keys_description" -->
<!-- android:label="@string/permission_access_keys_label" -->
<!-- android:permissionGroup="org.sufficientlysecure.keychain.permission-group.keychain" -->
<!-- android:protectionLevel="dangerous" /> -->
<!-- <permission -->
<!-- android:name="org.sufficientlysecure.keychain.permission.ACCESS_API" -->
<!-- android:description="@string/permission_access_api_description" -->
<!-- android:label="@string/permission_access_api_label" -->
<!-- android:permissionGroup="org.sufficientlysecure.keychain.permission-group.keychain" -->
<!-- android:protectionLevel="dangerous" /> -->
<!-- android:allowBackup="false": Don't allow backup over adb backup or other apps! -->
<application
android:name=".KeychainApplication"
@ -113,13 +91,15 @@
android:label="@string/title_managePublicKeys"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow" >
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable_public_keys" />
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.SEARCH" /> -->
<!-- </intent-filter> -->
<!-- <meta-data -->
<!-- android:name="android.app.searchable" -->
<!-- android:resource="@xml/searchable_public_keys" /> -->
</activity>
<activity
android:name=".ui.KeyListSecretActivity"
@ -127,31 +107,22 @@
android:label="@string/title_manageSecretKeys"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow" >
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable_secret_keys" />
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.SEARCH" /> -->
<!-- </intent-filter> -->
<!-- <meta-data -->
<!-- android:name="android.app.searchable" -->
<!-- android:resource="@xml/searchable_secret_keys" /> -->
</activity>
<!-- todo: export disabled, old API -->
<activity
android:name=".ui.EditKeyActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:exported="false"
android:label="@string/title_editKey"
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="stateHidden" >
<!-- TODO: disabled: old api! -->
<intent-filter>
<action android:name="org.sufficientlysecure.keychain.action.EDIT_KEYRING" />
<action android:name="org.sufficientlysecure.keychain.action.CREATE_KEYRING" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".ui.SelectPublicKeyActivity"
@ -159,36 +130,30 @@
android:label="@string/title_selectRecipients"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow" >
<intent-filter>
<action android:name="org.sufficientlysecure.keychain.action.SELECT_PUBLIC_KEYRINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.SEARCH" /> -->
<!-- </intent-filter> -->
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable_public_keys" />
<!-- <meta-data -->
<!-- android:name="android.app.searchable" -->
<!-- android:resource="@xml/searchable_public_keys" /> -->
</activity>
<activity
android:name=".ui.SelectSecretKeyActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_selectSignature"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="org.sufficientlysecure.keychain.action.SELECT_SECRET_KEYRING" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.SEARCH" /> -->
<!-- </intent-filter> -->
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable_secret_keys" />
<!-- <meta-data -->
<!-- android:name="android.app.searchable" -->
<!-- android:resource="@xml/searchable_secret_keys" /> -->
</activity>
<activity
android:name=".ui.EncryptActivity"
@ -197,16 +162,11 @@
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="stateHidden" >
<!-- APG's own Actions -->
<!-- Keychain's own Actions -->
<intent-filter>
<action android:name="org.sufficientlysecure.keychain.action.ENCRYPT" />
<action android:name="org.sufficientlysecure.keychain.action.ENCRYPT_FILE" />
<!-- With permission ACCESS_API: -->
<action android:name="org.sufficientlysecure.keychain.action.ENCRYPT_AND_RETURN" />
<action android:name="org.sufficientlysecure.keychain.action.ENCRYPT_STREAM_AND_RETURN" />
<action android:name="org.sufficientlysecure.keychain.action.GENERATE_SIGNATURE_AND_RETURN" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
@ -227,15 +187,11 @@
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="stateHidden" >
<!-- APG's own Actions -->
<!-- Keychain's own Actions -->
<intent-filter>
<action android:name="org.sufficientlysecure.keychain.action.DECRYPT" />
<action android:name="org.sufficientlysecure.keychain.action.DECRYPT_FILE" />
<!-- With permission ACCESS_API: -->
<action android:name="org.sufficientlysecure.keychain.action.DECRYPT_AND_RETURN" />
<action android:name="org.sufficientlysecure.keychain.action.DECRYPT_STREAM_AND_RETURN" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
@ -321,9 +277,9 @@
android:label="@string/title_importKeys"
android:uiOptions="splitActionBarWhenNarrow" >
<!-- APG's own Actions -->
<!-- Keychain's own Actions -->
<intent-filter android:label="@string/intent_import_key" >
<action android:name="org.sufficientlysecure.keychain.action.IMPORT" />
<action android:name="org.sufficientlysecure.keychain.action.KEY_IMPORT" />
<category android:name="android.intent.category.DEFAULT" />
@ -331,9 +287,8 @@
</intent-filter>
<!-- IMPORT again without mimeType to also allow data only without filename -->
<intent-filter android:label="@string/intent_import_key" >
<action android:name="org.sufficientlysecure.keychain.action.IMPORT" />
<action android:name="org.sufficientlysecure.keychain.action.IMPORT_FROM_QR_CODE" />
<action android:name="org.sufficientlysecure.keychain.action.IMPORT_FROM_NFC" />
<action android:name="org.sufficientlysecure.keychain.action.KEY_IMPORT" />
<action android:name="org.sufficientlysecure.keychain.action.KEY_IMPORT_FROM_QR_CODE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@ -386,11 +341,6 @@
android:label="@string/title_shareByNfc"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow" >
<intent-filter>
<action android:name="org.sufficientlysecure.keychain.action.SHARE_KEYRING_WITH_NFC" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<!-- Handle NFC tags detected from outside our application -->
<intent-filter>
@ -402,12 +352,6 @@
</intent-filter>
</activity>
<activity android:name=".ui.ShareActivity" >
<intent-filter>
<action android:name="org.sufficientlysecure.keychain.action.SHARE_KEYRING" />
<action android:name="org.sufficientlysecure.keychain.action.SHARE_KEYRING_WITH_QR_CODE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".ui.HelpActivity"
@ -419,16 +363,7 @@
android:process=":passphrase_cache" />
<service android:name="org.sufficientlysecure.keychain.service.KeychainIntentService" />
<!-- TODO: disabled, old API! -->
<!-- <service -->
<!-- android:name="org.sufficientlysecure.keychain.service.KeychainApiService" -->
<!-- android:enabled="true" -->
<!-- android:exported="true" -->
<!-- android:permission="org.sufficientlysecure.keychain.permission.ACCESS_API" -->
<!-- android:process=":remoteapi" > -->
<!-- <intent-filter> -->
<!-- <action android:name="org.sufficientlysecure.keychain.service.IKeychainApiService" /> -->
<!-- </intent-filter> -->
<!-- TODO: Make this extended API -->
<!-- <meta-data -->
@ -452,18 +387,11 @@
<!-- </service> -->
<provider
android:name="org.sufficientlysecure.keychain.provider.KeychainProviderInternal"
android:authorities="org.sufficientlysecure.keychain.internal"
android:name="org.sufficientlysecure.keychain.provider.KeychainProvider"
android:authorities="org.sufficientlysecure.keychain.provider"
android:exported="false" />
<!-- TODO: disabled, old API -->
<!-- <provider -->
<!-- android:name="org.sufficientlysecure.keychain.provider.KeychainProviderExternal" -->
<!-- android:authorities="org.sufficientlysecure.keychain" -->
<!-- android:exported="true" -->
<!-- android:readPermission="org.sufficientlysecure.keychain.permission.ACCESS_API" /> -->
<!-- TODO: authority! -->
<!-- TODO: authority! Make this API with content provider uris -->
<!-- <provider -->
<!-- android:name="org.sufficientlysecure.keychain.provider.KeychainServiceBlobProvider" -->
<!-- android:authorities="org.sufficientlysecure.keychain.provider.apgserviceblobprovider" -->
@ -476,6 +404,7 @@
android:name="org.sufficientlysecure.keychain.remote_api.CryptoServiceActivity"
android:exported="false"
android:label="@string/app_name"
android:launchMode="singleTop"
android:process=":crypto" >
<!-- Don't publish intents, they are only used internally! -->

View File

@ -306,14 +306,6 @@
<string name="progress_querying">querying…</string>
<string name="progress_queryingServer">querying %s…</string>
<!-- permission strings -->
<string name="permission_group_label">OpenPGP Keychain</string>
<string name="permission_group_description">Permissions to use OpenPGP</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 OpenPGP, 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 interaction.</string>
<!-- action strings -->
<string name="action_encrypt">Encrypt</string>
<string name="action_decrypt">Decrypt</string>
@ -335,7 +327,7 @@
<string name="slow">slow</string>
<string name="very_slow">very slow</string>
<!-- APG 2.0 -->
<!-- OpenPGP Keychain (2.0) -->
<!-- Dashboard -->

View File

@ -20,7 +20,7 @@ import android.os.Environment;
public final class Constants {
public static final boolean DEBUG = true;
public static final boolean DEBUG = BuildConfig.DEBUG;
public static final String TAG = "Keychain";
@ -29,14 +29,11 @@ public final class Constants {
// as defined in http://tools.ietf.org/html/rfc3156, section 7
public static final String NFC_MIME = "application/pgp-keys";
public static final String PERMISSION_ACCESS_KEY_DATABASE = PACKAGE_NAME
+ ".permission.ACCESS_KEY_DATABASE";
public static final String PERMISSION_ACCESS_API = PACKAGE_NAME + ".permission.ACCESS_API";
public static final String INTENT_PREFIX = PACKAGE_NAME + ".action.";
public static final class path {
public static final String APP_DIR = Environment.getExternalStorageDirectory() + "/OpenPGP-Keychain";
public static final String APP_DIR = Environment.getExternalStorageDirectory()
+ "/OpenPGP-Keychain";
}
public static final class pref {

View File

@ -66,11 +66,10 @@ public class KeychainContract {
public static final int SECRET = 1;
}
public static final String CONTENT_AUTHORITY_EXTERNAL = Constants.PACKAGE_NAME;
public static final String CONTENT_AUTHORITY_INTERNAL = Constants.PACKAGE_NAME + ".internal";
public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".provider";
private static final Uri BASE_CONTENT_URI_INTERNAL = Uri.parse("content://"
+ CONTENT_AUTHORITY_INTERNAL);
+ CONTENT_AUTHORITY);
public static final String BASE_KEY_RINGS = "key_rings";
public static final String BASE_DATA = "data";

View File

@ -34,7 +34,6 @@ import org.sufficientlysecure.keychain.util.Log;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.DatabaseUtils;
@ -46,11 +45,11 @@ import android.provider.BaseColumns;
import android.text.TextUtils;
public class KeychainProvider extends ContentProvider {
public static final String ACTION_BROADCAST_DATABASE_CHANGE = Constants.PACKAGE_NAME
+ ".action.DATABASE_CHANGE";
public static final String EXTRA_BROADCAST_KEY_TYPE = "keyType";
public static final String EXTRA_BROADCAST_CONTENT_ITEM_TYPE = "contentItemType";
// public static final String ACTION_BROADCAST_DATABASE_CHANGE = Constants.PACKAGE_NAME
// + ".action.DATABASE_CHANGE";
//
// public static final String EXTRA_BROADCAST_KEY_TYPE = "key_type";
// public static final String EXTRA_BROADCAST_CONTENT_ITEM_TYPE = "contentItemType";
private static final int PUBLIC_KEY_RING = 101;
private static final int PUBLIC_KEY_RING_BY_ROW_ID = 102;
@ -84,22 +83,16 @@ public class KeychainProvider extends ContentProvider {
// private static final int DATA_STREAM = 401;
protected boolean mInternalProvider;
protected UriMatcher mUriMatcher;
/**
* Build and return a {@link UriMatcher} that catches all {@link Uri} variations supported by
* this {@link ContentProvider}.
*/
protected UriMatcher buildUriMatcher(boolean internalProvider) {
protected UriMatcher buildUriMatcher() {
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
String authority;
if (internalProvider) {
authority = KeychainContract.CONTENT_AUTHORITY_INTERNAL;
} else {
authority = KeychainContract.CONTENT_AUTHORITY_EXTERNAL;
}
String authority = KeychainContract.CONTENT_AUTHORITY;
/**
* public key rings
@ -250,7 +243,7 @@ public class KeychainProvider extends ContentProvider {
/** {@inheritDoc} */
@Override
public boolean onCreate() {
mUriMatcher = buildUriMatcher(mInternalProvider);
mUriMatcher = buildUriMatcher();
mApgDatabase = new KeychainDatabase(getContext());
return true;
}
@ -359,11 +352,8 @@ public class KeychainProvider extends ContentProvider {
projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID);
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "."
+ KeyRingsColumns.MASTER_KEY_ID);
// only give out keyRing blob when we are using the internal content provider
if (mInternalProvider) {
projectionMap.put(KeyRingsColumns.KEY_RING_DATA, Tables.KEY_RINGS + "."
+ KeyRingsColumns.KEY_RING_DATA);
}
projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID);
return projectionMap;
@ -389,10 +379,7 @@ public class KeychainProvider extends ContentProvider {
projectionMap.put(KeysColumns.CREATION, KeysColumns.CREATION);
projectionMap.put(KeysColumns.EXPIRY, KeysColumns.EXPIRY);
projectionMap.put(KeysColumns.KEY_RING_ROW_ID, KeysColumns.KEY_RING_ROW_ID);
// only give out keyRing blob when we are using the internal content provider
if (mInternalProvider) {
projectionMap.put(KeysColumns.KEY_DATA, KeysColumns.KEY_DATA);
}
projectionMap.put(KeysColumns.RANK, KeysColumns.RANK);
return projectionMap;

View File

@ -1,32 +0,0 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.provider;
/**
* The same content provider as ApgProviderInternal except that it does not give out keyRing and key
* blob data when querying.
*
* This provider is exported with a readPermission in AndroidManifest.xml
*/
public class KeychainProviderExternal extends KeychainProvider {
public KeychainProviderExternal() {
mInternalProvider = false;
}
}

View File

@ -1,30 +0,0 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.provider;
/**
* This provider is NOT exported in AndroidManifest.xml as it also return the actual secret keys
* from the database
*/
public class KeychainProviderInternal extends KeychainProvider {
public KeychainProviderInternal() {
mInternalProvider = true;
}
}

View File

@ -239,7 +239,7 @@ public class ProviderHelper {
}
try {
context.getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY_INTERNAL,
context.getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY,
operations);
} catch (RemoteException e) {
Log.e(Constants.TAG, "applyBatch failed!", e);
@ -296,7 +296,7 @@ public class ProviderHelper {
}
try {
context.getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY_INTERNAL,
context.getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY,
operations);
} catch (RemoteException e) {
Log.e(Constants.TAG, "applyBatch failed!", e);

View File

@ -1,144 +0,0 @@
/*
* 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.sufficientlysecure.keychain.service;
import org.sufficientlysecure.keychain.service.handler.IKeychainEncryptHandler;
import org.sufficientlysecure.keychain.service.handler.IKeychainDecryptHandler;
import org.sufficientlysecure.keychain.service.handler.IKeychainGetDecryptionKeyIdHandler;
/**
* 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 IKeychainApiService {
/**
* Encrypt
*
* Either inputBytes or inputUri is given, the other should be null.
*
* @param inputBytes
* Byte array you want to encrypt
* @param inputUri
* Blob in ContentProvider you want to encrypt
* @param useAsciiArmor
* Convert bytes to ascii armored text to guard against encoding problems
* @param compression
* Compression: 0x21070001: none, 1: Zip, 2: Zlib, 3: BZip2
* @param encryptionKeyIds
* Ids of public keys used for encryption
* @param symmetricEncryptionAlgorithm
* 7: AES-128, 8: AES-192, 9: AES-256, 4: Blowfish, 10: Twofish, 3: CAST5,
* 6: DES, 2: Triple DES, 1: IDEA
* @param handler
* Results are returned to this Handler after successful encryption
*/
oneway void encryptAsymmetric(in byte[] inputBytes, in String inputUri, in boolean useAsciiArmor,
in int compression, in long[] encryptionKeyIds, in int symmetricEncryptionAlgorithm,
in IKeychainEncryptHandler handler);
/**
* Same as encryptAsymmetric but using a passphrase for symmetric encryption
*
* @param encryptionPassphrase
* Passphrase for direct symmetric encryption using symmetricEncryptionAlgorithm
*/
oneway void encryptSymmetric(in byte[] inputBytes, in String inputUri, in boolean useAsciiArmor,
in int compression, in String encryptionPassphrase, in int symmetricEncryptionAlgorithm,
in IKeychainEncryptHandler handler);
/**
* Encrypt and sign
*
* Either inputBytes or inputUri is given, the other should be null.
*
* @param inputBytes
* Byte array you want to encrypt
* @param inputUri
* Blob in ContentProvider you want to encrypt
* @param useAsciiArmor
* Convert bytes to ascii armored text to guard against encoding problems
* @param compression
* Compression: 0x21070001: none, 1: Zip, 2: Zlib, 3: BZip2
* @param encryptionKeyIds
* Ids of public keys used for encryption
* @param symmetricEncryptionAlgorithm
* 7: AES-128, 8: AES-192, 9: AES-256, 4: Blowfish, 10: Twofish, 3: CAST5,
* 6: DES, 2: Triple DES, 1: IDEA
* @param signatureKeyId
* Key id of key to sign with
* @param signatureHashAlgorithm
* 1: MD5, 3: RIPEMD-160, 2: SHA-1, 11: SHA-224, 8: SHA-256, 9: SHA-384,
* 10: SHA-512
* @param signatureForceV3
* Force V3 signatures
* @param signaturePassphrase
* Passphrase to unlock signature key
* @param handler
* Results are returned to this Handler after successful encryption and signing
*/
oneway void encryptAndSignAsymmetric(in byte[] inputBytes, in String inputUri,
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 IKeychainEncryptHandler handler);
/**
* Same as encryptAndSignAsymmetric but using a passphrase for symmetric encryption
*
* @param encryptionPassphrase
* Passphrase for direct symmetric encryption using symmetricEncryptionAlgorithm
*/
oneway void encryptAndSignSymmetric(in byte[] inputBytes, in String inputUri,
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 IKeychainEncryptHandler handler);
/**
* Decrypts and verifies given input bytes. If no signature is present this method
* will only decrypt.
*
* @param inputBytes
* Byte array you want to decrypt and verify
* @param inputUri
* Blob in ContentProvider you want to decrypt and verify
* @param keyPassphrase
* Passphrase to unlock secret key for decryption.
* @param handler
* Handler where to return results to after successful encryption
*/
oneway void decryptAndVerifyAsymmetric(in byte[] inputBytes, in String inputUri,
in String keyPassphrase, in IKeychainDecryptHandler handler);
/**
* Same as decryptAndVerifyAsymmetric but for symmetric decryption.
*
* @param encryptionPassphrase
* Passphrase to decrypt
*/
oneway void decryptAndVerifySymmetric(in byte[] inputBytes, in String inputUri,
in String encryptionPassphrase, in IKeychainDecryptHandler handler);
/**
*
*/
oneway void getDecryptionKeyId(in byte[] inputBytes, in String inputUri,
in IKeychainGetDecryptionKeyIdHandler handler);
}

View File

@ -1,324 +0,0 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.service;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import org.spongycastle.openpgp.PGPException;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.PgpMain;
import org.sufficientlysecure.keychain.helper.PgpMain.PgpGeneralException;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.service.IKeychainApiService;
import org.sufficientlysecure.keychain.service.handler.IKeychainDecryptHandler;
import org.sufficientlysecure.keychain.service.handler.IKeychainEncryptHandler;
import org.sufficientlysecure.keychain.service.handler.IKeychainGetDecryptionKeyIdHandler;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
public class KeychainApiService extends Service {
Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
Log.d(Constants.TAG, "KeychainApiService, onCreate()");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(Constants.TAG, "KeychainApiService, onDestroy()");
}
@Override
public IBinder onBind(Intent intent) {
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 synchronized void encryptAndSignSafe(byte[] inputBytes, String inputUri,
boolean useAsciiArmor, int compression, long[] encryptionKeyIds,
String encryptionPassphrase, int symmetricEncryptionAlgorithm, long signatureKeyId,
int signatureHashAlgorithm, boolean signatureForceV3, String signaturePassphrase,
IKeychainEncryptHandler handler) throws RemoteException {
try {
// TODO use inputUri
// InputStream inStream = null;
// if (isBlob) {
// ContentResolver cr = getContentResolver();
// try {
// inStream = cr.openInputStream(Uri.parse(pArgs.getString(arg.BLOB.name())));
// } catch (Exception e) {
// Log.e(TAG, "... exception on opening blob", e);
// }
// } else {
// inStream = new ByteArrayInputStream(pArgs.getString(arg.MESSAGE.name()).getBytes());
// }
// InputData in = new InputData(inStream, 0); // XXX Size second param?
// build InputData and write into OutputStream
InputStream inputStream = new ByteArrayInputStream(inputBytes);
long inputLength = inputBytes.length;
InputData input = new InputData(inputStream, inputLength);
OutputStream output = new ByteArrayOutputStream();
//
// PgpMain.encryptAndSign(mContext, null, input, output, useAsciiArmor, compression,
// encryptionKeyIds, encryptionPassphrase, symmetricEncryptionAlgorithm,
// signatureKeyId, signatureHashAlgorithm, signatureForceV3, signaturePassphrase);
//
// output.close();
// if (isBlob) {
// ContentResolver cr = getContentResolver();
// try {
// OutputStream outStream = cr.openOutputStream(Uri.parse(pArgs.getString(arg.BLOB
// .name())));
// writeToOutputStream(new ByteArrayInputStream(out.toString().getBytes()), outStream);
// outStream.close();
// } catch (Exception e) {
// Log.e(TAG, "... exception on writing blob", e);
// }
// } else {
// pReturn.putString(ret.RESULT.name(), out.toString());
// }
byte[] outputBytes = ((ByteArrayOutputStream) output).toByteArray();
// return over handler on client side
handler.onSuccess(outputBytes, null);
} catch (Exception e) {
Log.e(Constants.TAG, "KeychainService, Exception!", e);
try {
handler.onException(getExceptionId(e), e.getMessage());
} catch (Exception t) {
Log.e(Constants.TAG, "Error returning exception to client", t);
}
}
}
private synchronized void decryptAndVerifySafe(byte[] inputBytes, String inputUri,
String passphrase, boolean assumeSymmetric, IKeychainDecryptHandler handler)
throws RemoteException {
try {
// build InputData and write into OutputStream
InputStream inputStream = new ByteArrayInputStream(inputBytes);
long inputLength = inputBytes.length;
InputData inputData = new InputData(inputStream, inputLength);
OutputStream outputStream = new ByteArrayOutputStream();
Bundle outputBundle = PgpMain.decryptAndVerify(mContext, null, inputData, outputStream,
passphrase, assumeSymmetric);
outputStream.close();
byte[] outputBytes = ((ByteArrayOutputStream) outputStream).toByteArray();
// get signature informations from bundle
boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE);
long signatureKeyId = outputBundle
.getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID);
String signatureUserId = outputBundle
.getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID);
boolean signatureSuccess = outputBundle
.getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS);
boolean signatureUnknown = outputBundle
.getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN);
// return over handler on client side
handler.onSuccess(outputBytes, null, signature, signatureKeyId, signatureUserId,
signatureSuccess, signatureUnknown);
} catch (Exception e) {
Log.e(Constants.TAG, "KeychainService, Exception!", e);
try {
handler.onException(getExceptionId(e), e.getMessage());
} catch (Exception t) {
Log.e(Constants.TAG, "Error returning exception to client", t);
}
}
}
private synchronized void getDecryptionKeySafe(byte[] inputBytes, String inputUri,
IKeychainGetDecryptionKeyIdHandler handler) {
// TODO: implement inputUri
try {
InputStream inputStream = new ByteArrayInputStream(inputBytes);
long secretKeyId = Id.key.none;
boolean symmetric;
try {
secretKeyId = PgpMain.getDecryptionKeyId(KeychainApiService.this, inputStream);
if (secretKeyId == Id.key.none) {
throw new PgpGeneralException(getString(R.string.error_noSecretKeyFound));
}
symmetric = false;
} catch (PgpMain.NoAsymmetricEncryptionException e) {
secretKeyId = Id.key.symmetric;
if (!PgpMain.hasSymmetricEncryption(KeychainApiService.this, inputStream)) {
throw new PgpGeneralException(getString(R.string.error_noKnownEncryptionFound));
}
symmetric = true;
}
handler.onSuccess(secretKeyId, symmetric);
} catch (Exception e) {
Log.e(Constants.TAG, "KeychainService, Exception!", e);
try {
handler.onException(getExceptionId(e), e.getMessage());
} catch (Exception t) {
Log.e(Constants.TAG, "Error returning exception to client", t);
}
}
}
/**
* This is the implementation of the interface IKeychainService. All methods are oneway, meaning
* asynchronous and return to the client using IKeychainHandler.
*
* The real PGP code is located in PGPMain.
*/
private final IKeychainApiService.Stub mBinder = new IKeychainApiService.Stub() {
@Override
public void encryptAsymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor,
int compression, long[] encryptionKeyIds, int symmetricEncryptionAlgorithm,
IKeychainEncryptHandler handler) throws RemoteException {
encryptAndSignSafe(inputBytes, inputUri, useAsciiArmor, compression, encryptionKeyIds,
null, symmetricEncryptionAlgorithm, Id.key.none, 0, false, null, handler);
}
@Override
public void encryptSymmetric(byte[] inputBytes, String inputUri, boolean useAsciiArmor,
int compression, String encryptionPassphrase, int symmetricEncryptionAlgorithm,
IKeychainEncryptHandler handler) throws RemoteException {
encryptAndSignSafe(inputBytes, inputUri, useAsciiArmor, compression, null,
encryptionPassphrase, symmetricEncryptionAlgorithm, Id.key.none, 0, false,
null, handler);
}
@Override
public void encryptAndSignAsymmetric(byte[] inputBytes, String inputUri,
boolean useAsciiArmor, int compression, long[] encryptionKeyIds,
int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm,
boolean signatureForceV3, String signaturePassphrase,
IKeychainEncryptHandler handler) throws RemoteException {
encryptAndSignSafe(inputBytes, inputUri, useAsciiArmor, compression, encryptionKeyIds,
null, symmetricEncryptionAlgorithm, signatureKeyId, signatureHashAlgorithm,
signatureForceV3, signaturePassphrase, handler);
}
@Override
public void encryptAndSignSymmetric(byte[] inputBytes, String inputUri,
boolean useAsciiArmor, int compression, String encryptionPassphrase,
int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm,
boolean signatureForceV3, String signaturePassphrase,
IKeychainEncryptHandler handler) throws RemoteException {
encryptAndSignSafe(inputBytes, inputUri, useAsciiArmor, compression, null,
encryptionPassphrase, symmetricEncryptionAlgorithm, signatureKeyId,
signatureHashAlgorithm, signatureForceV3, signaturePassphrase, handler);
}
@Override
public void decryptAndVerifyAsymmetric(byte[] inputBytes, String inputUri,
String keyPassphrase, IKeychainDecryptHandler handler) throws RemoteException {
decryptAndVerifySafe(inputBytes, inputUri, keyPassphrase, false, handler);
}
@Override
public void decryptAndVerifySymmetric(byte[] inputBytes, String inputUri,
String encryptionPassphrase, IKeychainDecryptHandler handler)
throws RemoteException {
decryptAndVerifySafe(inputBytes, inputUri, encryptionPassphrase, true, handler);
}
@Override
public void getDecryptionKeyId(byte[] inputBytes, String inputUri,
IKeychainGetDecryptionKeyIdHandler handler) throws RemoteException {
getDecryptionKeySafe(inputBytes, inputUri, handler);
}
};
/**
* 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 PgpGeneralException) {
return 4;
} else if (e instanceof PGPException) {
return 5;
} else {
return -1;
}
}
}

View File

@ -1,27 +0,0 @@
/*
* 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.sufficientlysecure.keychain.service.handler;
interface IKeychainDecryptHandler {
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

@ -1,28 +0,0 @@
/*
* 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.sufficientlysecure.keychain.service.handler;
interface IKeychainEncryptHandler {
/**
* 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

@ -1,25 +0,0 @@
/*
* 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.sufficientlysecure.keychain.service.handler;
interface IKeychainGetDecryptionKeyIdHandler {
oneway void onSuccess(in long secretKeyId, in boolean symmetric);
oneway void onException(in int exceptionNumber, in String message);
}

View File

@ -1,28 +0,0 @@
/*
* 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.sufficientlysecure.keychain.service.handler;
interface IKeychainSignHandler {
/**
* 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

@ -1,26 +0,0 @@
/*
* 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.sufficientlysecure.keychain.service.handler;
interface IKeychainVerifyHandler {
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,13 +17,21 @@
package org.sufficientlysecure.keychain.ui;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.regex.Matcher;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.helper.FileHelper;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.helper.PgpHelper;
import org.sufficientlysecure.keychain.helper.PgpMain;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
@ -35,12 +43,8 @@ import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.LookupUnknownKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.R;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
@ -60,14 +64,11 @@ import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.regex.Matcher;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
@SuppressLint("NewApi")
public class DecryptActivity extends SherlockFragmentActivity {
/* Intents */
@ -75,16 +76,10 @@ public class DecryptActivity extends SherlockFragmentActivity {
public static final String ACTION_DECRYPT = Constants.INTENT_PREFIX + "DECRYPT";
public static final String ACTION_DECRYPT_FILE = Constants.INTENT_PREFIX + "DECRYPT_FILE";
// with permission
public static final String ACTION_DECRYPT_AND_RETURN = Constants.INTENT_PREFIX
+ "DECRYPT_AND_RETURN";
public static final String ACTION_DECRYPT_STREAM_AND_RETURN = Constants.INTENT_PREFIX
+ "DECRYPT_STREAM_AND_RETURN";
/* EXTRA keys for input */
public static final String EXTRA_TEXT = "text";
public static final String EXTRA_DATA = "data";
public static final String EXTRA_REPLY_TO = "replyTo";
public static final String EXTRA_REPLY_TO = "reply_to";
public static final String EXTRA_SUBJECT = "subject";
public static final String EXTRA_BINARY = "binary";
@ -248,11 +243,6 @@ public class DecryptActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// check permissions for intent actions without user interaction
String[] restrictedActions = new String[] { ACTION_DECRYPT_AND_RETURN };
OtherHelper.checkPackagePermissionForActions(this, this.getCallingPackage(),
Constants.PERMISSION_ACCESS_API, getIntent().getAction(), restrictedActions);
setContentView(R.layout.decrypt);
// set actionbar without home button if called from another app
@ -456,38 +446,39 @@ public class DecryptActivity extends SherlockFragmentActivity {
// end activity
finish();
}
} else if (ACTION_DECRYPT_AND_RETURN.equals(action)) {
mReturnBinary = extras.getBoolean(EXTRA_BINARY, false);
if (mContentUri == null) {
mDataBytes = extras.getByteArray(EXTRA_DATA);
String data = extras.getString(EXTRA_TEXT);
if (data != null) {
Matcher matcher = PgpMain.PGP_MESSAGE.matcher(data);
if (matcher.matches()) {
data = matcher.group(1);
// replace non breakable spaces
data = data.replaceAll("\\xa0", " ");
mMessage.setText(data);
} else {
matcher = PgpMain.PGP_SIGNED_MESSAGE.matcher(data);
if (matcher.matches()) {
data = matcher.group(1);
// replace non breakable spaces
data = data.replaceAll("\\xa0", " ");
mMessage.setText(data);
mDecryptString = getString(R.string.btn_verify);
// build new action bar
invalidateOptionsMenu();
}
}
}
}
mReturnResult = true;
} else if (ACTION_DECRYPT_STREAM_AND_RETURN.equals(action)) {
// TODO: Implement decrypt stream
}
// } else if (ACTION_DECRYPT_AND_RETURN.equals(action)) {
// mReturnBinary = extras.getBoolean(EXTRA_BINARY, false);
//
// if (mContentUri == null) {
// mDataBytes = extras.getByteArray(EXTRA_DATA);
// String data = extras.getString(EXTRA_TEXT);
// if (data != null) {
// Matcher matcher = PgpMain.PGP_MESSAGE.matcher(data);
// if (matcher.matches()) {
// data = matcher.group(1);
// // replace non breakable spaces
// data = data.replaceAll("\\xa0", " ");
// mMessage.setText(data);
// } else {
// matcher = PgpMain.PGP_SIGNED_MESSAGE.matcher(data);
// if (matcher.matches()) {
// data = matcher.group(1);
// // replace non breakable spaces
// data = data.replaceAll("\\xa0", " ");
// mMessage.setText(data);
// mDecryptString = getString(R.string.btn_verify);
//
// // build new action bar
// invalidateOptionsMenu();
// }
// }
// }
// }
// mReturnResult = true;
// } else if (ACTION_DECRYPT_STREAM_AND_RETURN.equals(action)) {
// // TODO: Implement decrypt stream
// }
}
private void guessOutputFilename() {
@ -662,7 +653,8 @@ public class DecryptActivity extends SherlockFragmentActivity {
try {
try {
if (inStream.markSupported()) {
inStream.mark(200); //should probably set this to the max size of two pgpF objects, if it even needs to be anything other than 0.
inStream.mark(200); // should probably set this to the max size of two pgpF
// objects, if it even needs to be anything other than 0.
}
mSecretKeyId = PgpMain.getDecryptionKeyId(this, inStream);
if (mSecretKeyId == Id.key.none) {
@ -781,7 +773,8 @@ public class DecryptActivity extends SherlockFragmentActivity {
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mDataBytes);
} else {
String message = mMessage.getText().toString();
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, message.getBytes());
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES,
message.getBytes());
}
}
@ -877,7 +870,8 @@ public class DecryptActivity extends SherlockFragmentActivity {
if (returnData.getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS)) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
} else if (returnData.getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN)) {
} else if (returnData
.getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN)) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
Toast.makeText(DecryptActivity.this,
R.string.unknownSignatureKeyTouchToLookUp, Toast.LENGTH_LONG)
@ -952,4 +946,3 @@ public class DecryptActivity extends SherlockFragmentActivity {
}
}

View File

@ -65,20 +65,20 @@ import com.actionbarsherlock.app.SherlockFragmentActivity;
public class EditKeyActivity extends SherlockFragmentActivity {
// possible intent actions for this activity
public static final String ACTION_CREATE_KEY = Constants.INTENT_PREFIX + "CREATE_KEYRING";
public static final String ACTION_EDIT_KEY = Constants.INTENT_PREFIX + "EDIT_KEYRING";
// Actions for internal use only:
public static final String ACTION_CREATE_KEY = Constants.INTENT_PREFIX + "CREATE_KEY";
public static final String ACTION_EDIT_KEY = Constants.INTENT_PREFIX + "EDIT_KEY";
// possible extra keys
public static final String EXTRA_USER_IDS = "userIds";
public static final String EXTRA_NO_PASSPHRASE = "noPassphrase";
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generateDefaultKeys";
public static final String EXTRA_MASTER_KEY_ID = "masterKeyId";
public static final String EXTRA_MASTER_CAN_SIGN = "masterCanSign";
public static final String EXTRA_USER_IDS = "user_ids";
public static final String EXTRA_NO_PASSPHRASE = "no_passphrase";
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generate_default_keys";
public static final String EXTRA_MASTER_KEY_ID = "master_key_id";
public static final String EXTRA_MASTER_CAN_SIGN = "master_can_sign";
// results when saving key
public static final String RESULT_EXTRA_MASTER_KEY_ID = "masterKeyId";
public static final String RESULT_EXTRA_USER_ID = "userId";
public static final String RESULT_EXTRA_MASTER_KEY_ID = "master_key_id";
public static final String RESULT_EXTRA_USER_ID = "user_id";
private ActionBar mActionBar;
@ -106,12 +106,6 @@ public class EditKeyActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO: disabled, old API!
// check permissions for intent actions without user interaction
// String[] restrictedActions = new String[] { ACTION_CREATE_KEY };
// OtherHelper.checkPackagePermissionForActions(this, this.getCallingPackage(),
// Constants.PERMISSION_ACCESS_API, getIntent().getAction(), restrictedActions);
// Inflate a "Done"/"Cancel" custom action bar view
final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);

View File

@ -30,7 +30,6 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.helper.FileHelper;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.helper.PgpHelper;
import org.sufficientlysecure.keychain.helper.PgpMain;
import org.sufficientlysecure.keychain.helper.Preferences;
@ -77,29 +76,20 @@ public class EncryptActivity extends SherlockFragmentActivity {
public static final String ACTION_ENCRYPT = Constants.INTENT_PREFIX + "ENCRYPT";
public static final String ACTION_ENCRYPT_FILE = Constants.INTENT_PREFIX + "ENCRYPT_FILE";
// with permission
public static final String ACTION_ENCRYPT_AND_RETURN = Constants.INTENT_PREFIX
+ "ENCRYPT_AND_RETURN";
public static final String ACTION_ENCRYPT_STREAM_AND_RETURN = Constants.INTENT_PREFIX
+ "ENCRYPT_STREAM_AND_RETURN";
public static final String ACTION_GENERATE_SIGNATURE_AND_RETURN = Constants.INTENT_PREFIX
+ "GENERATE_SIGNATURE_AND_RETURN";
/* EXTRA keys for input */
public static final String EXTRA_TEXT = "text";
public static final String EXTRA_DATA = "data";
public static final String EXTRA_ASCII_ARMOUR = "asciiArmour";
public static final String EXTRA_SEND_TO = "sendTo";
public static final String EXTRA_ASCII_ARMOUR = "ascii_armor";
public static final String EXTRA_SEND_TO = "send_to";
public static final String EXTRA_SUBJECT = "subject";
public static final String EXTRA_SIGNATURE_KEY_ID = "signatureKeyId";
public static final String EXTRA_ENCRYPTION_KEY_IDS = "encryptionKeyIds";
public static final String EXTRA_SIGNATURE_KEY_ID = "signature_key_id";
public static final String EXTRA_ENCRYPTION_KEY_IDS = "encryption_key_ids";
private String mSubject = null;
private String mSendTo = null;
private long mEncryptionKeyIds[] = null;
private boolean mEncryptImmediately = false;
private EditText mMessage = null;
private Button mSelectKeysButton = null;
@ -197,12 +187,6 @@ public class EncryptActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// check permissions for intent actions without user interaction
String[] restrictedActions = new String[] { ACTION_ENCRYPT_AND_RETURN,
ACTION_GENERATE_SIGNATURE_AND_RETURN, ACTION_ENCRYPT_STREAM_AND_RETURN };
OtherHelper.checkPackagePermissionForActions(this, this.getCallingPackage(),
Constants.PERMISSION_ACCESS_API, getIntent().getAction(), restrictedActions);
setContentView(R.layout.encrypt);
// set actionbar without home button if called from another app
@ -217,26 +201,26 @@ public class EncryptActivity extends SherlockFragmentActivity {
updateSource();
updateMode();
if (mEncryptImmediately) {
mSourcePrevious.setClickable(false);
mSourcePrevious.setEnabled(false);
mSourcePrevious.setVisibility(View.INVISIBLE);
mSourceNext.setClickable(false);
mSourceNext.setEnabled(false);
mSourceNext.setVisibility(View.INVISIBLE);
mSourceLabel.setClickable(false);
mSourceLabel.setEnabled(false);
}
// if (mEncryptImmediately) {
// mSourcePrevious.setClickable(false);
// mSourcePrevious.setEnabled(false);
// mSourcePrevious.setVisibility(View.INVISIBLE);
//
// mSourceNext.setClickable(false);
// mSourceNext.setEnabled(false);
// mSourceNext.setVisibility(View.INVISIBLE);
//
// mSourceLabel.setClickable(false);
// mSourceLabel.setEnabled(false);
// }
updateActionBarButtons();
if (mEncryptImmediately
&& (mMessage.getText().length() > 0 || mData != null)
&& ((mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) || mSecretKeyId != 0)) {
encryptClicked();
}
// if (mEncryptImmediately
// && (mMessage.getText().length() > 0 || mData != null)
// && ((mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) || mSecretKeyId != 0)) {
// encryptClicked();
// }
}
/**
@ -276,16 +260,16 @@ public class EncryptActivity extends SherlockFragmentActivity {
}
}
if (ACTION_ENCRYPT_AND_RETURN.equals(action)
|| ACTION_GENERATE_SIGNATURE_AND_RETURN.equals(action)) {
mEncryptImmediately = true;
}
if (ACTION_GENERATE_SIGNATURE_AND_RETURN.equals(action)) {
mGenerateSignature = true;
mOverrideAsciiArmour = true;
mAsciiArmorDemand = false;
}
// if (ACTION_ENCRYPT_AND_RETURN.equals(action)
// || ACTION_GENERATE_SIGNATURE_AND_RETURN.equals(action)) {
// mEncryptImmediately = true;
// }
//
// if (ACTION_GENERATE_SIGNATURE_AND_RETURN.equals(action)) {
// mGenerateSignature = true;
// mOverrideAsciiArmour = true;
// mAsciiArmorDemand = false;
// }
if (extras.containsKey(EXTRA_ASCII_ARMOUR)) {
mAsciiArmorDemand = extras.getBoolean(EXTRA_ASCII_ARMOUR, true);
@ -309,8 +293,9 @@ public class EncryptActivity extends SherlockFragmentActivity {
/**
* Main Actions
*/
if (ACTION_ENCRYPT.equals(action) || ACTION_ENCRYPT_AND_RETURN.equals(action)
|| ACTION_GENERATE_SIGNATURE_AND_RETURN.equals(action)) {
// if (ACTION_ENCRYPT.equals(action) || ACTION_ENCRYPT_AND_RETURN.equals(action)
// || ACTION_GENERATE_SIGNATURE_AND_RETURN.equals(action)) {
if (ACTION_ENCRYPT.equals(action)) {
if (textData != null) {
mMessage.setText(textData);
}
@ -340,10 +325,10 @@ public class EncryptActivity extends SherlockFragmentActivity {
// end activity
finish();
}
} else if (ACTION_ENCRYPT_STREAM_AND_RETURN.equals(action)) {
// TODO: Set mStreamAndReturnUri that is used later to encrypt a stream!
mStreamAndReturnUri = uri;
// } else if (ACTION_ENCRYPT_STREAM_AND_RETURN.equals(action)) {
// // TODO: Set mStreamAndReturnUri that is used later to encrypt a stream!
//
// mStreamAndReturnUri = uri;
}
}
@ -470,31 +455,31 @@ public class EncryptActivity extends SherlockFragmentActivity {
mSourceLabel.setText(R.string.label_message);
if (mMode.getCurrentView().getId() == R.id.modeSymmetric) {
if (mEncryptImmediately) {
setActionbarButtons(true, R.string.btn_encrypt, false, 0);
} else {
// if (mEncryptImmediately) {
// setActionbarButtons(true, R.string.btn_encrypt, false, 0);
// } else {
setActionbarButtons(true, R.string.btn_encryptAndEmail, true,
R.string.btn_encryptToClipboard);
}
// }
} else {
if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) {
if (mSecretKeyId == 0) {
setActionbarButtons(false, 0, false, 0);
} else {
if (mEncryptImmediately) {
setActionbarButtons(true, R.string.btn_sign, false, 0);
} else {
// if (mEncryptImmediately) {
// setActionbarButtons(true, R.string.btn_sign, false, 0);
// } else {
setActionbarButtons(true, R.string.btn_signAndEmail, true,
R.string.btn_signToClipboard);
}
// }
}
} else {
if (mEncryptImmediately) {
setActionbarButtons(true, R.string.btn_encrypt, false, 0);
} else {
// if (mEncryptImmediately) {
// setActionbarButtons(true, R.string.btn_encrypt, false, 0);
// } else {
setActionbarButtons(true, R.string.btn_encryptAndEmail, true,
R.string.btn_encryptToClipboard);
}
// }
}
}
break;
@ -726,7 +711,8 @@ public class EncryptActivity extends SherlockFragmentActivity {
data.putByteArray(KeychainIntentService.ENCRYPT_MESSAGE_BYTES, mData);
} else {
String message = mMessage.getText().toString();
if (signOnly && !mEncryptImmediately) {
// if (signOnly && !mEncryptImmediately) {
if (signOnly) {
fixBadCharactersForGmail(message);
}
data.putByteArray(KeychainIntentService.ENCRYPT_MESSAGE_BYTES, message.getBytes());
@ -769,13 +755,13 @@ public class EncryptActivity extends SherlockFragmentActivity {
break;
case Id.target.email:
if (mEncryptImmediately) {
Intent intent = new Intent();
intent.putExtras(data);
setResult(RESULT_OK, intent);
finish();
return;
}
// if (mEncryptImmediately) {
// Intent intent = new Intent();
// intent.putExtras(data);
// setResult(RESULT_OK, intent);
// finish();
// return;
// }
output = data.getString(KeychainIntentService.RESULT_ENCRYPTED_STRING);
Log.d(Constants.TAG, "output: " + output);

View File

@ -48,17 +48,20 @@ import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
public class ImportKeysActivity extends SherlockFragmentActivity {
public static final String ACTION_IMPORT = Constants.INTENT_PREFIX + "IMPORT";
public static final String ACTION_IMPORT_FROM_FILE = Constants.INTENT_PREFIX
+ "IMPORT_FROM_FILE";
public static final String ACTION_IMPORT_FROM_QR_CODE = Constants.INTENT_PREFIX
+ "IMPORT_FROM_QR_CODE";
public static final String ACTION_IMPORT_FROM_NFC = Constants.INTENT_PREFIX + "IMPORT_FROM_NFC";
public static final String ACTION_KEY_IMPORT = Constants.INTENT_PREFIX + "KEY_IMPORT";
public static final String ACTION_KEY_IMPORT_FROM_QR_CODE = Constants.INTENT_PREFIX
+ "KEY_IMPORT_FROM_QR_CODE";
// Actions for internal use only:
public static final String ACTION_KEY_IMPORT_FROM_FILE = Constants.INTENT_PREFIX
+ "KEY_IMPORT_FROM_FILE";
public static final String ACTION_KEY_IMPORT_FROM_NFC = Constants.INTENT_PREFIX
+ "KEY_IMPORT_FROM_NFC";
// only used by IMPORT
public static final String EXTRA_TEXT = "text";
public static final String EXTRA_KEYRING_BYTES = "keyringBytes";
public static final String EXTRA_KEYRING_BYTES = "keyring_bytes";
// TODO: import keys from server
// public static final String EXTRA_KEY_ID = "keyId";
protected String mImportFilename;
@ -140,35 +143,32 @@ public class ImportKeysActivity extends SherlockFragmentActivity {
* Android Standard Actions
*/
if (Intent.ACTION_VIEW.equals(action)) {
// Android's Action when opening file associated to APG (see AndroidManifest.xml)
// override action to delegate it to APGs ACTION_IMPORT
action = ACTION_IMPORT;
// Android's Action when opening file associated to Keychain (see AndroidManifest.xml)
// override action to delegate it to Keychains ACTION_IMPORT
action = ACTION_KEY_IMPORT;
}
/**
* APG's own Actions
*/
if (ACTION_IMPORT.equals(action)) {
if (ACTION_KEY_IMPORT.equals(action)) {
if ("file".equals(intent.getScheme()) && intent.getDataString() != null) {
mImportFilename = intent.getData().getPath();
mImportData = null;
} else if (extras.containsKey(EXTRA_TEXT)) {
mImportData = intent.getStringExtra(EXTRA_TEXT).getBytes();
mImportFilename = null;
} else if (extras.containsKey(EXTRA_KEYRING_BYTES)) {
mImportData = intent.getByteArrayExtra(EXTRA_KEYRING_BYTES);
mImportFilename = null;
}
loadKeyListFragment();
} else if (ACTION_IMPORT_FROM_FILE.equals(action)) {
} else if (ACTION_KEY_IMPORT_FROM_FILE.equals(action)) {
if ("file".equals(intent.getScheme()) && intent.getDataString() != null) {
mImportFilename = intent.getData().getPath();
mImportData = null;
}
showImportFromFileDialog();
} else if (ACTION_IMPORT_FROM_QR_CODE.equals(action)) {
} else if (ACTION_KEY_IMPORT_FROM_QR_CODE.equals(action)) {
importFromQrCode();
} else if (ACTION_IMPORT_FROM_NFC.equals(action)) {
} else if (ACTION_KEY_IMPORT_FROM_NFC.equals(action)) {
importFromNfc();
}
}
@ -325,7 +325,7 @@ public class ImportKeysActivity extends SherlockFragmentActivity {
Bundle data = new Bundle();
// TODO: check for key type?
// data.putInt(ApgIntentService.IMPORT_KEY_TYPE, Id.type.secret_key);
// data.putInt(KeychainIntentService.IMPORT_KEY_TYPE, Id.type.secret_key);
if (mImportData != null) {
data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES);
@ -349,7 +349,8 @@ public class ImportKeysActivity extends SherlockFragmentActivity {
Bundle returnData = message.getData();
int added = returnData.getInt(KeychainIntentService.RESULT_IMPORT_ADDED);
int updated = returnData.getInt(KeychainIntentService.RESULT_IMPORT_UPDATED);
int updated = returnData
.getInt(KeychainIntentService.RESULT_IMPORT_UPDATED);
int bad = returnData.getInt(KeychainIntentService.RESULT_IMPORT_BAD);
String toastMessage;
if (added > 0 && updated > 0) {

View File

@ -154,7 +154,7 @@ public class KeyListActivity extends SherlockFragmentActivity {
case Id.menu.option.import_from_file: {
Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_FROM_FILE);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_KEY_IMPORT_FROM_FILE);
startActivityForResult(intentImportFromFile, 0);
return true;
}

View File

@ -67,7 +67,7 @@ public class KeyListPublicActivity extends KeyListActivity {
}
case Id.menu.option.import_from_file: {
Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_FROM_FILE);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_KEY_IMPORT_FROM_FILE);
startActivityForResult(intentImportFromFile, 0);
return true;
@ -75,7 +75,7 @@ public class KeyListPublicActivity extends KeyListActivity {
case Id.menu.option.import_from_qr_code: {
Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_FROM_QR_CODE);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_KEY_IMPORT_FROM_QR_CODE);
startActivityForResult(intentImportFromFile, Id.request.import_from_qr_code);
return true;
@ -83,7 +83,7 @@ public class KeyListPublicActivity extends KeyListActivity {
case Id.menu.option.import_from_nfc: {
Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_FROM_NFC);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_KEY_IMPORT_FROM_NFC);
startActivityForResult(intentImportFromFile, 0);
return true;

View File

@ -227,8 +227,8 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
if (mKeyData != null) {
Intent intent = new Intent(KeyServerQueryActivity.this,
ImportKeysActivity.class);
intent.setAction(ImportKeysActivity.ACTION_IMPORT);
intent.putExtra(ImportKeysActivity.EXTRA_TEXT, mKeyData);
intent.setAction(ImportKeysActivity.ACTION_KEY_IMPORT);
intent.putExtra(ImportKeysActivity.EXTRA_KEYRING_BYTES, mKeyData.getBytes());
startActivity(intent);
}
}

View File

@ -29,14 +29,14 @@ import com.actionbarsherlock.app.SherlockFragmentActivity;
public class SelectPublicKeyActivity extends SherlockFragmentActivity {
// Not used in sourcode, but listed in AndroidManifest!
// Actions for internal use only:
public static final String ACTION_SELECT_PUBLIC_KEYS = Constants.INTENT_PREFIX
+ "SELECT_PUBLIC_KEYRINGS";
public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "masterKeyIds";
public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "master_key_ids";
public static final String RESULT_EXTRA_MASTER_KEY_IDS = "masterKeyIds";
public static final String RESULT_EXTRA_USER_IDS = "userIds";
public static final String RESULT_EXTRA_MASTER_KEY_IDS = "master_key_ids";
public static final String RESULT_EXTRA_USER_IDS = "user_ids";
SelectPublicKeyFragment mSelectFragment;

View File

@ -30,14 +30,14 @@ import android.os.Bundle;
public class SelectSecretKeyActivity extends SherlockFragmentActivity {
// Not used in sourcode, but listed in AndroidManifest!
// Actions for internal use only:
public static final String ACTION_SELECT_SECRET_KEY = Constants.INTENT_PREFIX
+ "SELECT_SECRET_KEYRING";
public static final String EXTRA_FILTER_CERTIFY = "filter_certify";
public static final String RESULT_EXTRA_MASTER_KEY_ID = "masterKeyId";
public static final String RESULT_EXTRA_USER_ID = "userId";
public static final String RESULT_EXTRA_MASTER_KEY_ID = "master_key_id";
public static final String RESULT_EXTRA_USER_ID = "user_id";
private boolean mFilterCertify = false;
private SelectSecretKeyFragment mSelectFragment;

View File

@ -30,11 +30,12 @@ import android.content.Intent;
import android.os.Bundle;
public class ShareActivity extends SherlockFragmentActivity {
// Actions for internal use only:
public static final String ACTION_SHARE_KEYRING = Constants.INTENT_PREFIX + "SHARE_KEYRING";
public static final String ACTION_SHARE_KEYRING_WITH_QR_CODE = Constants.INTENT_PREFIX
+ "SHARE_KEYRING_WITH_QR_CODE";
public static final String EXTRA_MASTER_KEY_ID = "masterKeyId";
public static final String EXTRA_MASTER_KEY_ID = "master_key_id";
@Override
public void onCreate(Bundle savedInstanceState) {

View File

@ -115,7 +115,7 @@ public class ShareNfcBeamActivity extends SherlockFragmentActivity implements
byte[] receivedKeyringBytes = msg.getRecords()[0].getPayload();
Intent importIntent = new Intent(this, ImportKeysActivity.class);
importIntent.setAction(ImportKeysActivity.ACTION_IMPORT);
importIntent.setAction(ImportKeysActivity.ACTION_KEY_IMPORT);
importIntent.putExtra(ImportKeysActivity.EXTRA_KEYRING_BYTES, receivedKeyringBytes);
finish();