This commit is contained in:
Daniel Hammann 2014-03-05 17:05:01 +01:00
commit bc5f2a9305
109 changed files with 1849 additions and 2495 deletions

16
.travis.yml Normal file
View File

@ -0,0 +1,16 @@
language: java
jdk: oraclejdk7
before_install:
# Install base Android SDK
- sudo apt-get update -qq
- if [ `uname -m` = x86_64 ]; then sudo apt-get install -qq --force-yes libgd2-xpm ia32-libs; fi
- wget http://dl.google.com/android/android-sdk_r22.3-linux.tgz
- tar xzf android-sdk_r22.3-linux.tgz
- export ANDROID_HOME=$PWD/android-sdk-linux
- export PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
# Install required Android components.
- echo "y" | android update sdk -a --filter build-tools-19.0.1,android-19,platform-tools,extra-android-support,extra-android-m2repository,android-17 --no-ui --force
install: echo "Installation done"
script: gradle assemble -S -q

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.sufficientlysecure.keychain.demo"
android:versionCode="2"
android:versionName="1.1">
android:versionCode="3"
android:versionName="2">
<uses-sdk
android:minSdkVersion="9"

View File

@ -112,11 +112,11 @@ public class IntentActivity extends PreferenceActivity {
byte[] pubkey = null;
try {
pubkey = TEST_PUBKEY.getBytes("UTF-8");
intent.putExtra(OpenKeychainIntents.IMPORT_KEY_EXTRA_KEY_BYTES, pubkey);
startActivity(intent);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
Log.e(Constants.TAG, "UnsupportedEncodingException", e);
}
intent.putExtra(OpenKeychainIntents.IMPORT_KEY_EXTRA_KEY_BYTES, pubkey);
startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(IntentActivity.this, "Activity not found!", Toast.LENGTH_LONG).show();
}

View File

@ -33,7 +33,6 @@ import android.widget.Toast;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpConstants;
import org.openintents.openpgp.util.OpenPgpServiceConnection;
import java.io.ByteArrayInputStream;
@ -73,25 +72,25 @@ public class OpenPgpProviderActivity extends Activity {
mSign.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sign(new Bundle());
sign(new Intent());
}
});
mEncrypt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
encrypt(new Bundle());
encrypt(new Intent());
}
});
mSignAndEncrypt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
signAndEncrypt(new Bundle());
signAndEncrypt(new Intent());
}
});
mDecryptAndVerify.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
decryptAndVerify(new Bundle());
decryptAndVerify(new Intent());
}
});
@ -169,11 +168,11 @@ public class OpenPgpProviderActivity extends Activity {
}
@Override
public void onReturn(Bundle result) {
switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
case OpenPgpConstants.RESULT_CODE_SUCCESS: {
public void onReturn(Intent result) {
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
case OpenPgpApi.RESULT_CODE_SUCCESS: {
try {
Log.d(OpenPgpConstants.TAG, "result: " + os.toByteArray().length
Log.d(OpenPgpApi.TAG, "result: " + os.toByteArray().length
+ " str=" + os.toString("UTF-8"));
if (returnToCiphertextField) {
@ -185,15 +184,15 @@ public class OpenPgpProviderActivity extends Activity {
Log.e(Constants.TAG, "UnsupportedEncodingException", e);
}
if (result.containsKey(OpenPgpConstants.RESULT_SIGNATURE)) {
if (result.hasExtra(OpenPgpApi.RESULT_SIGNATURE)) {
OpenPgpSignatureResult sigResult
= result.getParcelable(OpenPgpConstants.RESULT_SIGNATURE);
= result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
handleSignature(sigResult);
}
break;
}
case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED: {
PendingIntent pi = result.getParcelable(OpenPgpConstants.RESULT_INTENT);
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: {
PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
try {
OpenPgpProviderActivity.this.startIntentSenderForResult(pi.getIntentSender(),
requestCode, null, 0, 0, 0);
@ -202,8 +201,8 @@ public class OpenPgpProviderActivity extends Activity {
}
break;
}
case OpenPgpConstants.RESULT_CODE_ERROR: {
OpenPgpError error = result.getParcelable(OpenPgpConstants.RESULT_ERRORS);
case OpenPgpApi.RESULT_CODE_ERROR: {
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERRORS);
handleError(error);
break;
}
@ -211,46 +210,50 @@ public class OpenPgpProviderActivity extends Activity {
}
}
public void sign(Bundle params) {
params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
public void sign(Intent data) {
data.setAction(OpenPgpApi.ACTION_SIGN);
data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
InputStream is = getInputstream(false);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.sign(params, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN));
api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN));
}
public void encrypt(Bundle params) {
params.putStringArray(OpenPgpConstants.PARAMS_USER_IDS, mEncryptUserIds.getText().toString().split(","));
params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
public void encrypt(Intent data) {
data.setAction(OpenPgpApi.ACTION_ENCRYPT);
data.putExtra(OpenPgpApi.EXTRA_USER_IDS, mEncryptUserIds.getText().toString().split(","));
data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
InputStream is = getInputstream(false);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.encrypt(params, is, os, new MyCallback(true, os, REQUEST_CODE_ENCRYPT));
api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_ENCRYPT));
}
public void signAndEncrypt(Bundle params) {
params.putStringArray(OpenPgpConstants.PARAMS_USER_IDS, mEncryptUserIds.getText().toString().split(","));
params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
public void signAndEncrypt(Intent data) {
data.setAction(OpenPgpApi.ACTION_SIGN_AND_ENCTYPT);
data.putExtra(OpenPgpApi.EXTRA_USER_IDS, mEncryptUserIds.getText().toString().split(","));
data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
InputStream is = getInputstream(false);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.signAndEncrypt(params, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN_AND_ENCRYPT));
api.executeApiAsync(data, is, os, new MyCallback(true, os, REQUEST_CODE_SIGN_AND_ENCRYPT));
}
public void decryptAndVerify(Bundle params) {
params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
public void decryptAndVerify(Intent data) {
data.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
InputStream is = getInputstream(true);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
OpenPgpApi api = new OpenPgpApi(this, mServiceConnection.getService());
api.decryptAndVerify(params, is, os, new MyCallback(false, os, REQUEST_CODE_DECRYPT_AND_VERIFY));
api.executeApiAsync(data, is, os, new MyCallback(false, os, REQUEST_CODE_DECRYPT_AND_VERIFY));
}
@Override
@ -261,29 +264,28 @@ public class OpenPgpProviderActivity extends Activity {
// try again after user interaction
if (resultCode == RESULT_OK) {
/*
* The params originally given to the pgp method are are again
* The data originally given to the pgp method are are again
* returned here to be used when calling again after user interaction.
*
* They also contain results from the user interaction which happened,
* for example selected key ids.
*/
Bundle params = data.getBundleExtra(OpenPgpConstants.PI_RESULT_PARAMS);
switch (requestCode) {
case REQUEST_CODE_SIGN: {
sign(params);
sign(data);
break;
}
case REQUEST_CODE_ENCRYPT: {
encrypt(params);
encrypt(data);
break;
}
case REQUEST_CODE_SIGN_AND_ENCRYPT: {
signAndEncrypt(params);
signAndEncrypt(data);
break;
}
case REQUEST_CODE_DECRYPT_AND_VERIFY: {
decryptAndVerify(params);
decryptAndVerify(data);
break;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -2,5 +2,6 @@
<resources>
<string name="openpgp_list_preference_none">None</string>
<string name="openpgp_install_openkeychain_via">Install OpenKeychain via %s</string>
</resources>

View File

@ -18,68 +18,7 @@ package org.openintents.openpgp;
interface IOpenPgpService {
/**
* General extras
* --------------
*
* Bundle params:
* int api_version (required)
* boolean ascii_armor (request ascii armor for ouput)
*
* returned Bundle:
* int result_code (0, 1, or 2 (see OpenPgpConstants))
* OpenPgpError error (if result_code == 0)
* Intent intent (if result_code == 2)
*
*/
/**
* Sign only
*
* optional params:
* String passphrase (for key passphrase)
*/
Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* Encrypt
*
* Bundle params:
* long[] key_ids
* or
* String[] user_ids (= emails of recipients) (if more than one key has this user_id, a PendingIntent is returned)
*
* optional params:
* String passphrase (for key passphrase)
*/
Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* Sign and encrypt
*
* Bundle params:
* same as in encrypt()
*/
Bundle signAndEncrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* Decrypts and verifies given input bytes. This methods handles encrypted-only, signed-and-encrypted,
* and also signed-only input.
*
* returned Bundle:
* OpenPgpSignatureResult signature_result
*/
Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* Retrieves key ids based on given user ids (=emails)
*
* Bundle params:
* String[] user_ids
*
* returned Bundle:
* long[] key_ids
*/
Bundle getKeyIds(in Bundle params);
// see OpenPgpApi for documentation
Intent execute(in Intent data, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
}

View File

@ -25,10 +25,8 @@ public class OpenPgpSignatureResult implements Parcelable {
// successfully verified signature, with certified public key
public static final int SIGNATURE_SUCCESS_CERTIFIED = 1;
// no public key was found for this signature verification
// you can retrieve the key with
// getKeys(new String[] {String.valueOf(signatureResult.getKeyId)}, true, callback)
public static final int SIGNATURE_UNKNOWN_PUB_KEY = 2;
// successfully verified signature, but with certified public key
// successfully verified signature, but with uncertified public key
public static final int SIGNATURE_SUCCESS_UNCERTIFIED = 3;
int status;
@ -40,24 +38,40 @@ public class OpenPgpSignatureResult implements Parcelable {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public boolean isSignatureOnly() {
return signatureOnly;
}
public void setSignatureOnly(boolean signatureOnly) {
this.signatureOnly = signatureOnly;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public long getKeyId() {
return keyId;
}
public void setKeyId(long keyId) {
this.keyId = keyId;
}
public OpenPgpSignatureResult() {
}
public OpenPgpSignatureResult(int signatureStatus, String signatureUserId,
boolean signatureOnly, long keyId) {
boolean signatureOnly, long keyId) {
this.status = signatureStatus;
this.signatureOnly = signatureOnly;
this.userId = signatureUserId;

View File

@ -17,9 +17,9 @@
package org.openintents.openpgp.util;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
@ -31,104 +31,143 @@ import java.io.OutputStream;
public class OpenPgpApi {
//TODO: fix this documentation
/**
* General extras
* --------------
*
* Intent extras:
* int api_version (required)
* boolean ascii_armor (request ascii armor for ouput)
*
* returned Bundle:
* int result_code (0, 1, or 2 (see OpenPgpApi))
* OpenPgpError error (if result_code == 0)
* Intent intent (if result_code == 2)
*/
/**
* Sign only
*
* optional params:
* String passphrase (for key passphrase)
*/
/**
* Encrypt
*
* Intent extras:
* long[] key_ids
* or
* String[] user_ids (= emails of recipients) (if more than one key has this user_id, a PendingIntent is returned)
*
* optional extras:
* String passphrase (for key passphrase)
*/
/**
* Sign and encrypt
*
* Intent extras:
* same as in encrypt()
*/
/**
* Decrypts and verifies given input bytes. This methods handles encrypted-only, signed-and-encrypted,
* and also signed-only input.
*
* returned Bundle:
* OpenPgpSignatureResult signature_result
*/
/**
* Retrieves key ids based on given user ids (=emails)
*
* Intent extras:
* String[] user_ids
*
* returned Bundle:
* long[] key_ids
*/
public static final String TAG = "OpenPgp API";
public static final int API_VERSION = 2;
public static final String SERVICE_INTENT = "org.openintents.openpgp.IOpenPgpService";
public static final String ACTION_SIGN = "org.openintents.openpgp.action.SIGN";
public static final String ACTION_ENCRYPT = "org.openintents.openpgp.action.ENCRYPT";
public static final String ACTION_SIGN_AND_ENCTYPT = "org.openintents.openpgp.action.SIGN_AND_ENCRYPT";
public static final String ACTION_DECRYPT_VERIFY = "org.openintents.openpgp.action.DECRYPT_VERIFY";
public static final String ACTION_DOWNLOAD_KEYS = "org.openintents.openpgp.action.DOWNLOAD_KEYS";
public static final String ACTION_GET_KEY_IDS = "org.openintents.openpgp.action.GET_KEY_IDS";
/* Bundle params */
public static final String EXTRA_API_VERSION = "api_version";
// SIGN, ENCRYPT, SIGN_ENCRYPT, DECRYPT_VERIFY
// request ASCII Armor for output
// OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53)
public static final String EXTRA_REQUEST_ASCII_ARMOR = "ascii_armor";
// ENCRYPT, SIGN_ENCRYPT
public static final String EXTRA_USER_IDS = "user_ids";
public static final String EXTRA_KEY_IDS = "key_ids";
// optional parameter:
public static final String EXTRA_PASSPHRASE = "passphrase";
/* Service Bundle returns */
public static final String RESULT_CODE = "result_code";
public static final String RESULT_SIGNATURE = "signature";
public static final String RESULT_ERRORS = "error";
public static final String RESULT_INTENT = "intent";
// get actual error object from RESULT_ERRORS
public static final int RESULT_CODE_ERROR = 0;
// success!
public static final int RESULT_CODE_SUCCESS = 1;
// executeServiceMethod intent and do it again with intent
public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2;
IOpenPgpService mService;
Context mContext;
private static final int OPERATION_SIGN = 0;
private static final int OPERATION_ENCRYPT = 1;
private static final int OPERATION_SIGN_ENCRYPT = 2;
private static final int OPERATION_DECRYPT_VERIFY = 3;
private static final int OPERATION_GET_KEY_IDS = 4;
public OpenPgpApi(Context context, IOpenPgpService service) {
this.mContext = context;
this.mService = service;
}
public Bundle sign(InputStream is, final OutputStream os) {
return executeApi(OPERATION_SIGN, new Bundle(), is, os);
}
public Bundle sign(Bundle params, InputStream is, final OutputStream os) {
return executeApi(OPERATION_SIGN, params, is, os);
}
public void sign(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) {
executeApiAsync(OPERATION_SIGN, params, is, os, callback);
}
public Bundle encrypt(InputStream is, final OutputStream os) {
return executeApi(OPERATION_ENCRYPT, new Bundle(), is, os);
}
public Bundle encrypt(Bundle params, InputStream is, final OutputStream os) {
return executeApi(OPERATION_ENCRYPT, params, is, os);
}
public void encrypt(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) {
executeApiAsync(OPERATION_ENCRYPT, params, is, os, callback);
}
public Bundle signAndEncrypt(InputStream is, final OutputStream os) {
return executeApi(OPERATION_SIGN_ENCRYPT, new Bundle(), is, os);
}
public Bundle signAndEncrypt(Bundle params, InputStream is, final OutputStream os) {
return executeApi(OPERATION_SIGN_ENCRYPT, params, is, os);
}
public void signAndEncrypt(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) {
executeApiAsync(OPERATION_SIGN_ENCRYPT, params, is, os, callback);
}
public Bundle decryptAndVerify(InputStream is, final OutputStream os) {
return executeApi(OPERATION_DECRYPT_VERIFY, new Bundle(), is, os);
}
public Bundle decryptAndVerify(Bundle params, InputStream is, final OutputStream os) {
return executeApi(OPERATION_DECRYPT_VERIFY, params, is, os);
}
public void decryptAndVerify(Bundle params, InputStream is, final OutputStream os, IOpenPgpCallback callback) {
executeApiAsync(OPERATION_DECRYPT_VERIFY, params, is, os, callback);
}
public Bundle getKeyIds(Bundle params) {
return executeApi(OPERATION_GET_KEY_IDS, params, null, null);
}
public interface IOpenPgpCallback {
void onReturn(final Bundle result);
void onReturn(final Intent result);
}
private class OpenPgpAsyncTask extends AsyncTask<Void, Integer, Bundle> {
int operationId;
Bundle params;
private class OpenPgpAsyncTask extends AsyncTask<Void, Integer, Intent> {
Intent data;
InputStream is;
OutputStream os;
IOpenPgpCallback callback;
private OpenPgpAsyncTask(int operationId, Bundle params, InputStream is, OutputStream os, IOpenPgpCallback callback) {
this.operationId = operationId;
this.params = params;
private OpenPgpAsyncTask(Intent data, InputStream is, OutputStream os, IOpenPgpCallback callback) {
this.data = data;
this.is = is;
this.os = os;
this.callback = callback;
}
@Override
protected Bundle doInBackground(Void... unused) {
return executeApi(operationId, params, is, os);
protected Intent doInBackground(Void... unused) {
return executeApi(data, is, os);
}
protected void onPostExecute(Bundle result) {
protected void onPostExecute(Intent result) {
callback.onReturn(result);
}
}
private void executeApiAsync(int operationId, Bundle params, InputStream is, OutputStream os, IOpenPgpCallback callback) {
OpenPgpAsyncTask task = new OpenPgpAsyncTask(operationId, params, is, os, callback);
public void executeApiAsync(Intent data, InputStream is, OutputStream os, IOpenPgpCallback callback) {
OpenPgpAsyncTask task = new OpenPgpAsyncTask(data, is, os, callback);
// don't serialize async tasks!
// http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html
@ -139,14 +178,14 @@ public class OpenPgpApi {
}
}
private Bundle executeApi(int operationId, Bundle params, InputStream is, OutputStream os) {
public Intent executeApi(Intent data, InputStream is, OutputStream os) {
try {
params.putInt(OpenPgpConstants.PARAMS_API_VERSION, OpenPgpConstants.API_VERSION);
data.putExtra(EXTRA_API_VERSION, OpenPgpApi.API_VERSION);
Bundle result = null;
Intent result = null;
if (operationId == OPERATION_GET_KEY_IDS) {
result = mService.getKeyIds(params);
if (ACTION_GET_KEY_IDS.equals(data.getAction())) {
result = mService.execute(data, null, null);
return result;
} else {
// send the input and output pfds
@ -155,7 +194,7 @@ public class OpenPgpApi {
@Override
public void onThreadFinished(Thread thread) {
Log.d(OpenPgpConstants.TAG, "Copy to service finished");
Log.d(OpenPgpApi.TAG, "Copy to service finished");
}
});
ParcelFileDescriptor output = ParcelFileDescriptorUtil.pipeTo(os,
@ -163,45 +202,30 @@ public class OpenPgpApi {
@Override
public void onThreadFinished(Thread thread) {
Log.d(OpenPgpConstants.TAG, "Service finished writing!");
Log.d(OpenPgpApi.TAG, "Service finished writing!");
}
});
// blocks until result is ready
switch (operationId) {
case OPERATION_SIGN:
result = mService.sign(params, input, output);
break;
case OPERATION_ENCRYPT:
result = mService.encrypt(params, input, output);
break;
case OPERATION_SIGN_ENCRYPT:
result = mService.signAndEncrypt(params, input, output);
break;
case OPERATION_DECRYPT_VERIFY:
result = mService.decryptAndVerify(params, input, output);
break;
}
result = mService.execute(data, input, output);
// close() is required to halt the TransferThread
output.close();
// set class loader to current context to allow unparcelling
// of OpenPgpError and OpenPgpSignatureResult
// http://stackoverflow.com/a/3806769
result.setClassLoader(mContext.getClassLoader());
result.setExtrasClassLoader(mContext.getClassLoader());
return result;
}
} catch (Exception e) {
Log.e(OpenPgpConstants.TAG, "Exception", e);
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
Log.e(OpenPgpApi.TAG, "Exception", e);
Intent result = new Intent();
result.putExtra(RESULT_CODE, RESULT_CODE_ERROR);
result.putExtra(RESULT_ERRORS,
new OpenPgpError(OpenPgpError.CLIENT_SIDE_ERROR, e.getMessage()));
return result;
}
}
}

View File

@ -1,54 +0,0 @@
/*
* Copyright (C) 2014 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.openintents.openpgp.util;
public class OpenPgpConstants {
public static final String TAG = "OpenPgp API";
public static final int API_VERSION = 1;
public static final String SERVICE_INTENT = "org.openintents.openpgp.IOpenPgpService";
/* Bundle params */
public static final String PARAMS_API_VERSION = "api_version";
// request ASCII Armor for output
// OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53)
public static final String PARAMS_REQUEST_ASCII_ARMOR = "ascii_armor";
// (for encrypt method)
public static final String PARAMS_USER_IDS = "user_ids";
public static final String PARAMS_KEY_IDS = "key_ids";
// optional parameter:
public static final String PARAMS_PASSPHRASE = "passphrase";
/* Service Bundle returns */
public static final String RESULT_CODE = "result_code";
public static final String RESULT_SIGNATURE = "signature";
public static final String RESULT_ERRORS = "error";
public static final String RESULT_INTENT = "intent";
// get actual error object from RESULT_ERRORS
public static final int RESULT_CODE_ERROR = 0;
// success!
public static final int RESULT_CODE_SUCCESS = 1;
// executeServiceMethod intent and do it again with params from intent
public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2;
/* PendingIntent returns */
public static final String PI_RESULT_PARAMS = "params";
}

View File

@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
@ -30,18 +31,24 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.TextView;
import org.sufficientlysecure.keychain.api.R;
import java.util.ArrayList;
import java.util.List;
import org.sufficientlysecure.keychain.api.R;
/**
* Does not extend ListPreference, but is very similar to it!
* http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/preference/ListPreference.java/?v=source
*/
public class OpenPgpListPreference extends DialogPreference {
private ArrayList<OpenPgpProviderEntry> mProviderList = new ArrayList<OpenPgpProviderEntry>();
private static final String OPENKEYCHAIN_PACKAGE = "org.sufficientlysecure.keychain";
private static final String MARKET_INTENT_URI_BASE = "market://details?id=%s";
private static final Intent MARKET_INTENT = new Intent(Intent.ACTION_VIEW, Uri.parse(
String.format(MARKET_INTENT_URI_BASE, OPENKEYCHAIN_PACKAGE)));
private ArrayList<OpenPgpProviderEntry> mLegacyList = new ArrayList<OpenPgpProviderEntry>();
private ArrayList<OpenPgpProviderEntry> mList = new ArrayList<OpenPgpProviderEntry>();
private String mSelectedPackage;
public OpenPgpListPreference(Context context, AttributeSet attrs) {
@ -59,16 +66,25 @@ public class OpenPgpListPreference extends DialogPreference {
* @param simpleName
* @param icon
*/
public void addProvider(int position, String packageName, String simpleName, Drawable icon) {
mProviderList.add(position, new OpenPgpProviderEntry(packageName, simpleName, icon));
public void addLegacyProvider(int position, String packageName, String simpleName, Drawable icon) {
mLegacyList.add(position, new OpenPgpProviderEntry(packageName, simpleName, icon));
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
// get providers
mProviderList.clear();
Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT);
mList.clear();
// add "none"-entry
mList.add(0, new OpenPgpProviderEntry("",
getContext().getString(R.string.openpgp_list_preference_none),
getContext().getResources().getDrawable(R.drawable.ic_action_cancel_launchersize)));
// add all additional (legacy) providers
mList.addAll(mLegacyList);
// search for OpenPGP providers...
ArrayList<OpenPgpProviderEntry> providerList = new ArrayList<OpenPgpProviderEntry>();
Intent intent = new Intent(OpenPgpApi.SERVICE_INTENT);
List<ResolveInfo> resInfo = getContext().getPackageManager().queryIntentServices(intent, 0);
if (!resInfo.isEmpty()) {
for (ResolveInfo resolveInfo : resInfo) {
@ -80,25 +96,40 @@ public class OpenPgpListPreference extends DialogPreference {
.getPackageManager()));
Drawable icon = resolveInfo.serviceInfo.loadIcon(getContext().getPackageManager());
mProviderList.add(new OpenPgpProviderEntry(packageName, simpleName, icon));
providerList.add(new OpenPgpProviderEntry(packageName, simpleName, icon));
}
}
// add "none"-entry
mProviderList.add(0, new OpenPgpProviderEntry("",
getContext().getString(R.string.openpgp_list_preference_none),
getContext().getResources().getDrawable(R.drawable.ic_action_cancel_launchersize)));
if (providerList.isEmpty()) {
// add install links if provider list is empty
resInfo = getContext().getPackageManager().queryIntentActivities
(MARKET_INTENT, 0);
for (ResolveInfo resolveInfo : resInfo) {
Intent marketIntent = new Intent(MARKET_INTENT);
marketIntent.setPackage(resolveInfo.activityInfo.packageName);
Drawable icon = resolveInfo.activityInfo.loadIcon(getContext().getPackageManager());
String marketName = String.valueOf(resolveInfo.activityInfo.applicationInfo
.loadLabel(getContext().getPackageManager()));
String simpleName = String.format(getContext().getString(R.string
.openpgp_install_openkeychain_via), marketName);
mList.add(new OpenPgpProviderEntry(OPENKEYCHAIN_PACKAGE, simpleName,
icon, marketIntent));
}
} else {
// add provider
mList.addAll(providerList);
}
// Init ArrayAdapter with OpenPGP Providers
ListAdapter adapter = new ArrayAdapter<OpenPgpProviderEntry>(getContext(),
android.R.layout.select_dialog_singlechoice, android.R.id.text1, mProviderList) {
android.R.layout.select_dialog_singlechoice, android.R.id.text1, mList) {
public View getView(int position, View convertView, ViewGroup parent) {
// User super class to create the View
View v = super.getView(position, convertView, parent);
TextView tv = (TextView) v.findViewById(android.R.id.text1);
// Put the image on the TextView
tv.setCompoundDrawablesWithIntrinsicBounds(mProviderList.get(position).icon, null,
tv.setCompoundDrawablesWithIntrinsicBounds(mList.get(position).icon, null,
null, null);
// Add margin between image and text (support various screen densities)
@ -114,7 +145,22 @@ public class OpenPgpListPreference extends DialogPreference {
@Override
public void onClick(DialogInterface dialog, int which) {
mSelectedPackage = mProviderList.get(which).packageName;
OpenPgpProviderEntry entry = mList.get(which);
if (entry.intent != null) {
/*
* Intents are called as activity
*
* Current approach is to assume the user installed the app.
* If he does not, the selected package is not valid.
*
* However applications should always consider this could happen,
* as the user might remove the currently used OpenPGP app.
*/
getContext().startActivity(entry.intent);
}
mSelectedPackage = entry.packageName;
/*
* Clicking on an item simulates the positive button click, and dismisses
@ -144,9 +190,9 @@ public class OpenPgpListPreference extends DialogPreference {
}
private int getIndexOfProviderList(String packageName) {
for (OpenPgpProviderEntry app : mProviderList) {
for (OpenPgpProviderEntry app : mList) {
if (app.packageName.equals(packageName)) {
return mProviderList.indexOf(app);
return mList.indexOf(app);
}
}
@ -177,7 +223,7 @@ public class OpenPgpListPreference extends DialogPreference {
}
public String getEntryByValue(String packageName) {
for (OpenPgpProviderEntry app : mProviderList) {
for (OpenPgpProviderEntry app : mList) {
if (app.packageName.equals(packageName)) {
return app.simpleName;
}
@ -190,6 +236,7 @@ public class OpenPgpListPreference extends DialogPreference {
private String packageName;
private String simpleName;
private Drawable icon;
private Intent intent;
public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon) {
this.packageName = packageName;
@ -197,6 +244,11 @@ public class OpenPgpListPreference extends DialogPreference {
this.icon = icon;
}
public OpenPgpProviderEntry(String packageName, String simpleName, Drawable icon, Intent intent) {
this(packageName, simpleName, icon);
this.intent = intent;
}
@Override
public String toString() {
return simpleName;

View File

@ -52,7 +52,7 @@ public class OpenPgpUtils {
}
public static boolean isAvailable(Context context) {
Intent intent = new Intent(OpenPgpConstants.SERVICE_INTENT);
Intent intent = new Intent(OpenPgpApi.SERVICE_INTENT);
List<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(intent, 0);
if (!resInfo.isEmpty()) {
return true;

View File

@ -81,21 +81,21 @@ public class ParcelFileDescriptorUtil {
}
mOut.flush(); // just to be safe
} catch (IOException e) {
//Log.e(OpenPgpConstants.TAG, "TransferThread" + getId() + ": writing failed", e);
//Log.e(OpenPgpApi.TAG, "TransferThread" + getId() + ": writing failed", e);
} finally {
try {
mIn.close();
} catch (IOException e) {
//Log.e(OpenPgpConstants.TAG, "TransferThread" + getId(), e);
//Log.e(OpenPgpApi.TAG, "TransferThread" + getId(), e);
}
try {
mOut.close();
} catch (IOException e) {
//Log.e(OpenPgpConstants.TAG, "TransferThread" + getId(), e);
//Log.e(OpenPgpApi.TAG, "TransferThread" + getId(), e);
}
}
if (mListener != null) {
//Log.d(OpenPgpConstants.TAG, "TransferThread " + getId() + " finished!");
//Log.d(OpenPgpApi.TAG, "TransferThread " + getId() + " finished!");
mListener.onThreadFinished(this);
}
}

View File

@ -3,7 +3,7 @@ apply plugin: 'android'
dependencies {
compile 'com.android.support:support-v4:19.0.1'
compile 'com.android.support:appcompat-v7:19.0.1'
compile project(':libraries:keychain-api-library')
compile project(':OpenPGP-Keychain-API:libraries:keychain-api-library')
compile project(':libraries:HtmlTextView')
compile project(':libraries:StickyListHeaders:library')
compile project(':libraries:AndroidBootstrap')

View File

@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.sufficientlysecure.keychain"
android:installLocation="auto"
android:versionCode="23100"
android:versionName="2.3.1">
android:versionCode="23102"
android:versionName="2.3.1 beta2">
<!--
General remarks
@ -22,7 +22,8 @@
Remarks about the ugly android:pathPattern:
- We are matching all files with a specific file ending.
This is done in an ugly way because of Android limitations.
Read http://stackoverflow.com/questions/1733195/android-intent-filter-for-a-particular-file-extension and http://stackoverflow.com/questions/3400072/pathpattern-to-match-file-extension-does-not-work-if-a-period-exists-elsewhere-i/8599921
Read http://stackoverflow.com/questions/1733195/android-intent-filter-for-a-particular-file-extension
and http://stackoverflow.com/questions/3400072/pathpattern-to-match-file-extension-does-not-work-if-a-period-exists-elsewhere-i/8599921
for more information.
- Do _not_ set mimeType for gpg!
Cyanogenmod's file manager will only show Keychain for gpg files if no mimeType is set!

View File

@ -18,8 +18,8 @@
package org.sufficientlysecure.keychain.pgp;
import android.content.Context;
import android.os.Bundle;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.spongycastle.bcpg.ArmoredInputStream;
import org.spongycastle.bcpg.SignatureSubpacketTags;
import org.spongycastle.openpgp.PGPCompressedData;
@ -36,6 +36,7 @@ import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureList;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
@ -53,7 +54,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
@ -75,9 +76,10 @@ public class PgpDecryptVerify {
private InputData data;
private OutputStream outStream;
private ProgressDialogUpdater progress;
boolean assumeSymmetric;
String passphrase;
private ProgressDialogUpdater progressDialogUpdater;
private boolean assumeSymmetric;
private String passphrase;
private long enforcedKeyId;
private PgpDecryptVerify(Builder builder) {
// private Constructor can only be called from Builder
@ -85,9 +87,10 @@ public class PgpDecryptVerify {
this.data = builder.data;
this.outStream = builder.outStream;
this.progress = builder.progress;
this.progressDialogUpdater = builder.progressDialogUpdater;
this.assumeSymmetric = builder.assumeSymmetric;
this.passphrase = builder.passphrase;
this.enforcedKeyId = builder.enforcedKeyId;
}
public static class Builder {
@ -97,9 +100,10 @@ public class PgpDecryptVerify {
private OutputStream outStream;
// optional
private ProgressDialogUpdater progress = null;
private ProgressDialogUpdater progressDialogUpdater = null;
private boolean assumeSymmetric = false;
private String passphrase = "";
private long enforcedKeyId = 0;
public Builder(Context context, InputData data, OutputStream outStream) {
this.context = context;
@ -107,8 +111,8 @@ public class PgpDecryptVerify {
this.outStream = outStream;
}
public Builder progress(ProgressDialogUpdater progress) {
this.progress = progress;
public Builder progressDialogUpdater(ProgressDialogUpdater progressDialogUpdater) {
this.progressDialogUpdater = progressDialogUpdater;
return this;
}
@ -122,20 +126,32 @@ public class PgpDecryptVerify {
return this;
}
/**
* Allow this key id alone for decryption.
* This means only ciphertexts encrypted for this private key can be decrypted.
*
* @param enforcedKeyId
* @return
*/
public Builder enforcedKeyId(long enforcedKeyId) {
this.enforcedKeyId = enforcedKeyId;
return this;
}
public PgpDecryptVerify build() {
return new PgpDecryptVerify(this);
}
}
public void updateProgress(int message, int current, int total) {
if (progress != null) {
progress.setProgress(message, current, total);
if (progressDialogUpdater != null) {
progressDialogUpdater.setProgress(message, current, total);
}
}
public void updateProgress(int current, int total) {
if (progress != null) {
progress.setProgress(current, total);
if (progressDialogUpdater != null) {
progressDialogUpdater.setProgress(current, total);
}
}
@ -177,9 +193,8 @@ public class PgpDecryptVerify {
* @throws PGPException
* @throws SignatureException
*/
public Bundle execute()
public PgpDecryptVerifyResult execute()
throws IOException, PgpGeneralException, PGPException, SignatureException {
// automatically works with ascii armor input and binary
InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
if (in instanceof ArmoredInputStream) {
@ -207,9 +222,9 @@ public class PgpDecryptVerify {
* @throws PGPException
* @throws SignatureException
*/
private Bundle decryptVerify(InputStream in)
private PgpDecryptVerifyResult decryptVerify(InputStream in)
throws IOException, PgpGeneralException, PGPException, SignatureException {
Bundle returnData = new Bundle();
PgpDecryptVerifyResult returnData = new PgpDecryptVerifyResult();
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
@ -277,9 +292,40 @@ public class PgpDecryptVerify {
PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj;
secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, encData.getKeyID());
if (secretKey != null) {
// secret key exists in database
// allow only a specific key for decryption?
if (enforcedKeyId != 0) {
// TODO: improve this code! get master key directly!
PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, encData.getKeyID());
long masterKeyId = PgpKeyHelper.getMasterKey(secretKeyRing).getKeyID();
Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID());
Log.d(Constants.TAG, "enforcedKeyId: " + enforcedKeyId);
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
if (enforcedKeyId != masterKeyId) {
throw new PgpGeneralException(context.getString(R.string.error_no_secret_key_found));
}
}
pbe = encData;
// if no passphrase was explicitly set try to get it from the cache service
if (passphrase == null) {
// returns "" if key has no passphrase
passphrase = PassphraseCacheService.getCachedPassphrase(context, encData.getKeyID());
// if passphrase was not cached, return here indicating that a passphrase is missing!
if (passphrase == null) {
returnData.setKeyPassphraseNeeded(true);
return returnData;
}
}
break;
}
}
}
@ -317,6 +363,7 @@ public class PgpDecryptVerify {
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
Object dataChunk = plainFact.nextObject();
PGPOnePassSignature signature = null;
OpenPgpSignatureResult signatureResult = null;
PGPPublicKey signatureKey = null;
int signatureIndex = -1;
@ -334,7 +381,7 @@ public class PgpDecryptVerify {
if (dataChunk instanceof PGPOnePassSignatureList) {
updateProgress(R.string.progress_processing_signature, currentProgress, 100);
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE, true);
signatureResult = new OpenPgpSignatureResult();
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk;
for (int i = 0; i < sigList.size(); ++i) {
signature = sigList.get(i);
@ -354,12 +401,12 @@ public class PgpDecryptVerify {
if (signKeyRing != null) {
userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
}
returnData.putString(KeychainIntentService.RESULT_SIGNATURE_USER_ID, userId);
signatureResult.setUserId(userId);
break;
}
}
returnData.putLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, signatureKeyId);
signatureResult.setKeyId(signatureKeyId);
if (signature != null) {
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
@ -367,7 +414,7 @@ public class PgpDecryptVerify {
signature.init(contentVerifierBuilderProvider, signatureKey);
} else {
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN, true);
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY);
}
dataChunk = plainFact.nextObject();
@ -405,8 +452,7 @@ public class PgpDecryptVerify {
try {
signature.update(buffer, 0, n);
} catch (SignatureException e) {
returnData
.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, false);
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
signature = null;
}
}
@ -430,17 +476,20 @@ public class PgpDecryptVerify {
PGPSignature messageSignature = signatureList.get(signatureIndex);
// these are not cleartext signatures!
returnData.putBoolean(KeychainIntentService.RESULT_CLEARTEXT_SIGNATURE_ONLY, false);
// TODO: what about binary signatures?
signatureResult.setSignatureOnly(false);
//Now check binding signatures
boolean keyBinding_isok = verifyKeyBinding(context, messageSignature, signatureKey);
boolean sig_isok = signature.verify(messageSignature);
boolean validKeyBinding = verifyKeyBinding(context, messageSignature, signatureKey);
boolean validSignature = signature.verify(messageSignature);
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, keyBinding_isok & sig_isok);
// TODO: implement CERTIFIED!
if (validKeyBinding & validSignature) {
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED);
}
}
}
// TODO: test if this integrity really check works!
if (encryptedData.isIntegrityProtected()) {
updateProgress(R.string.progress_verifying_integrity, 95, 100);
@ -455,9 +504,12 @@ public class PgpDecryptVerify {
} else {
// no integrity check
Log.e(Constants.TAG, "Encrypted data was not integrity protected!");
// TODO: inform user?
}
updateProgress(R.string.progress_done, 100, 100);
returnData.setSignatureResult(signatureResult);
return returnData;
}
@ -474,11 +526,12 @@ public class PgpDecryptVerify {
* @throws PGPException
* @throws SignatureException
*/
private Bundle verifyCleartextSignature(ArmoredInputStream aIn)
private PgpDecryptVerifyResult verifyCleartextSignature(ArmoredInputStream aIn)
throws IOException, PgpGeneralException, PGPException, SignatureException {
Bundle returnData = new Bundle();
PgpDecryptVerifyResult returnData = new PgpDecryptVerifyResult();
OpenPgpSignatureResult signatureResult = new OpenPgpSignatureResult();
// cleartext signatures are never encrypted ;)
returnData.putBoolean(KeychainIntentService.RESULT_CLEARTEXT_SIGNATURE_ONLY, true);
signatureResult.setSignatureOnly(true);
ByteArrayOutputStream out = new ByteArrayOutputStream();
@ -504,8 +557,6 @@ public class PgpDecryptVerify {
byte[] clearText = out.toByteArray();
outStream.write(clearText);
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE, true);
updateProgress(R.string.progress_processing_signature, 60, 100);
PGPObjectFactory pgpFact = new PGPObjectFactory(aIn);
@ -533,15 +584,15 @@ public class PgpDecryptVerify {
if (signKeyRing != null) {
userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
}
returnData.putString(KeychainIntentService.RESULT_SIGNATURE_USER_ID, userId);
signatureResult.setUserId(userId);
break;
}
}
returnData.putLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, signatureKeyId);
signatureResult.setKeyId(signatureKeyId);
if (signature == null) {
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN, true);
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY);
updateProgress(R.string.progress_done, 100, 100);
return returnData;
}
@ -569,47 +620,52 @@ public class PgpDecryptVerify {
} while (lookAhead != -1);
}
boolean sig_isok = signature.verify();
//Now check binding signatures
boolean keyBinding_isok = verifyKeyBinding(context, signature, signatureKey);
boolean validKeyBinding = verifyKeyBinding(context, signature, signatureKey);
boolean validSignature = signature.verify();
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, sig_isok & keyBinding_isok);
if (validSignature & validKeyBinding) {
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED);
}
// TODO: what about SIGNATURE_SUCCESS_CERTIFIED and SIGNATURE_ERROR????
updateProgress(R.string.progress_done, 100, 100);
returnData.setSignatureResult(signatureResult);
return returnData;
}
private static boolean verifyKeyBinding(Context context, PGPSignature signature, PGPPublicKey signatureKey) {
long signatureKeyId = signature.getKeyID();
boolean keyBinding_isok = false;
String userId = null;
boolean validKeyBinding = false;
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(context,
signatureKeyId);
PGPPublicKey mKey = null;
if (signKeyRing != null) {
mKey = PgpKeyHelper.getMasterKey(signKeyRing);
}
if (signature.getKeyID() != mKey.getKeyID()) {
keyBinding_isok = verifyKeyBinding(mKey, signatureKey);
validKeyBinding = verifyKeyBinding(mKey, signatureKey);
} else { //if the key used to make the signature was the master key, no need to check binding sigs
keyBinding_isok = true;
validKeyBinding = true;
}
return keyBinding_isok;
return validKeyBinding;
}
private static boolean verifyKeyBinding(PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) {
boolean subkeyBinding_isok = false;
boolean tmp_subkeyBinding_isok = false;
boolean primkeyBinding_isok = false;
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
boolean validSubkeyBinding = false;
boolean validTempSubkeyBinding = false;
boolean validPrimaryKeyBinding = false;
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
Iterator<PGPSignature> itr = signingPublicKey.getSignatures();
subkeyBinding_isok = false;
tmp_subkeyBinding_isok = false;
primkeyBinding_isok = false;
while (itr.hasNext()) { //what does gpg do if the subkey binding is wrong?
//gpg has an invalid subkey binding error on key import I think, but doesn't shout
//about keys without subkey signing. Can't get it to import a slightly broken one
@ -619,32 +675,36 @@ public class PgpDecryptVerify {
//check and if ok, check primary key binding.
try {
sig.init(contentVerifierBuilderProvider, masterPublicKey);
tmp_subkeyBinding_isok = sig.verifyCertification(masterPublicKey, signingPublicKey);
validTempSubkeyBinding = sig.verifyCertification(masterPublicKey, signingPublicKey);
} catch (PGPException e) {
continue;
} catch (SignatureException e) {
continue;
}
if (tmp_subkeyBinding_isok)
subkeyBinding_isok = true;
if (tmp_subkeyBinding_isok) {
primkeyBinding_isok = verifyPrimaryBinding(sig.getUnhashedSubPackets(), masterPublicKey, signingPublicKey);
if (primkeyBinding_isok)
if (validTempSubkeyBinding)
validSubkeyBinding = true;
if (validTempSubkeyBinding) {
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(),
masterPublicKey, signingPublicKey);
if (validPrimaryKeyBinding)
break;
primkeyBinding_isok = verifyPrimaryBinding(sig.getHashedSubPackets(), masterPublicKey, signingPublicKey);
if (primkeyBinding_isok)
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(),
masterPublicKey, signingPublicKey);
if (validPrimaryKeyBinding)
break;
}
}
}
return (subkeyBinding_isok & primkeyBinding_isok);
return (validSubkeyBinding & validPrimaryKeyBinding);
}
private static boolean verifyPrimaryBinding(PGPSignatureSubpacketVector Pkts, PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) {
boolean primkeyBinding_isok = false;
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
private static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector Pkts,
PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) {
boolean validPrimaryKeyBinding = false;
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureList eSigList;
if (Pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) {
@ -660,8 +720,8 @@ public class PgpDecryptVerify {
if (emSig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) {
try {
emSig.init(contentVerifierBuilderProvider, signingPublicKey);
primkeyBinding_isok = emSig.verifyCertification(masterPublicKey, signingPublicKey);
if (primkeyBinding_isok)
validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey);
if (validPrimaryKeyBinding)
break;
} catch (PGPException e) {
continue;
@ -671,7 +731,8 @@ public class PgpDecryptVerify {
}
}
}
return primkeyBinding_isok;
return validPrimaryKeyBinding;
}
/**

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2014 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.pgp;
import android.os.Parcel;
import android.os.Parcelable;
import org.openintents.openpgp.OpenPgpSignatureResult;
public class PgpDecryptVerifyResult implements Parcelable {
boolean symmetricPassphraseNeeded;
boolean keyPassphraseNeeded;
OpenPgpSignatureResult signatureResult;
public boolean isSymmetricPassphraseNeeded() {
return symmetricPassphraseNeeded;
}
public void setSymmetricPassphraseNeeded(boolean symmetricPassphraseNeeded) {
this.symmetricPassphraseNeeded = symmetricPassphraseNeeded;
}
public boolean isKeyPassphraseNeeded() {
return keyPassphraseNeeded;
}
public void setKeyPassphraseNeeded(boolean keyPassphraseNeeded) {
this.keyPassphraseNeeded = keyPassphraseNeeded;
}
public OpenPgpSignatureResult getSignatureResult() {
return signatureResult;
}
public void setSignatureResult(OpenPgpSignatureResult signatureResult) {
this.signatureResult = signatureResult;
}
public PgpDecryptVerifyResult() {
}
public PgpDecryptVerifyResult(PgpDecryptVerifyResult b) {
this.symmetricPassphraseNeeded = b.symmetricPassphraseNeeded;
this.keyPassphraseNeeded = b.keyPassphraseNeeded;
this.signatureResult = b.signatureResult;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (symmetricPassphraseNeeded ? 1 : 0));
dest.writeByte((byte) (keyPassphraseNeeded ? 1 : 0));
dest.writeParcelable(signatureResult, 0);
}
public static final Creator<PgpDecryptVerifyResult> CREATOR = new Creator<PgpDecryptVerifyResult>() {
public PgpDecryptVerifyResult createFromParcel(final Parcel source) {
PgpDecryptVerifyResult vr = new PgpDecryptVerifyResult();
vr.symmetricPassphraseNeeded = source.readByte() == 1;
vr.keyPassphraseNeeded = source.readByte() == 1;
vr.signatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
return vr;
}
public PgpDecryptVerifyResult[] newArray(final int size) {
return new PgpDecryptVerifyResult[size];
}
};
}

View File

@ -44,6 +44,7 @@ import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpImportExport;
import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
@ -181,13 +182,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
// decrypt/verify
public static final String RESULT_DECRYPTED_STRING = "decrypted_message";
public static final String RESULT_DECRYPTED_BYTES = "decrypted_data";
public static final String RESULT_SIGNATURE = "signature";
public static final String RESULT_SIGNATURE_KEY_ID = "signature_key_id";
public static final String RESULT_SIGNATURE_USER_ID = "signature_user_id";
public static final String RESULT_CLEARTEXT_SIGNATURE_ONLY = "signature_only";
public static final String RESULT_SIGNATURE_SUCCESS = "signature_success";
public static final String RESULT_SIGNATURE_UNKNOWN = "signature_unknown";
public static final String RESULT_DECRYPT_VERIFY_RESULT = "signature";
// import
public static final String RESULT_IMPORT_ADDED = "added";
@ -203,8 +198,16 @@ public class KeychainIntentService extends IntentService implements ProgressDial
Messenger mMessenger;
private boolean mIsCanceled;
public KeychainIntentService() {
super("ApgService");
super("KeychainIntentService");
}
@Override
public void onDestroy() {
super.onDestroy();
this.mIsCanceled = true;
}
/**
@ -481,15 +484,17 @@ public class KeychainIntentService extends IntentService implements ProgressDial
// verifyText and decrypt returning additional resultData values for the
// verification of signatures
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, outStream);
builder.progress(this);
builder.progressDialogUpdater(this);
builder.assumeSymmetric(assumeSymmetricEncryption)
.passphrase(PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
resultData = builder.build().execute();
PgpDecryptVerifyResult decryptVerifyResult = builder.build().execute();
outStream.close();
resultData.putParcelable(RESULT_DECRYPT_VERIFY_RESULT, decryptVerifyResult);
/* Output */
switch (target) {
@ -815,6 +820,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial
}
private void sendErrorToHandler(Exception e) {
// Service was canceled. Do not send error to handler.
if (this.mIsCanceled)
return;
Log.e(Constants.TAG, "ApgService Exception: ", e);
e.printStackTrace();
@ -824,6 +833,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial
}
private void sendMessageToHandler(Integer arg1, Integer arg2, Bundle data) {
// Service was canceled. Do not send message to handler.
if (this.mIsCanceled)
return;
Message msg = Message.obtain();
msg.arg1 = arg1;
if (arg2 != null) {
@ -851,10 +864,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial
}
/**
* Set progress of ProgressDialog by sending message to handler on UI thread
* Set progressDialogUpdater of ProgressDialog by sending message to handler on UI thread
*/
public void setProgress(String message, int progress, int max) {
Log.d(Constants.TAG, "Send message by setProgress with progress=" + progress + ", max="
Log.d(Constants.TAG, "Send message by setProgress with progressDialogUpdater=" + progress + ", max="
+ max);
Bundle data = new Bundle();

View File

@ -21,6 +21,8 @@ import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.R;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@ -55,9 +57,15 @@ public class KeychainIntentServiceHandler extends Handler {
}
public KeychainIntentServiceHandler(Activity activity, int progressDialogMessageId, int progressDialogStyle) {
this(activity, progressDialogMessageId, progressDialogStyle, false, null);
}
public KeychainIntentServiceHandler(Activity activity, int progressDialogMessageId,
int progressDialogStyle, boolean cancelable,
OnCancelListener onCancelListener) {
this.mActivity = activity;
this.mProgressDialogFragment = ProgressDialogFragment.newInstance(progressDialogMessageId,
progressDialogStyle);
progressDialogStyle, cancelable, onCancelListener);
}
public void showProgressDialog(FragmentActivity activity) {

View File

@ -21,21 +21,21 @@ import android.app.PendingIntent;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import org.openintents.openpgp.IOpenPgpService;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpConstants;
import org.openintents.openpgp.util.OpenPgpApi;
import org.spongycastle.util.Arrays;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
@ -48,7 +48,7 @@ public class OpenPgpService extends RemoteService {
private static final int PRIVATE_REQUEST_CODE_PASSPHRASE = 551;
private static final int PRIVATE_REQUEST_CODE_USER_IDS = 552;
private static final int PRIVATE_REQUEST_CODE_GET_KEYS = 553;
/**
* Search database for key ids based on emails.
@ -56,7 +56,7 @@ public class OpenPgpService extends RemoteService {
* @param encryptionUserIds
* @return
*/
private Bundle getKeyIdsFromEmails(Bundle params, String[] encryptionUserIds) {
private Intent getKeyIdsFromEmails(Intent data, String[] encryptionUserIds) {
// find key ids to given emails in database
ArrayList<Long> keyIds = new ArrayList<Long>();
@ -91,20 +91,20 @@ public class OpenPgpService extends RemoteService {
// allow the user to verify pub key selection
if (missingUserIdsCheck || dublicateUserIdsCheck) {
// build PendingIntent for passphrase input
// build PendingIntent
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS);
intent.putExtra(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray);
intent.putExtra(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds);
intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, dublicateUserIds);
intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_USER_IDS, intent, 0);
// return PendingIntent to be executed by client
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED);
result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi);
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
return result;
}
@ -113,44 +113,44 @@ public class OpenPgpService extends RemoteService {
return null;
}
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS);
result.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS, keyIdsArray);
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
result.putExtra(OpenPgpApi.EXTRA_KEY_IDS, keyIdsArray);
return result;
}
private Bundle getPassphraseBundleIntent(Bundle params, long keyId) {
private Intent getPassphraseBundleIntent(Intent data, long keyId) {
// build PendingIntent for passphrase input
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_CACHE_PASSPHRASE);
intent.putExtra(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId);
// pass params through to activity that it can be returned again later to repeat pgp operation
intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_PASSPHRASE, intent, 0);
// return PendingIntent to be executed by client
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED);
result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi);
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
return result;
}
private Bundle signImpl(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output,
AppSettings appSettings) {
private Intent signImpl(Intent data, ParcelFileDescriptor input,
ParcelFileDescriptor output, AppSettings appSettings) {
try {
boolean asciiArmor = params.getBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
boolean asciiArmor = data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
// get passphrase from cache, if key has "no" passphrase, this returns an empty String
String passphrase;
if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) {
passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE);
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE);
} else {
passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId());
}
if (passphrase == null) {
// get PendingIntent for passphrase input, add it to given params and return to client
Bundle passphraseBundle = getPassphraseBundleIntent(params, appSettings.getKeyId());
Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId());
return passphraseBundle;
}
@ -174,43 +174,42 @@ public class OpenPgpService extends RemoteService {
os.close();
}
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS);
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
return result;
} catch (Exception e) {
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
result.putExtra(OpenPgpApi.RESULT_ERRORS,
new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
return result;
}
}
private Bundle encryptAndSignImpl(Bundle params, ParcelFileDescriptor input,
ParcelFileDescriptor output, AppSettings appSettings,
boolean sign) {
private Intent encryptAndSignImpl(Intent data, ParcelFileDescriptor input,
ParcelFileDescriptor output, AppSettings appSettings, boolean sign) {
try {
boolean asciiArmor = params.getBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
boolean asciiArmor = data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
long[] keyIds;
if (params.containsKey(OpenPgpConstants.PARAMS_KEY_IDS)) {
keyIds = params.getLongArray(OpenPgpConstants.PARAMS_KEY_IDS);
} else if (params.containsKey(OpenPgpConstants.PARAMS_USER_IDS)) {
if (data.hasExtra(OpenPgpApi.EXTRA_KEY_IDS)) {
keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS);
} else if (data.hasExtra(OpenPgpApi.EXTRA_USER_IDS)) {
// get key ids based on given user ids
String[] userIds = params.getStringArray(OpenPgpConstants.PARAMS_USER_IDS);
String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS);
// give params through to activity...
Bundle result = getKeyIdsFromEmails(params, userIds);
Intent result = getKeyIdsFromEmails(data, userIds);
if (result.getInt(OpenPgpConstants.RESULT_CODE, 0) == OpenPgpConstants.RESULT_CODE_SUCCESS) {
keyIds = result.getLongArray(OpenPgpConstants.PARAMS_KEY_IDS);
if (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0) == OpenPgpApi.RESULT_CODE_SUCCESS) {
keyIds = result.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS);
} else {
// if not success -> result contains a PendingIntent for user interaction
return result;
}
} else {
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
result.putExtra(OpenPgpApi.RESULT_ERRORS,
new OpenPgpError(OpenPgpError.GENERIC_ERROR, "Missing parameter user_ids or key_ids!"));
return result;
}
@ -235,15 +234,15 @@ public class OpenPgpService extends RemoteService {
if (sign) {
String passphrase;
if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) {
passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE);
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE);
} else {
passphrase = PassphraseCacheService.getCachedPassphrase(getContext(),
appSettings.getKeyId());
}
if (passphrase == null) {
// get PendingIntent for passphrase input, add it to given params and return to client
Bundle passphraseBundle = getPassphraseBundleIntent(params, appSettings.getKeyId());
Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId());
return passphraseBundle;
}
@ -263,144 +262,88 @@ public class OpenPgpService extends RemoteService {
os.close();
}
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS);
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
return result;
} catch (Exception e) {
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
result.putExtra(OpenPgpApi.RESULT_ERRORS,
new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
return result;
}
}
private Bundle decryptAndVerifyImpl(Bundle params, ParcelFileDescriptor input,
private Intent decryptAndVerifyImpl(Intent data, ParcelFileDescriptor input,
ParcelFileDescriptor output, AppSettings appSettings) {
try {
// Get Input- and OutputStream from ParcelFileDescriptor
InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
Bundle result = new Bundle();
Intent result = new Intent();
try {
// TODO:
// fix the mess: http://stackoverflow.com/questions/148130/how-do-i-peek-at-the-first-two-bytes-in-an-inputstream
// should we allow to decrypt everything under every key id or only the one set?
// TODO: instead of trying to get the passphrase before
// pause stream when passphrase is missing and then resume
// TODO: put this code into PgpDecryptVerify class
// TODO: This allows to decrypt messages with ALL secret keys, not only the one for the
// app, Fix this?
// String passphrase = null;
// if (!signedOnly) {
// // BEGIN Get key
// // TODO: this input stream is consumed after PgpMain.getDecryptionKeyId()... do it
// // better!
// InputStream inputStream2 = new ByteArrayInputStream(inputBytes);
//
// // TODO: duplicates functions from DecryptActivity!
// long secretKeyId;
// try {
// if (inputStream2.markSupported()) {
// // should probably set this to the max size of two
// // pgpF objects, if it even needs to be anything other
// // than 0.
// inputStream2.mark(200);
// }
// secretKeyId = PgpHelper.getDecryptionKeyId(this, inputStream2);
// if (secretKeyId == Id.key.none) {
// throw new PgpGeneralException(getString(R.string.error_no_secret_key_found));
// }
// } catch (NoAsymmetricEncryptionException e) {
// if (inputStream2.markSupported()) {
// inputStream2.reset();
// }
// secretKeyId = Id.key.symmetric;
// if (!PgpDecryptVerify.hasSymmetricEncryption(this, inputStream2)) {
// throw new PgpGeneralException(
// getString(R.string.error_no_known_encryption_found));
// }
// // we do not support symmetric decryption from the API!
// throw new Exception("Symmetric decryption is not supported!");
// }
//
// Log.d(Constants.TAG, "secretKeyId " + secretKeyId);
// NOTE: currently this only gets the passphrase for the key set for this client
String passphrase;
if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) {
passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE);
} else {
passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId());
}
if (passphrase == null) {
// get PendingIntent for passphrase input, add it to given params and return to client
Bundle passphraseBundle = getPassphraseBundleIntent(params, appSettings.getKeyId());
return passphraseBundle;
}
String passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE);
long inputLength = is.available();
InputData inputData = new InputData(is, inputLength);
Bundle outputBundle;
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os);
builder.assumeSymmetric(false)
builder.assumeSymmetric(false) // no support for symmetric encryption
.enforcedKeyId(appSettings.getKeyId()) // allow only the private key for this app for decryption
.passphrase(passphrase);
// TODO: this also decrypts with other secret keys that have no passphrase!!!
outputBundle = builder.build().execute();
// TODO: currently does not support binary signed-only content
PgpDecryptVerifyResult decryptVerifyResult = builder.build().execute();
//TODO: instead of using all these wrapping use OpenPgpSignatureResult directly
// in DecryptVerify class and then in DecryptActivity
boolean signature = outputBundle.getBoolean(KeychainIntentService.RESULT_SIGNATURE, false);
if (signature) {
long signatureKeyId = outputBundle
.getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, 0);
String signatureUserId = outputBundle
.getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID);
boolean signatureSuccess = outputBundle
.getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, false);
boolean signatureUnknown = outputBundle
.getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN, false);
boolean signatureOnly = outputBundle
.getBoolean(KeychainIntentService.RESULT_CLEARTEXT_SIGNATURE_ONLY, false);
if (decryptVerifyResult.isKeyPassphraseNeeded()) {
// get PendingIntent for passphrase input, add it to given params and return to client
Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId());
return passphraseBundle;
} else if (decryptVerifyResult.isSymmetricPassphraseNeeded()) {
throw new PgpGeneralException("Decryption of symmetric content not supported by API!");
}
int signatureStatus = OpenPgpSignatureResult.SIGNATURE_ERROR;
if (signatureSuccess) {
signatureStatus = OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED;
} else if (signatureUnknown) {
signatureStatus = OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY;
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
if (signatureResult != null) {
if (signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY) {
// If signature is unknown we return an additional PendingIntent
// to retrieve the missing key
// TODO!!!
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE);
intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, "todo");
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(),
PRIVATE_REQUEST_CODE_GET_KEYS, intent, 0);
result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
}
OpenPgpSignatureResult sigResult = new OpenPgpSignatureResult(signatureStatus,
signatureUserId, signatureOnly, signatureKeyId);
result.putParcelable(OpenPgpConstants.RESULT_SIGNATURE, sigResult);
result.putExtra(OpenPgpApi.RESULT_SIGNATURE, signatureResult);
}
} finally {
is.close();
os.close();
}
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS);
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
return result;
} catch (Exception e) {
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
result.putExtra(OpenPgpApi.RESULT_ERRORS,
new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
return result;
}
}
private Bundle getKeyIdsImpl(Bundle params) {
private Intent getKeyIdsImpl(Intent data) {
// get key ids based on given user ids
String[] userIds = params.getStringArray(OpenPgpConstants.PARAMS_USER_IDS);
Bundle result = getKeyIdsFromEmails(params, userIds);
String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS);
Intent result = getKeyIdsFromEmails(data, userIds);
return result;
}
@ -410,30 +353,30 @@ public class OpenPgpService extends RemoteService {
* - has supported API version
* - is allowed to call the service (access has been granted)
*
* @param params
* @param data
* @return null if everything is okay, or a Bundle with an error/PendingIntent
*/
private Bundle checkRequirements(Bundle params) {
private Intent checkRequirements(Intent data) {
// params Bundle is required!
if (params == null) {
Bundle result = new Bundle();
if (data == null) {
Intent result = new Intent();
OpenPgpError error = new OpenPgpError(OpenPgpError.GENERIC_ERROR, "params Bundle required!");
result.putParcelable(OpenPgpConstants.RESULT_ERRORS, error);
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putExtra(OpenPgpApi.RESULT_ERRORS, error);
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
return result;
}
// version code is required and needs to correspond to version code of service!
if (params.getInt(OpenPgpConstants.PARAMS_API_VERSION) != OpenPgpConstants.API_VERSION) {
Bundle result = new Bundle();
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != OpenPgpApi.API_VERSION) {
Intent result = new Intent();
OpenPgpError error = new OpenPgpError(OpenPgpError.INCOMPATIBLE_API_VERSIONS, "Incompatible API versions!");
result.putParcelable(OpenPgpConstants.RESULT_ERRORS, error);
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putExtra(OpenPgpApi.RESULT_ERRORS, error);
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
return result;
}
// check if caller is allowed to access openpgp keychain
Bundle result = isAllowed(params);
Intent result = isAllowed(data);
if (result != null) {
return result;
}
@ -445,61 +388,31 @@ public class OpenPgpService extends RemoteService {
private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() {
@Override
public Bundle sign(Bundle params, final ParcelFileDescriptor input, final ParcelFileDescriptor output) {
public Intent execute(Intent data, ParcelFileDescriptor input, ParcelFileDescriptor output) {
Intent errorResult = checkRequirements(data);
if (errorResult != null) {
return errorResult;
}
final AppSettings appSettings = getAppSettings();
Bundle errorResult = checkRequirements(params);
if (errorResult != null) {
return errorResult;
String action = data.getAction();
if (OpenPgpApi.ACTION_SIGN.equals(action)) {
return signImpl(data, input, output, appSettings);
} else if (OpenPgpApi.ACTION_ENCRYPT.equals(action)) {
return encryptAndSignImpl(data, input, output, appSettings, false);
} else if (OpenPgpApi.ACTION_SIGN_AND_ENCTYPT.equals(action)) {
return encryptAndSignImpl(data, input, output, appSettings, true);
} else if (OpenPgpApi.ACTION_DECRYPT_VERIFY.equals(action)) {
return decryptAndVerifyImpl(data, input, output, appSettings);
} else if (OpenPgpApi.ACTION_DOWNLOAD_KEYS.equals(action)) {
// TODO!
return null;
} else if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(action)) {
return getKeyIdsImpl(data);
} else {
return null;
}
return signImpl(params, input, output, appSettings);
}
@Override
public Bundle encrypt(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) {
final AppSettings appSettings = getAppSettings();
Bundle errorResult = checkRequirements(params);
if (errorResult != null) {
return errorResult;
}
return encryptAndSignImpl(params, input, output, appSettings, false);
}
@Override
public Bundle signAndEncrypt(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) {
final AppSettings appSettings = getAppSettings();
Bundle errorResult = checkRequirements(params);
if (errorResult != null) {
return errorResult;
}
return encryptAndSignImpl(params, input, output, appSettings, true);
}
@Override
public Bundle decryptAndVerify(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) {
final AppSettings appSettings = getAppSettings();
Bundle errorResult = checkRequirements(params);
if (errorResult != null) {
return errorResult;
}
return decryptAndVerifyImpl(params, input, output, appSettings);
}
@Override
public Bundle getKeyIds(Bundle params) {
Bundle errorResult = checkRequirements(params);
if (errorResult != null) {
return errorResult;
}
return getKeyIdsImpl(params);
}
};

View File

@ -21,7 +21,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.util.OpenPgpConstants;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
@ -38,10 +38,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
/**
* Abstract service class for remote APIs that handle app registration and user input.
@ -57,7 +53,7 @@ public abstract class RemoteService extends Service {
return mContext;
}
protected Bundle isAllowed(Bundle params) {
protected Intent isAllowed(Intent data) {
try {
if (isCallerAllowed(false)) {
@ -74,9 +70,9 @@ public abstract class RemoteService extends Service {
} catch (NameNotFoundException e) {
Log.e(Constants.TAG, "Should not happen, returning!", e);
// return error
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR);
result.putParcelable(OpenPgpConstants.RESULT_ERRORS,
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
result.putExtra(OpenPgpApi.RESULT_ERRORS,
new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage()));
return result;
}
@ -86,14 +82,14 @@ public abstract class RemoteService extends Service {
intent.setAction(RemoteServiceActivity.ACTION_REGISTER);
intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName);
intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature);
intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_REGISTER, intent, 0);
// return PendingIntent to be executed by client
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED);
result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi);
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
return result;
}
@ -103,14 +99,14 @@ public abstract class RemoteService extends Service {
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE);
intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, getString(R.string.api_error_wrong_signature));
intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_ERROR, intent, 0);
// return PendingIntent to be executed by client
Bundle result = new Bundle();
result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED);
result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi);
Intent result = new Intent();
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
return result;
}

View File

@ -25,7 +25,7 @@ import android.os.Messenger;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import org.openintents.openpgp.util.OpenPgpConstants;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.htmltextview.HtmlTextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
@ -51,6 +51,8 @@ public class RemoteServiceActivity extends ActionBarActivity {
public static final String EXTRA_MESSENGER = "messenger";
public static final String EXTRA_DATA = "data";
// passphrase action
public static final String EXTRA_SECRET_KEY_ID = "secret_key_id";
// register action
@ -100,12 +102,9 @@ public class RemoteServiceActivity extends ActionBarActivity {
ProviderHelper.insertApiApp(RemoteServiceActivity.this,
mSettingsFragment.getAppSettings());
// give params through for new service call
Bundle oldParams = extras.getBundle(OpenPgpConstants.PI_RESULT_PARAMS);
Intent finishIntent = new Intent();
finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, oldParams);
RemoteServiceActivity.this.setResult(RESULT_OK, finishIntent);
// give data through for new service call
Intent resultData = extras.getParcelable(EXTRA_DATA);
RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
RemoteServiceActivity.this.finish();
}
}
@ -128,9 +127,9 @@ public class RemoteServiceActivity extends ActionBarActivity {
mSettingsFragment.setAppSettings(settings);
} else if (ACTION_CACHE_PASSPHRASE.equals(action)) {
long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID);
Bundle oldParams = extras.getBundle(OpenPgpConstants.PI_RESULT_PARAMS);
Intent resultData = extras.getParcelable(EXTRA_DATA);
showPassphraseDialog(oldParams, secretKeyId);
showPassphraseDialog(resultData, secretKeyId);
} else if (ACTION_SELECT_PUB_KEYS.equals(action)) {
long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
ArrayList<String> missingUserIds = intent
@ -167,13 +166,11 @@ public class RemoteServiceActivity extends ActionBarActivity {
@Override
public void onClick(View v) {
// add key ids to params Bundle for new request
Bundle params = extras.getBundle(OpenPgpConstants.PI_RESULT_PARAMS);
params.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS,
Intent resultData = extras.getParcelable(EXTRA_DATA);
resultData.putExtra(OpenPgpApi.EXTRA_KEY_IDS,
mSelectFragment.getSelectedMasterKeyIds());
Intent finishIntent = new Intent();
finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
RemoteServiceActivity.this.setResult(RESULT_OK, finishIntent);
RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
RemoteServiceActivity.this.finish();
}
}, R.string.btn_do_not_save, new View.OnClickListener() {
@ -222,7 +219,7 @@ public class RemoteServiceActivity extends ActionBarActivity {
@Override
public void onClick(View v) {
RemoteServiceActivity.this.setResult(RESULT_OK);
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
RemoteServiceActivity.this.finish();
}
});
@ -244,16 +241,14 @@ public class RemoteServiceActivity extends ActionBarActivity {
* encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks
* for a symmetric passphrase
*/
private void showPassphraseDialog(final Bundle params, long secretKeyId) {
private void showPassphraseDialog(final Intent data, long secretKeyId) {
// Message is received after passphrase is cached
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
// return given params again, for calling the service method again
Intent finishIntent = new Intent();
finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
RemoteServiceActivity.this.setResult(RESULT_OK, finishIntent);
RemoteServiceActivity.this.setResult(RESULT_OK, data);
} else {
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
}
@ -273,9 +268,7 @@ public class RemoteServiceActivity extends ActionBarActivity {
} catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No passphrase for this secret key, do pgp operation directly!");
// return given params again, for calling the service method again
Intent finishIntent = new Intent();
finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params);
setResult(RESULT_OK, finishIntent);
setResult(RESULT_OK, data);
finish();
}
}

View File

@ -25,6 +25,7 @@ import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.regex.Matcher;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
@ -32,6 +33,7 @@ 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.pgp.PgpDecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
@ -690,11 +692,15 @@ public class DecryptActivity extends DrawerActivity {
}
if (returnData.getBoolean(KeychainIntentService.RESULT_SIGNATURE)) {
String userId = returnData
.getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID);
mSignatureKeyId = returnData
.getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID);
PgpDecryptVerifyResult decryptVerifyResult =
returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT);
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
if (signatureResult != null) {
String userId = signatureResult.getUserId();
mSignatureKeyId = signatureResult.getKeyId();
mUserIdRest.setText("id: "
+ PgpKeyHelper.convertKeyIdToHex(mSignatureKeyId));
if (userId == null) {
@ -707,19 +713,32 @@ public class DecryptActivity extends DrawerActivity {
}
mUserId.setText(userId);
if (returnData.getBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS)) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
mLookupKey.setVisibility(View.GONE);
} else if (returnData
.getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN)) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
mLookupKey.setVisibility(View.VISIBLE);
AppMsg.makeText(DecryptActivity.this,
R.string.unknown_signature,
AppMsg.STYLE_ALERT).show();
} else {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
mLookupKey.setVisibility(View.GONE);
switch (signatureResult.getStatus()) {
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: {
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
mLookupKey.setVisibility(View.GONE);
break;
}
// TODO!
// case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: {
// break;
// }
case OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY: {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
mLookupKey.setVisibility(View.VISIBLE);
AppMsg.makeText(DecryptActivity.this,
R.string.unknown_signature,
AppMsg.STYLE_ALERT).show();
break;
}
default: {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
mLookupKey.setVisibility(View.GONE);
break;
}
}
mSignatureLayout.setVisibility(View.VISIBLE);
}

View File

@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.service.remote.RegisteredAppsListActivity;
import org.sufficientlysecure.keychain.util.Log;
import android.app.Activity;
import android.content.Context;
@ -52,6 +53,7 @@ public class DrawerActivity extends ActionBarActivity {
private static Class[] mItemsClass = new Class[] { KeyListPublicActivity.class,
EncryptActivity.class, DecryptActivity.class, ImportKeysActivity.class,
KeyListSecretActivity.class, RegisteredAppsListActivity.class };
private Class mSelectedItem;
private static final int MENU_ID_PREFERENCE = 222;
private static final int MENU_ID_HELP = 223;
@ -94,6 +96,17 @@ public class DrawerActivity extends ActionBarActivity {
getSupportActionBar().setTitle(mTitle);
// creates call to onPrepareOptionsMenu()
supportInvalidateOptionsMenu();
// call intent activity if selected
if(mSelectedItem != null) {
finish();
overridePendingTransition(0, 0);
Intent intent = new Intent(DrawerActivity.this, mSelectedItem);
startActivity(intent);
// disable animation of activity start
overridePendingTransition(0, 0);
}
}
public void onDrawerOpened(View drawerView) {
@ -182,14 +195,8 @@ public class DrawerActivity extends ActionBarActivity {
mDrawerList.setItemChecked(position, true);
// setTitle(mDrawerTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
finish();
overridePendingTransition(0, 0);
Intent intent = new Intent(this, mItemsClass[position]);
startActivity(intent);
// disable animation of activity start
overridePendingTransition(0, 0);
// set selected class
mSelectedItem = mItemsClass[position];
}
/**

View File

@ -44,8 +44,10 @@ import org.sufficientlysecure.keychain.ui.widget.UserIdEditor;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@ -173,7 +175,7 @@ public class EditKeyActivity extends ActionBarActivity {
if (generateDefaultKeys) {
// Send all information needed to service generate keys in other thread
Intent serviceIntent = new Intent(this, KeychainIntentService.class);
final Intent serviceIntent = new Intent(this, KeychainIntentService.class);
serviceIntent.setAction(KeychainIntentService.ACTION_GENERATE_DEFAULT_RSA_KEYS);
// fill values for this action
@ -185,7 +187,19 @@ public class EditKeyActivity extends ActionBarActivity {
// Message is received after generating is done in ApgService
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
this, R.string.progress_generating, ProgressDialog.STYLE_SPINNER) {
this, R.string.progress_generating, ProgressDialog.STYLE_SPINNER, true,
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
// Stop key generation on cancel
stopService(serviceIntent);
EditKeyActivity.this.setResult(Activity.RESULT_CANCELED);
EditKeyActivity.this.finish();
}
}) {
@Override
public void handleMessage(Message message) {
// handle messages by standard ApgHandler first
super.handleMessage(message);

View File

@ -17,22 +17,9 @@
package org.sufficientlysecure.keychain.ui;
import java.util.ArrayList;
import java.util.Locale;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.util.Log;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.nfc.NdefMessage;
@ -51,6 +38,18 @@ import android.widget.ArrayAdapter;
import com.beardedhen.androidbootstrap.BootstrapButton;
import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.ui.dialog.BadImportKeyDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
import java.util.Locale;
public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNavigationListener {
public static final String ACTION_IMPORT_KEY = Constants.INTENT_PREFIX + "IMPORT_KEY";
public static final String ACTION_IMPORT_KEY_FROM_QR_CODE = Constants.INTENT_PREFIX
@ -236,10 +235,10 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
* inside your Activity."
* <p/>
* from http://stackoverflow.com/questions/10983396/fragment-oncreateview-and-onactivitycreated-called-twice/14295474#14295474
*
* <p/>
* In our case, if we start ImportKeysActivity with parameters to directly search using a fingerprint,
* the fragment would be loaded twice resulting in the query being empty after the second load.
*
* <p/>
* Our solution:
* To prevent that a fragment will be loaded again even if it was already loaded loadNavFragment
* checks against mCurrentNavPostition.
@ -395,23 +394,8 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa
AppMsg.makeText(ImportKeysActivity.this, toastMessage, AppMsg.STYLE_INFO)
.show();
if (bad > 0) {
AlertDialog.Builder alert = new AlertDialog.Builder(
ImportKeysActivity.this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.warning);
alert.setMessage(ImportKeysActivity.this.getResources()
.getQuantityString(R.plurals.bad_keys_encountered, bad, bad));
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
alert.setCancelable(true);
alert.create().show();
BadImportKeyDialogFragment badImportKeyDialogFragment = BadImportKeyDialogFragment.newInstance(bad);
badImportKeyDialogFragment.show(getSupportFragmentManager(), "badKeyDialog");
}
}
}

View File

@ -27,11 +27,13 @@ import java.util.List;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.KeyServer;
import org.sufficientlysecure.keychain.util.Log;
import android.app.Activity;
@ -42,10 +44,11 @@ import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;
import com.devspark.appmsg.AppMsg;
public class ImportKeysListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<List<ImportKeysListEntry>> {
LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
private static final String ARG_DATA_URI = "uri";
private static final String ARG_BYTES = "bytes";
private static final String ARG_SERVER_QUERY = "query";
@ -181,11 +184,10 @@ public class ImportKeysListFragment extends ListFragment implements
}
@Override
public Loader<List<ImportKeysListEntry>> onCreateLoader(int id, Bundle args) {
public Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_ID_BYTES: {
InputData inputData = getInputData(mKeyBytes, mDataUri);
return new ImportKeysListLoader(mActivity, inputData);
}
case LOADER_ID_SERVER_QUERY: {
@ -198,15 +200,15 @@ public class ImportKeysListFragment extends ListFragment implements
}
@Override
public void onLoadFinished(Loader<List<ImportKeysListEntry>> loader,
List<ImportKeysListEntry> data) {
public void onLoadFinished(Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader,
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
Log.d(Constants.TAG, "data: " + data);
Log.d(Constants.TAG, "data: " + data.getResult());
// swap in the real data!
mAdapter.setData(data);
mAdapter.setData(data.getResult());
mAdapter.notifyDataSetChanged();
setListAdapter(mAdapter);
@ -222,11 +224,25 @@ public class ImportKeysListFragment extends ListFragment implements
break;
case LOADER_ID_SERVER_QUERY:
Toast.makeText(
getActivity(), getResources().getQuantityString(R.plurals.keys_found,
mAdapter.getCount(), mAdapter.getCount()),
Toast.LENGTH_SHORT
).show();
Exception error = data.getError();
if(error == null){
AppMsg.makeText(
getActivity(), getResources().getQuantityString(R.plurals.keys_found,
mAdapter.getCount(), mAdapter.getCount()),
AppMsg.STYLE_INFO
).show();
} else if(error instanceof KeyServer.InsufficientQuery){
AppMsg.makeText(getActivity(), R.string.error_keyserver_insufficient_query,
AppMsg.STYLE_ALERT).show();
}else if(error instanceof KeyServer.QueryException){
AppMsg.makeText(getActivity(), R.string.error_keyserver_query,
AppMsg.STYLE_ALERT).show();
}else if(error instanceof KeyServer.TooManyResponses){
AppMsg.makeText(getActivity(), R.string.error_keyserver_too_many_responses,
AppMsg.STYLE_ALERT).show();
}
break;
default:
@ -235,7 +251,7 @@ public class ImportKeysListFragment extends ListFragment implements
}
@Override
public void onLoaderReset(Loader<List<ImportKeysListEntry>> loader) {
public void onLoaderReset(Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader) {
switch (loader.getId()) {
case LOADER_ID_BYTES:
// Clear the data in the adapter.

View File

@ -33,6 +33,7 @@ import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
@ -276,7 +277,8 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
viewIntent.setData(KeychainContract.KeyRings.buildPublicKeyRingsUri(Long.toString(id)));
startActivity(viewIntent);
}
@TargetApi(11)
public void encrypt(ActionMode mode, long[] keyRingRowIds) {
// get master key ids from row ids
long[] keyRingIds = new long[keyRingRowIds.length];
@ -298,6 +300,7 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
*
* @param keyRingRowIds
*/
@TargetApi(11)
public void showDeleteKeyDialog(final ActionMode mode, long[] keyRingRowIds) {
// Message is received after key is deleted
Handler returnHandler = new Handler() {
@ -332,4 +335,4 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog");
}
}
}

View File

@ -29,6 +29,7 @@ import org.sufficientlysecure.keychain.ui.adapter.KeyListSecretAdapter;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
@ -209,6 +210,7 @@ public class KeyListSecretFragment extends ListFragment implements
*
* @param keyRingRowIds
*/
@TargetApi(11)
public void showDeleteKeyDialog(final ActionMode mode, long[] keyRingRowIds) {
// Message is received after key is deleted
Handler returnHandler = new Handler() {

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2014 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.ui.adapter;
/**
* The AsyncTaskResultWrapper is used to wrap a result from a AsyncTask (for example: Loader).
* You can pass the result and an exception in it if an error occurred.
* Concept found at:
* https://stackoverflow.com/questions/19593577/how-to-handle-errors-in-custom-asynctaskloader
* @param <T> - Typ of the result which is wrapped
*/
public class AsyncTaskResultWrapper <T>{
private final T result;
private final Exception error;
public AsyncTaskResultWrapper(T result, Exception error){
this.result = result;
this.error = error;
}
public T getResult() {
return result;
}
public Exception getError() {
return error;
}
}

View File

@ -33,12 +33,13 @@ import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> {
public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
Context mContext;
InputData mInputData;
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper;
public ImportKeysListLoader(Context context, InputData inputData) {
super(context);
@ -47,15 +48,18 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEnt
}
@Override
public List<ImportKeysListEntry> loadInBackground() {
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(data, null);
if (mInputData == null) {
Log.e(Constants.TAG, "Input data is null!");
return data;
return entryListWrapper;
}
generateListOfKeyrings(mInputData);
return data;
return entryListWrapper;
}
@Override
@ -77,7 +81,7 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEnt
}
@Override
public void deliverResult(List<ImportKeysListEntry> data) {
public void deliverResult(AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) {
super.deliverResult(data);
}

View File

@ -26,15 +26,15 @@ import org.sufficientlysecure.keychain.util.KeyServer;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
import java.util.List;
public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> {
public class ImportKeysListServerLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
Context mContext;
String mServerQuery;
String mKeyServer;
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
private ArrayList<ImportKeysListEntry> entryList = new ArrayList<ImportKeysListEntry>();
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper;
public ImportKeysListServerLoader(Context context, String serverQuery, String keyServer) {
super(context);
@ -44,15 +44,18 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysL
}
@Override
public List<ImportKeysListEntry> loadInBackground() {
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null);
if (mServerQuery == null) {
Log.e(Constants.TAG, "mServerQuery is null!");
return data;
return entryListWrapper;
}
queryServer(mServerQuery, mKeyServer);
return data;
return entryListWrapper;
}
@Override
@ -74,7 +77,7 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysL
}
@Override
public void deliverResult(List<ImportKeysListEntry> data) {
public void deliverResult(AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) {
super.deliverResult(data);
}
@ -87,13 +90,17 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysL
ArrayList<ImportKeysListEntry> searchResult = server.search(query);
// add result to data
data.addAll(searchResult);
entryList.addAll(searchResult);
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null);
} catch (KeyServer.InsufficientQuery e) {
Log.e(Constants.TAG, "InsufficientQuery", e);
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e);
} catch (KeyServer.QueryException e) {
Log.e(Constants.TAG, "QueryException", e);
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e);
} catch (KeyServer.TooManyResponses e) {
Log.e(Constants.TAG, "TooManyResponses", e);
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e);
}
}

View File

@ -0,0 +1,68 @@
/*
* 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.ui.dialog;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import org.sufficientlysecure.keychain.R;
public class BadImportKeyDialogFragment extends DialogFragment {
private static final String ARG_BAD_IMPORT = "bad_import";
/**
* Creates a new instance of this Bad Import Key DialogFragment
*
* @param bad
* @return
*/
public static BadImportKeyDialogFragment newInstance(int bad) {
BadImportKeyDialogFragment frag = new BadImportKeyDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_BAD_IMPORT, bad);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final FragmentActivity activity = getActivity();
final int badImport = getArguments().getInt(ARG_BAD_IMPORT);
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setIcon(R.drawable.ic_dialog_alert_holo_light);
alert.setTitle(R.string.warning);
alert.setMessage(activity.getResources()
.getQuantityString(R.plurals.bad_keys_encountered, badImport, badImport));
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
alert.setCancelable(true);
return alert.create();
}
}

View File

@ -0,0 +1,152 @@
/*
* 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.ui.dialog;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.Choice;
import java.util.Vector;
public class CreateKeyDialogFragment extends DialogFragment {
public interface OnAlgorithmSelectedListener {
public void onAlgorithmSelected(Choice algorithmChoice, int keySize);
}
private static final String ARG_EDITOR_CHILD_COUNT = "child_count";
private int mNewKeySize;
private Choice mNewKeyAlgorithmChoice;
private OnAlgorithmSelectedListener mAlgorithmSelectedListener;
public void setOnAlgorithmSelectedListener(OnAlgorithmSelectedListener listener) {
mAlgorithmSelectedListener = listener;
}
public static CreateKeyDialogFragment newInstance(int mEditorChildCount) {
CreateKeyDialogFragment frag = new CreateKeyDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_EDITOR_CHILD_COUNT, mEditorChildCount);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final FragmentActivity context = getActivity();
final LayoutInflater mInflater;
final int childCount = getArguments().getInt(ARG_EDITOR_CHILD_COUNT);
mInflater = context.getLayoutInflater();
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
View view = mInflater.inflate(R.layout.create_key_dialog, null);
dialog.setView(view);
dialog.setTitle(R.string.title_create_key);
boolean wouldBeMasterKey = (childCount == 0);
final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm);
Vector<Choice> choices = new Vector<Choice>();
choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString(
R.string.dsa)));
if (!wouldBeMasterKey) {
choices.add(new Choice(Id.choice.algorithm.elgamal, getResources().getString(
R.string.elgamal)));
}
choices.add(new Choice(Id.choice.algorithm.rsa, getResources().getString(
R.string.rsa)));
ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(context,
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
algorithm.setAdapter(adapter);
// make RSA the default
for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).getId() == Id.choice.algorithm.rsa) {
algorithm.setSelection(i);
break;
}
}
final Spinner keySize = (Spinner) view.findViewById(R.id.create_key_size);
ArrayAdapter<CharSequence> keySizeAdapter = ArrayAdapter.createFromResource(
context, R.array.key_size_spinner_values,
android.R.layout.simple_spinner_item);
keySizeAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
keySize.setAdapter(keySizeAdapter);
keySize.setSelection(3); // Default to 4096 for the key length
dialog.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di, int id) {
di.dismiss();
try {
int nKeyIndex = keySize.getSelectedItemPosition();
switch (nKeyIndex) {
case 0:
mNewKeySize = 512;
break;
case 1:
mNewKeySize = 1024;
break;
case 2:
mNewKeySize = 2048;
break;
case 3:
mNewKeySize = 4096;
break;
}
} catch (NumberFormatException e) {
mNewKeySize = 0;
}
mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem();
mAlgorithmSelectedListener.onAlgorithmSelected(mNewKeyAlgorithmChoice, mNewKeySize);
}
});
dialog.setCancelable(true);
dialog.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di, int id) {
di.dismiss();
}
});
return dialog.create();
}
}

View File

@ -83,7 +83,7 @@ public class DeleteFileDialogFragment extends DialogFragment {
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
ProgressDialogFragment deletingDialog = ProgressDialogFragment.newInstance(
R.string.progress_deleting_securely, ProgressDialog.STYLE_HORIZONTAL);
R.string.progress_deleting_securely, ProgressDialog.STYLE_HORIZONTAL, false, null);
// Message is received after deleting is done in ApgService
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(activity, deletingDialog) {

View File

@ -17,17 +17,6 @@
package org.sufficientlysecure.keychain.ui.dialog;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
@ -40,6 +29,14 @@ import android.os.RemoteException;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
public class DeleteKeyDialogFragment extends DialogFragment {

View File

@ -21,28 +21,40 @@ import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnKeyListener;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.KeyEvent;
import org.sufficientlysecure.keychain.R;
public class ProgressDialogFragment extends DialogFragment {
private static final String ARG_MESSAGE_ID = "message_id";
private static final String ARG_STYLE = "style";
private static final String ARG_CANCELABLE = "cancelable";
private OnCancelListener mOnCancelListener;
/**
* Creates new instance of this fragment
*
* @param id
* @param messageId
* @param style
* @param cancelable
* @return
*/
public static ProgressDialogFragment newInstance(int messageId, int style) {
public static ProgressDialogFragment newInstance(int messageId, int style, boolean cancelable,
OnCancelListener onCancelListener) {
ProgressDialogFragment frag = new ProgressDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_MESSAGE_ID, messageId);
args.putInt(ARG_STYLE, style);
args.putBoolean(ARG_CANCELABLE, cancelable);
frag.setArguments(args);
frag.mOnCancelListener = onCancelListener;
return frag;
}
@ -60,7 +72,6 @@ public class ProgressDialogFragment extends DialogFragment {
/**
* Updates progress of dialog
*
* @param messageId
* @param progress
* @param max
*/
@ -74,7 +85,7 @@ public class ProgressDialogFragment extends DialogFragment {
/**
* Updates progress of dialog
*
* @param messageId
* @param message
* @param progress
* @param max
*/
@ -86,12 +97,20 @@ public class ProgressDialogFragment extends DialogFragment {
dialog.setMax(max);
}
@Override
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
if (this.mOnCancelListener != null)
this.mOnCancelListener.onCancel(dialog);
}
/**
* Creates dialog
*/
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Activity activity = getActivity();
final Activity activity = getActivity();
ProgressDialog dialog = new ProgressDialog(activity);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
@ -100,10 +119,22 @@ public class ProgressDialogFragment extends DialogFragment {
int messageId = getArguments().getInt(ARG_MESSAGE_ID);
int style = getArguments().getInt(ARG_STYLE);
boolean cancelable = getArguments().getBoolean(ARG_CANCELABLE);
dialog.setMessage(getString(messageId));
dialog.setProgressStyle(style);
if (cancelable) {
dialog.setButton(DialogInterface.BUTTON_NEGATIVE,
activity.getString(R.string.progress_cancel),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
}
// Disable the back button
OnKeyListener keyListener = new OnKeyListener() {

View File

@ -17,28 +17,26 @@
package org.sufficientlysecure.keychain.ui.dialog;
import java.util.ArrayList;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.QrCodeUtils;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.QrCodeUtils;
import java.util.ArrayList;
public class ShareQrCodeDialogFragment extends DialogFragment {
private static final String ARG_KEY_URI = "uri";
private static final String ARG_FINGERPRINT_ONLY = "fingerprint_only";

View File

@ -16,20 +16,6 @@
package org.sufficientlysecure.keychain.ui.widget;
import java.util.Vector;
import org.spongycastle.openpgp.PGPSecretKey;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.util.Choice;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
@ -43,13 +29,25 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.spongycastle.openpgp.PGPSecretKey;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.ui.dialog.CreateKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.util.Choice;
import java.util.Vector;
public class SectionView extends LinearLayout implements OnClickListener, EditorListener {
private LayoutInflater mInflater;
private BootstrapButton mPlusButton;
@ -149,84 +147,16 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
}
case Id.type.key: {
AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
View view = mInflater.inflate(R.layout.create_key_dialog, null);
dialog.setView(view);
dialog.setTitle(R.string.title_create_key);
boolean wouldBeMasterKey = (mEditors.getChildCount() == 0);
final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm);
Vector<Choice> choices = new Vector<Choice>();
choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString(
R.string.dsa)));
if (!wouldBeMasterKey) {
choices.add(new Choice(Id.choice.algorithm.elgamal, getResources().getString(
R.string.elgamal)));
}
choices.add(new Choice(Id.choice.algorithm.rsa, getResources().getString(
R.string.rsa)));
ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(getContext(),
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
algorithm.setAdapter(adapter);
// make RSA the default
for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).getId() == Id.choice.algorithm.rsa) {
algorithm.setSelection(i);
break;
CreateKeyDialogFragment mCreateKeyDialogFragment = CreateKeyDialogFragment.newInstance(mEditors.getChildCount());
mCreateKeyDialogFragment.setOnAlgorithmSelectedListener(new CreateKeyDialogFragment.OnAlgorithmSelectedListener() {
@Override
public void onAlgorithmSelected(Choice algorithmChoice, int keySize) {
mNewKeyAlgorithmChoice = algorithmChoice;
mNewKeySize = keySize;
createKey();
}
}
final Spinner keySize = (Spinner) view.findViewById(R.id.create_key_size);
ArrayAdapter<CharSequence> keySizeAdapter = ArrayAdapter.createFromResource(
getContext(), R.array.key_size_spinner_values,
android.R.layout.simple_spinner_item);
keySizeAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
keySize.setAdapter(keySizeAdapter);
keySize.setSelection(3); // Default to 4096 for the key length
dialog.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di, int id) {
di.dismiss();
try {
int nKeyIndex = keySize.getSelectedItemPosition();
switch (nKeyIndex) {
case 0:
mNewKeySize = 512;
break;
case 1:
mNewKeySize = 1024;
break;
case 2:
mNewKeySize = 2048;
break;
case 3:
mNewKeySize = 4096;
break;
}
} catch (NumberFormatException e) {
mNewKeySize = 0;
}
mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem();
createKey();
}
});
dialog.setCancelable(true);
dialog.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di, int id) {
di.dismiss();
}
});
dialog.create().show();
});
mCreateKeyDialogFragment.show(mActivity.getSupportFragmentManager(), "createKeyDialog");
break;
}
@ -282,7 +212,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
private void createKey() {
// Send all information needed to service to edit key in other thread
Intent intent = new Intent(mActivity, KeychainIntentService.class);
final Intent intent = new Intent(mActivity, KeychainIntentService.class);
intent.setAction(KeychainIntentService.ACTION_GENERATE_KEY);
@ -309,7 +239,12 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
// show progress dialog
mGeneratingDialog = ProgressDialogFragment.newInstance(R.string.progress_generating,
ProgressDialog.STYLE_SPINNER);
ProgressDialog.STYLE_SPINNER, true, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
mActivity.stopService(intent);
}
});
// Message is received after generating is done in ApgService
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(mActivity,

View File

@ -1,6 +1,8 @@
/*
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2011 Thialfihar <thi@thialfihar.org>
* Copyright (C) 2011 Senecaso
*
*
* 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
@ -32,6 +34,7 @@ import java.util.List;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Locale;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
@ -172,11 +175,11 @@ public class HkpKeyServer extends KeyServer {
if (e.getCode() == 404) {
return results;
} else {
if (e.getData().toLowerCase().contains("no keys found")) {
if (e.getData().toLowerCase(Locale.US).contains("no keys found")) {
return results;
} else if (e.getData().toLowerCase().contains("too many")) {
} else if (e.getData().toLowerCase(Locale.US).contains("too many")) {
throw new TooManyResponses();
} else if (e.getData().toLowerCase().contains("insufficient")) {
} else if (e.getData().toLowerCase(Locale.US).contains("insufficient")) {
throw new InsufficientQuery();
}
}

View File

@ -1,6 +1,8 @@
/*
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2011 Thialfihar <thi@thialfihar.org>
* Copyright (C) 2011 Senecaso
*
*
* 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
@ -16,14 +18,8 @@
package org.sufficientlysecure.keychain.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.os.Parcel;
import android.os.Parcelable;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
public abstract class KeyServer {

View File

@ -6,7 +6,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
@ -26,4 +26,4 @@
tools:layout="@layout/api_app_settings_fragment" />
</LinearLayout>
</ScrollView>
</ScrollView>

View File

@ -6,7 +6,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
@ -18,4 +18,4 @@
tools:layout="@layout/api_app_settings_fragment" />
</LinearLayout>
</ScrollView>
</ScrollView>

View File

@ -71,8 +71,8 @@
<LinearLayout
android:id="@+id/editors"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
</LinearLayout>
</LinearLayout>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> ist eine OpenPGP-Implementierung für Android. Die Entwicklung begann als ein Fork von Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> ist eine OpenPGP implementation für Android.</p>
<p>Lizenz: GPLv3+</p>
<h2>Entwickler OpenPGP Keychain</h2>
<h2>Entwickler OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (Leitender Entwickler)</li>
<li>Ash Hughes (crypto patches)</li>
@ -23,9 +23,9 @@
<h2>Bibliotheken</h2>
<ul>
<li>
<a href="http://developer.android.com/tools/support-library/index.html">Android Support Library v4</a> (Apache License v2)</li>
<a href="http://developer.android.com/tools/support-library/index.html">Android Support Bibliothek v4</a> (Apache Lizenz v2)</li>
<li>
<a href="http://developer.android.com/tools/support-library/index.html">Android Support Library v7 'appcompat'</a> (Apache License v2)</li>
<a href="http://developer.android.com/tools/support-library/index.html">Android Support Bibliothek v7 'appcompat'</a> (Apache Lizenz v2)</li>
<li>
<a href="https://github.com/emilsjolander/StickyListHeaders">StickyListHeaders</a> (Apache Lizenz v2)</li>
<li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 Lizenz)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache Lizenz v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Android AppMsg Bibliothek</a> (Apache Lizenz v2)</li>
<li>Icons von <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike Lizenz 3.0)</li>
<li>Icons von <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Public Domain)</li>
</ul>

View File

@ -16,12 +16,12 @@
<h2>2.2</h2>
<ul>
<li>new design with navigation drawer</li>
<li>new public key list design</li>
<li>Neus Design für die Liste der öffentlichen Schlüssel</li>
<li>new public key view</li>
<li>bug fixes for importing of keys</li>
<li>Fehler beim Schlüsselimport behoben</li>
<li>key cross-certification (thanks to Ash Hughes)</li>
<li>handle UTF-8 passwords properly (thanks to Ash Hughes)</li>
<li>first version with new languages (thanks to the contributors on Transifex)</li>
<li>Erste Version mit neuen Sprachen (Danke an die Mitwirkenden bei Transifex)</li>
<li>sharing of keys via QR Codes fixed and improved</li>
<li>package signature verification for API</li>
</ul>
@ -31,16 +31,16 @@
</ul>
<h2>2.1</h2>
<ul>
<li>lots of bug fixes</li>
<li>new API for developers</li>
<li>PRNG bug fix by Google</li>
<li>Viele Fehler behoben</li>
<li>Neue API für Entwickler</li>
<li>PRNG Bugfix von Google</li>
</ul>
<h2>2.0</h2>
<ul>
<li>complete redesign</li>
<li>Komlett neu designd</li>
<li>share public keys via qr codes, nfc beam</li>
<li>sign keys</li>
<li>upload keys to server</li>
<li>Schlüssel signieren</li>
<li>Schlüssel auf den Server hochladen</li>
<li>fixes import issues</li>
<li>new AIDL API</li>
</ul>
@ -56,25 +56,25 @@
<h2>1.0.7</h2>
<ul>
<li>fixed problem with signature verification of texts with trailing newline</li>
<li>more options for pass phrase cache time to live (20, 40, 60 mins)</li>
<li>weitere Optionen für die Time-to-live des Passphrasencaches (20, 40, 60 mins)</li>
</ul>
<h2>1.0.6</h2>
<ul>
<li>account adding crash on Froyo fixed</li>
<li>crash beim Hinzufügen eines Kontos auf Froyo repariert</li>
<li>sichere Dateilöschung</li>
<li>option to delete key file after import</li>
<li>Option, um Schlüsseldatei nach dem Import zu löschen</li>
<li>Streamverschlüsselung/-entschlüsselung (Galerie, etc.)</li>
<li>new options (language, force v3 signatures)</li>
<li>interface changes</li>
<li>neue Optionen (Sprache, v3-Unterschriften erzwingen)</li>
<li>Interfaceänderungen</li>
<li>Fehlerbehebungen</li>
</ul>
<h2>1.0.5</h2>
<ul>
<li>Deutsche und Italienische Übersetzung</li>
<li>much smaller package, due to reduced BC sources</li>
<li>new preferences GUI</li>
<li>layout adjustment for localization</li>
<li>signature bugfix</li>
<li>viel kleineres Paket, dank reduzierter BC Quellen</li>
<li>Neues Einstellungs-GUI</li>
<li>Lay-Out-Anpassung für die Lokalisierung</li>
<li>Fehler bei Signatur behoben</li>
</ul>
<h2>1.0.4</h2>
<ul>
@ -82,11 +82,11 @@
</ul>
<h2>1.0.3</h2>
<ul>
<li>fixed crashes during encryption/signing and possibly key export</li>
<li>Absturz während der Verschlüsselung/Signierung und möglicherweise Schlüsselexport behoben.</li>
</ul>
<h2>1.0.2</h2>
<ul>
<li>filterable key lists</li>
<li>Filterbare Schlüsselliste</li>
<li>smarter pre-selection of encryption keys</li>
<li>new Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers</li>
<li>fixes and additional features (key preselection) for K-9 Mail, new beta build available</li>
@ -100,7 +100,7 @@
<li>K-9 Mail integration, APG supporting beta build of K-9 Mail</li>
<li>support of more file managers (including ASTRO)</li>
<li>Slovenian translation</li>
<li>new database, much faster, less memory usage</li>
<li>Neue Datenbank, viel schneller, weniger Speicherbedarf</li>
<li>defined Intents and content provider for other apps</li>
<li>Fehlerbehebungen</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
<h2>I found a bug in OpenPGP Keychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenPGP Keychain</a>.</p>
<h2>Ich habe einen Fehler in OpenKeychain gefunden!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenKeychain</a>.</p>
<h2>Contribute</h2>
<p>If you want to help us developing OpenPGP Keychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<p>If you want to help us developing OpenKeychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<h2>Translations</h2>
<p>Help translating OpenPGP Keychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain on Transifex</a>.</p>
<h2>Übersetzungen</h2>
<p>Help translating OpenKeychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain on Transifex</a>.</p>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> is an OpenPGP implementation for Android. The development began as a fork of Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> is an OpenPGP implementation for Android.</p>
<p>License: GPLv3+</p>
<h2>Developers OpenPGP Keychain</h2>
<h2>Developers OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (Lead developer)</li>
<li>Ash Hughes (crypto patches)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Android AppMsg Library</a> (Apache License v2)</li>
<li>Icons from <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
<li>Icons from <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Public Domain)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
<h2>I found a bug in OpenPGP Keychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenPGP Keychain</a>.</p>
<h2>I found a bug in OpenKeychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenKeychain</a>.</p>
<h2>Contribute</h2>
<p>If you want to help us developing OpenPGP Keychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<p>If you want to help us developing OpenKeychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<h2>Translations</h2>
<p>Help translating OpenPGP Keychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain on Transifex</a>.</p>
<p>Help translating OpenKeychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain on Transifex</a>.</p>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> es una implementación de OpenPGP para Android. Su desarrollo comenzó como un fork de Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> es una implementación de OpenPGP para Android.</p>
<p>Licencia: GPLv3+</p>
<h2>Desarrolladores de OpenPGP Keychain</h2>
<h2>Desarrolladores OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (Desarrollador principal)</li>
<li>Ash Hughes (Parches cryptográficos)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (Licencia MIT X11)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Licencia Apache v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Librería Android AppMsg</a> (Licencia Apache v2)</li>
<li>Icons de <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Compartir-Igual licencia 3.0)</li>
<li>Iconos de <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Dominio Público)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>Es recomendable que instales <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> para una mejor selección de archivos y <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> para escanear los códigos QR generados. Pulsando en los enlaces se abrirá Google Play o F-Droid.</p>
<h2>¡He encontrado un bug en OpenPGP Keychain!</h2>
<p>Por favor, informa de errores usando el <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">seguimiento de incidencias de OpenPGP Keychain</a>.</p>
<h2>¡He encontrado un bug en OpenKeychain!</h2>
<p>Por favor, informa de errores usando el <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">seguimiento de incidencias de OpenKeychain</a>.</p>
<h2>Aportar</h2>
<p>Si quieres ayudarnos con el desarrollo de OpenPGP Keychain aportando código <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">sigue nuestra pequeña guía en Github</a>.</p>
<p>Si quieres ayudarnos con el desarrollo de OpenKeychain aportando código <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">sigue nuestra pequeña guía en Github</a>.</p>
<h2>Traducciones</h2>
<p>¡Ayúdanos a traducir OpenPGP Keychain! Todo el mundo es bienvenido en <a href="https://www.transifex.com/projects/p/openpgp-keychain/">Transifex - OpenPGP Keychain</a>.</p>
<p>¡Ayúdanos a traducir OpenKeychain! Todo el mundo es bienvenido en <a href="https://www.transifex.com/projects/p/openpgp-keychain/">Transifex - OpenKeychain</a>.</p>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">Le porte-clefs OpenPGP</a> est une implémentation d'OpenPGP pour Android. Le développement a commencé comme bifurcation d'Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> est une implémentation d'OpenPGP pour Android.</p>
<p>Licence : GPLv3+</p>
<h2>Les développeurs du Porte-clefs OpenPGP</h2>
<h2>Les développeurs d'OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (développeur principal)</li>
<li>Ash Hughes (correctif crypto)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (Licence MIT X11)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Licence Apache v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Bibliothèque Android AppMsg</a> (Licence Apache v2)</li>
<li>Icônes du <a href="http://rrze-icon-set.berlios.de/">jeu d'icônes RRZE</a> (Licence Creative Commons Paternité - Partage des Conditions Initiales à l'Identique 3.0)</li>
<li>Icônes du <a href="http://tango.freedesktop.org/">jeu d'icônes Tango</a> (domaine public)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>Il vous est recommendé d'installer le <a href="market://details?id=org.openintents.filemanager">gestionnaire de fichiers OI</a> pour sa fonction améliorée de séléction des fichiers et le <a href="market://details?id=com.google.zxing.client.android">lecteur de codes à barres</a> pour balayer les codes QR générés. Cliquer sur les liens ouvrira Google Play Store ou F-Droid pour l'installation.</p>
<h2>J'ai trouvé un bogue dans le Porte-clefs OpenPGP !</h2>
<p>Veuillez rapporter le bogue en utilisant le <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">gestionnaire de bogues du Porte-clefs OpenPGP</a>.</p>
<h2>J'ai trouvé un bogue dans OpenKeychain !</h2>
<p>Veuillez rapporter le bogue en utilisant le <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">gestionnaire de bogue d'OpenKeychain</a>.</p>
<h2>Contribuer</h2>
<p>Si vous voulez nous aider à développer le Porte-clefs OpenPGP en y contribuant par du code, <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">veuillez suivre notre petit guide sur Github</a>.</p>
<p>Si vous voulez nous aider à développer OpenKeychain en y contribuant par du code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">veuillez suivre notre petit guide sur Github</a>.</p>
<h2>Traductions</h2>
<p>Aidez-nous à traduire le Porte-clefs OpenPGP ! Tout le monde peut y participer sur la <a href="https://www.transifex.com/projects/p/openpgp-keychain/">page Transifex du Porte-clefs OpenPGP Keychain</a>.</p>
<p>Aidez-nous à traduire le OpenKeychain ! Tout le monde peut y participer sur la <a href="https://www.transifex.com/projects/p/openpgp-keychain/">page d'OpenKeychain sur Transifex</a>.</p>
</body>
</html>

View File

@ -1,43 +1,45 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> is an OpenPGP implementation for Android. The development began as a fork of Android Privacy Guard (APG).</p>
<p>License: GPLv3+</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> un implementazione OpenPGP per Android.</p>
<p>Licenza: GPLv3+</p>
<h2>Developers OpenPGP Keychain</h2>
<h2>Sviluppatori OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (Lead developer)</li>
<li>Ash Hughes (crypto patches)</li>
<li>Dominik Schürmann (Capo Sviluppatore)</li>
<li>Ash Hughes (Patch crittografia)</li>
<li>Brian C. Barnes</li>
<li>Bahtiar 'kalkin' Gadimov (UI)</li>
<li>Bahtiar 'kalkin' Gadimov (Interfaccia Utente)</li>
</ul>
<h2>Developers APG 1.x</h2>
<h2>Sviluppatori APG 1.x</h2>
<ul>
<li>'Thialfihar' (Lead developer)</li>
<li>'Senecaso' (QRCode, sign key, upload key)</li>
<li>'Thialfihar' (Capo Sviluppatore)</li>
<li>'Senecaso' (QRCode, firma chiavi, caricamento chiavi)</li>
<li>Oliver Runge</li>
<li>Markus Doits</li>
</ul>
<h2>Libraries</h2>
<h2>Librerie</h2>
<ul>
<li>
<a href="http://developer.android.com/tools/support-library/index.html">Android Support Library v4</a> (Apache License v2)</li>
<a href="http://developer.android.com/tools/support-library/index.html">Android Support Library v4</a> (Licenza Apache v2)</li>
<li>
<a href="http://developer.android.com/tools/support-library/index.html">Android Support Library v7 'appcompat'</a> (Apache License v2)</li>
<a href="http://developer.android.com/tools/support-library/index.html">Android Support Library v7 'appcompat'</a> (Licenza Apache v2)</li>
<li>
<a href="https://github.com/emilsjolander/StickyListHeaders">StickyListHeaders</a> (Apache License v2)</li>
<a href="https://github.com/emilsjolander/StickyListHeaders">StickyListHeaders</a> (Licenza Apache v2)</li>
<li>
<a href="https://github.com/Bearded-Hen/Android-Bootstrap">Android-Bootstrap</a> (MIT License)</li>
<a href="https://github.com/Bearded-Hen/Android-Bootstrap">Android-Bootstrap</a> (Licenza MIT)</li>
<li>
<a href="http://code.google.com/p/zxing/">ZXing</a> (Apache License v2)</li>
<a href="http://code.google.com/p/zxing/">ZXing</a> (Licenza Apache v2)</li>
<li>
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (Licenza MIT X11)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>Icons from <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
<li>Icons from <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Public Domain)</li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Licenza Apache v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Android AppMsg Library</a> (Licenza Apache v2)</li>
<li>Icone da <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Licenza Creative Commons Attribution Share-Alike 3.0)</li>
<li>Icone da <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Pubblico Dominio)</li>
</ul>
</body>
</html>

View File

@ -3,106 +3,106 @@
<body>
<h2>2.3</h2>
<ul>
<li>remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)</li>
<li>fix setting expiry dates on keys (thanks to Ash Hughes)</li>
<li>more internal fixes when editing keys (thanks to Ash Hughes)</li>
<li>querying keyservers directly from the import screen</li>
<li>fix layout and dialog style on Android 2.2-3.0</li>
<li>fix crash on keys with empty user ids</li>
<li>fix crash and empty lists when coming back from signing screen</li>
<li>Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source</li>
<li>fix upload of key from signing screen</li>
<li>rimossa esportazione non necessaria delle chiavi pubbliche quando si esportano le chiavi private (grazie a Ash Hughes)</li>
<li>corretto impostazione data di scadenza delle chiavi (grazie a Ash Hughes)</li>
<li>altre correzioni interne quando si modificano le chiavi (grazie a Ash Hughes)</li>
<li>interrogazione server delle chiavi direttamente dalla schermata di importazione</li>
<li>corretto layout e dialog style su Android 2.2-3.0</li>
<li>corretto crash su chiavi con id utente vuoto</li>
<li>corretto crash e liste vuote quando si torna dalla schermata di firma</li>
<li>Bouncy Castle (libreria crittografica) aggiornata da 1.47 a 1.50 e compilata da sorgente</li>
<li>corretto upload delle chiavi dalla schermata di firma</li>
</ul>
<h2>2.2</h2>
<ul>
<li>new design with navigation drawer</li>
<li>new public key list design</li>
<li>new public key view</li>
<li>bug fixes for importing of keys</li>
<li>key cross-certification (thanks to Ash Hughes)</li>
<li>handle UTF-8 passwords properly (thanks to Ash Hughes)</li>
<li>first version with new languages (thanks to the contributors on Transifex)</li>
<li>sharing of keys via QR Codes fixed and improved</li>
<li>package signature verification for API</li>
<li>nuovo design con drawer di navigazione</li>
<li>nuovo design per la lista chiavi pubbliche</li>
<li>nuova visuale chiavi pubbliche</li>
<li>correzione bug per importazione chiavi</li>
<li>Chiave certificazione incrociata (grazie a Ash Hughes)</li>
<li>password UTF-8 gestite correttamente (grazie a Ash Hughes)</li>
<li>Prima versione con nuove lingue (grazie ai contributori su Transifex)</li>
<li>condivisione di chiavi via Codici QR corretta e migliorata</li>
<li>Verifica firma pacchetto per API</li>
</ul>
<h2>2.1.1</h2>
<ul>
<li>API Updates, preparation for K-9 Mail integration</li>
<li>Aggiornamenti API, preparazione per integrazione con K-9 Mail</li>
</ul>
<h2>2.1</h2>
<ul>
<li>lots of bug fixes</li>
<li>new API for developers</li>
<li>molte correzioni di bug</li>
<li>nuove API per sviluppatori</li>
<li>PRNG bug fix by Google</li>
</ul>
<h2>2.0</h2>
<ul>
<li>complete redesign</li>
<li>share public keys via qr codes, nfc beam</li>
<li>sign keys</li>
<li>upload keys to server</li>
<li>fixes import issues</li>
<li>new AIDL API</li>
<li>completo restyle</li>
<li>condivisione chiavi pubbliche via codici qr, nfc beam</li>
<li>firma chiavi</li>
<li>Carica chiavi sul server</li>
<li>corrette caratteristiche di importazione</li>
<li>nuova AIDL API</li>
</ul>
<h2>1.0.8</h2>
<ul>
<li>basic keyserver support</li>
<li>supporto base per server delle chiavi</li>
<li>app2sd</li>
<li>more choices for pass phrase cache: 1, 2, 4, 8, hours</li>
<li>translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)</li>
<li>bugfixes</li>
<li>optimizations</li>
<li>Aggiunte opzioni per la cache della frase di accesso: 1, 2, 4, 8 ore</li>
<li>Traduzioni: Norvegese (grazie, Sander Danielsen), Cinese (grazie, Zhang Fredrick)</li>
<li>correzione bug</li>
<li>ottimizzazioni</li>
</ul>
<h2>1.0.7</h2>
<ul>
<li>fixed problem with signature verification of texts with trailing newline</li>
<li>more options for pass phrase cache time to live (20, 40, 60 mins)</li>
<li>corretto problema con la verifica firma di testi con capo finale</li>
<li>maggiori opzioni per il tempo di mantenimento della cache della frase di accesso (20, 40, 60 minuti)</li>
</ul>
<h2>1.0.6</h2>
<ul>
<li>account adding crash on Froyo fixed</li>
<li>secure file deletion</li>
<li>option to delete key file after import</li>
<li>stream encryption/decryption (gallery, etc.)</li>
<li>new options (language, force v3 signatures)</li>
<li>interface changes</li>
<li>bugfixes</li>
<li>crash della aggiunta degli account risolto su Froyo</li>
<li>Cancellazione sicura dei file</li>
<li>opzione per cancellare file delle chiavi dopo l'importazione</li>
<li>flusso codifica/decodifica (galleria, ecc.)</li>
<li>nuove opzioni (lingua, forza firme v3)</li>
<li>cambiamenti interfaccia</li>
<li>correzione bug</li>
</ul>
<h2>1.0.5</h2>
<ul>
<li>German and Italian translation</li>
<li>much smaller package, due to reduced BC sources</li>
<li>new preferences GUI</li>
<li>layout adjustment for localization</li>
<li>signature bugfix</li>
<li>Traduzione Italiana e Tedesca</li>
<li>dimensioni pacchetto ridotte, a causa della riduzione dei sorgenti BC</li>
<li>Nuove preferenze GUI</li>
<li>Regolazione layout per la localizzazione</li>
<li>correzione bug firma</li>
</ul>
<h2>1.0.4</h2>
<ul>
<li>fixed another crash caused by some SDK bug with query builder</li>
<li>corretto altro crash causato da alcuni bug SDK con query builder</li>
</ul>
<h2>1.0.3</h2>
<ul>
<li>fixed crashes during encryption/signing and possibly key export</li>
<li>corretto crash durante codifica/firma e possibilita' di esportare chiave</li>
</ul>
<h2>1.0.2</h2>
<ul>
<li>filterable key lists</li>
<li>smarter pre-selection of encryption keys</li>
<li>new Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers</li>
<li>fixes and additional features (key preselection) for K-9 Mail, new beta build available</li>
<li>liste chiavi filtrabili</li>
<li>preselezione di chiavi di codifica intelligente</li>
<li>nuovo gestore intent per VIEW e SEND, permette la codifica/decodifica file all'infuori di file manager</li>
<li>caratteristiche corrette e aggiunte (preselezione chiavi) per K-9 Mail. nuova build beta disponibile</li>
</ul>
<h2>1.0.1</h2>
<ul>
<li>GMail account listing was broken in 1.0.0, fixed again</li>
<li>elencazione account GMail corrotta in 1.0.0, corretta nuovamente</li>
</ul>
<h2>1.0.0</h2>
<ul>
<li>K-9 Mail integration, APG supporting beta build of K-9 Mail</li>
<li>support of more file managers (including ASTRO)</li>
<li>Slovenian translation</li>
<li>new database, much faster, less memory usage</li>
<li>defined Intents and content provider for other apps</li>
<li>bugfixes</li>
<li>integrazione K-9 Mail, APG supporto beta build di K-9 Mail</li>
<li>supporto per altri file manager (incluso ASTRO)</li>
<li>traduzione Slovena</li>
<li>Nuovo database, piu' veloce, utilizzo memoria ridotto</li>
<li>Definiti Intent e ContentProvider per le altre app</li>
<li>correzione bug</li>
</ul>
</body>
</html>

View File

@ -1,12 +1,12 @@
<html>
<head></head>
<body>
<h2>How to receive keys</h2>
<h2>Come ricevere le chiavi</h2>
<ol>
<li>Go to your partners contacts and open the contact you want to share.</li>
<li>Hold the two devices back to back (they have to be almost touching) and youll feel a vibration.</li>
<li>After it vibrates youll see the content on your partners device turn into a card-like object with Star Trek warp speed-looking animation in the background.</li>
<li>Tap the card and the content will then load on the your device.</li>
<li>Vai ai contatti dei tuoi partner e apri il contatto che si desidera condividere.</li>
<li>Mantieni i due dispositivi vicini (devono quasi toccarsi) e sentirai una vibrazione.</li>
<li>Dopo che ha vibrato, vedrai il contenuto del tuo dispositivo diventare come una scheda e nello sfondo apparirà una animazione come la propulsione a curvatura di Star Trek.</li>
<li>Tocca la scheda e il contenuto dopo si trasferira' nel dispositivo dell'altra persona.</li>
</ol>
</body>
</html>

View File

@ -1,19 +1,19 @@
<html>
<head></head>
<body>
<h2>Getting started</h2>
<p>First you need a personal key pair. Create one via the option menus in "My Keys" or import existing key pairs via "Import Keys". Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.</p>
<h2>Per iniziare</h2>
<p>Per prima cosa hai bisogno di un paio di chiavi personali. Creane una tramite i menu di opzione sotto 'Mie Chiavi' o importane di esistenti attraverso "Importa Chiavi". Dopodiche' puoi scaricare le chiavi dei tuoi amici o scambiarle tramite Codici QR o NFC.</p>
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
<p>Si raccomanda di installare <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> per una migliore selezione dei file e <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> per scansionare i codici QR. I collegamenti verranno aperti in Google Play Store o F-Droid per l'installazione.</p>
<h2>I found a bug in OpenPGP Keychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenPGP Keychain</a>.</p>
<h2>Ho trovato un bug in OpenKeychain!</h2>
<p>Per favore riporta i bug usando il <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker di OpenKeychain</a>.</p>
<h2>Contribute</h2>
<p>If you want to help us developing OpenPGP Keychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<h2>Contribuire</h2>
<p>Se vuoi aiutarci nello sviluppo di OpenKeychain contribuendo al codice <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">segui la nostra breve guida su Github</a>.</p>
<h2>Translations</h2>
<p>Help translating OpenPGP Keychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain on Transifex</a>.</p>
<h2>Traduzioni</h2>
<p>Aiutaci a tradurre OpenKeychain! Tutti possono collaborare a <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain su Transifex</a>.</p>
</body>
</html>

View File

@ -2,10 +2,10 @@
<head></head>
<body>
<ol>
<li>Make sure that NFC is turned on in Settings &gt; More &gt; NFC and make sure that Android Beam is also on in the same section.</li>
<li>Hold the two devices back to back (they have to be almost touching) and you'll feel a vibration.</li>
<li>After it vibrates you'll see the content on your device turn into a card-like object with Star Trek warp speed-looking animation in the background.</li>
<li>Tap the card and the content will then load on the other persons device.</li>
<li>Assicurati che NFC sia acceso in Impostazioni &gt; Altro &gt; NFC a assicurati che Android Beam sia pure su On nella stessa sezione.</li>
<li>Mantieni i due dispositivi vicini (devono quasi toccarsi) e sentirai una vibrazione.</li>
<li>Dopo che ha vibrato, vedrai il contenuto del tuo dispositivo diventare come una scheda e nello sfondo apparirà una animazione come la propulsione a curvatura di Star Trek.</li>
<li>Tocca la scheda e il contenuto dopo si trasferira' nel dispositivo dell'altra persona.</li>
</ol>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> は AndroidにおけるOpenPGP実装の一つです。開発はAndroid Privacy Guard (APG)から分岐して始まりました</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> は Android における OpenPGP 実装です。</p>
<p>ライセンス: GPLv3以降</p>
<h2>OpenPGP Keychain開発者</h2>
<h2>OpenKeychain開発者</h2>
<ul>
<li>Dominik Schürmann (主任開発者)</li>
<li>Ash Hughes (暗号関係パッチ提供)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Android AppMsg Library</a> (Apache License v2)</li>
<li>Icons from <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
<li>Icons from <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (パブリックドメイン)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>ファイルの選択を拡張するには<a href="market://details?id=org.openintents.filemanager">OI File Manager</a><a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a>を生成したQRコードのスキャンのため、それぞれのインストールを必要とします。 リンクをクリックして、Google Play Store上かF-Droidからインストールしてください。</p>
<h2>OpenPGP Keychainにバグを発見した!</h2>
<p><a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">OpenPGP KeychainのIssueトラッカー</a>を使ってバグレポートを送ってください。</p>
<h2>OpenKeychainでバグを見付けた!</h2>
<p><a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">OpenKeychainのIssueトラッカー</a>を使ってバグレポートを送ってください。</p>
<h2>寄贈</h2>
<p>もし、あなたが OpenPGP Keychain の開発を助け、コードを寄贈するというなら、<a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">Githubの寄贈ガイドを確認</a>して下さい。</p>
<p>もし、あなたが OpenKeychain の開発を助け、コードを寄贈するというなら、<a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">Githubのミニガイドを確認</a>して下さい。</p>
<h2>翻訳</h2>
<p>OpenPGP Keychainの翻訳を補助してください! だれでも、<a href="https://www.transifex.com/projects/p/openpgp-keychain/">TransifexのOpenPGP Keychainプロジェクト</a>に参加できます。</p>
<p>OpenKeychainの翻訳を助けてください! <a href="https://www.transifex.com/projects/p/openpgp-keychain/">TransifexのOpenKeychainプロジェクト</a>誰でも参加できます。</p>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> is an OpenPGP implementation for Android. The development began as a fork of Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> is an OpenPGP implementation for Android.</p>
<p>License: GPLv3+</p>
<h2>Developers OpenPGP Keychain</h2>
<h2>Developers OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (Lead developer)</li>
<li>Ash Hughes (crypto patches)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Android AppMsg Library</a> (Apache License v2)</li>
<li>Icons from <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
<li>Icons from <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Public Domain)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
<h2>I found a bug in OpenPGP Keychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenPGP Keychain</a>.</p>
<h2>I found a bug in OpenKeychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenKeychain</a>.</p>
<h2>Contribute</h2>
<p>If you want to help us developing OpenPGP Keychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<p>If you want to help us developing OpenKeychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<h2>Translations</h2>
<p>Help translating OpenPGP Keychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain on Transifex</a>.</p>
<p>Help translating OpenKeychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain on Transifex</a>.</p>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> is an OpenPGP implementation for Android. The development began as a fork of Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> is an OpenPGP implementation for Android.</p>
<p>License: GPLv3+</p>
<h2>Developers OpenPGP Keychain</h2>
<h2>Developers OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (Lead developer)</li>
<li>Ash Hughes (crypto patches)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Android AppMsg Library</a> (Apache License v2)</li>
<li>Icons from <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
<li>Icons from <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Public Domain)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
<h2>I found a bug in OpenPGP Keychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenPGP Keychain</a>.</p>
<h2>I found a bug in OpenKeychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenKeychain</a>.</p>
<h2>Contribute</h2>
<p>If you want to help us developing OpenPGP Keychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<p>If you want to help us developing OpenKeychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<h2>Translations</h2>
<p>Help translating OpenPGP Keychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain on Transifex</a>.</p>
<p>Help translating OpenKeychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain on Transifex</a>.</p>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> - свободная реализация OpenPGP для Android. Разработка начиналась как ответвление Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> - реализация OpenPGP для Android.</p>
<p>Лицензия: GPLv3+</p>
<h2>Разработчики OpenPGP Keychain</h2>
<h2>Разработчики OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (главный разработчик)</li>
<li>Ash Hughes (патчи криптографии)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Библиотека Android AppMsg</a> (Apache License v2)</li>
<li>Иконки <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
<li>Иконки <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Public Domain)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>Рекомендуется установить <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> для удобного выбора файлов и <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> для распознавания QR кодов. Перейдите по ссылкам на соответствующие страницы Google Play или F-Droid для дальнейшей установки.</p>
<h2>Я нашел ошибку в OpenPGP Keychain!</h2>
<p>Пожалуйста, сообщайте о возникших проблемах и найденных ошибках в разделе <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">Решение проблем OpenPGP Keychain</a>.</p>
<h2>Я нашел ошибку в OpenKeychain!</h2>
<p>Пожалуйста, сообщайте о возникших проблемах и найденных ошибках в разделе <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">Решение проблем OpenKeychain</a>.</p>
<h2>Вклад в развитие</h2>
<p>Если Вы хотите помочь в разработке OpenPGP Keychain, обратитесь к <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">инструкции на Github</a>.</p>
<p>Если Вы хотите помочь в разработке OpenKeychain, обратитесь к <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">инструкции на Github</a>.</p>
<h2>Перевод</h2>
<p>Помогите переводить OpenPGP Keychain! Каждый может принять участие в переводе <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain на Transifex</a>.</p>
<p>Помогите переводить OpenKeychain! Каждый может принять участие в переводе <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain на Transifex</a>.</p>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> is an OpenPGP implementation for Android. The development began as a fork of Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> is an OpenPGP implementation for Android.</p>
<p>License: GPLv3+</p>
<h2>Developers OpenPGP Keychain</h2>
<h2>Developers OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (Lead developer)</li>
<li>Ash Hughes (crypto patches)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Android AppMsg Library</a> (Apache License v2)</li>
<li>Icons from <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
<li>Icons from <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Public Domain)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
<h2>I found a bug in OpenPGP Keychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenPGP Keychain</a>.</p>
<h2>I found a bug in OpenKeychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenKeychain</a>.</p>
<h2>Contribute</h2>
<p>If you want to help us developing OpenPGP Keychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<p>If you want to help us developing OpenKeychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<h2>Translations</h2>
<p>Help translating OpenPGP Keychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain on Transifex</a>.</p>
<p>Help translating OpenKeychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain on Transifex</a>.</p>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> Android için bir OpenPGP uygulamasıdır. </p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> is an OpenPGP implementation for Android.</p>
<p>Lisans: GPLv3+</p>
<h2>Geliştiriciler OpenPGP Keychain</h2>
<h2>Developers OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (Baş geliştirici)</li>
<li>Ash Hughes (kripto yamaları)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Android AppMsg Library</a> (Apache License v2)</li>
<li>İkonlar <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
<li>İkonlar <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Public Domain)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
<h2>I found a bug in OpenPGP Keychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenPGP Keychain</a>.</p>
<h2>I found a bug in OpenKeychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenKeychain</a>.</p>
<h2>Contribute</h2>
<p>If you want to help us developing OpenPGP Keychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<p>If you want to help us developing OpenKeychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<h2>Translations</h2>
<p>Help translating OpenPGP Keychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain on Transifex</a>.</p>
<p>Help translating OpenKeychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain on Transifex</a>.</p>
</body>
</html>

View File

@ -1,8 +1,8 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> - вільна реалізація OpenPGP для Android. Розробка починалася як відгалуження Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> імплементація OpenPGP для Андроїду.</p>
<p>Ліцензія: GPLv3+</p>
<h2>Розробники OpenPGP Keychain</h2>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (ліцензія MIT X11)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (ліцензія Apache в.2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Бібліотека Android AppMsg Library</a> (Ліцензія Apache в. 2)</li>
<li>Піктограми із <a href="http://rrze-icon-set.berlios.de/">набору піктограм RRZE</a> (ліцензія Creative Commons - Із зазначенням авторства - Розповсюдження на тих самих умовах - версія 3.0)</li>
<li>Піктограми із <a href="http://tango.freedesktop.org/">набору піктограм Tango</a> (відкритий домен)</li>
</ul>

View File

@ -13,7 +13,7 @@
<p>Якщо ви хочете допомогти нам у розробці OpenPGP Keychain через редагування коду програми <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">підпишіться на наш невеличкий посібник у Github</a>.</p>
<h2>Переклади</h2>
<p>Допоможіть перекласти OpenPGP Keychain! Кожний може взяти участь у <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain на Transifex</a>.</p>
<p>Допоможіть перекласти OpenPGP Keychain! Кожний може взяти участь на <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain на Transifex</a>.</p>
</body>
</html>

View File

@ -1,11 +1,11 @@
<html>
<head></head>
<body>
<p><a href="http://sufficientlysecure.org/keychain">http://sufficientlysecure.org/keychain</a></p>
<p><a href="http://sufficientlysecure.org/keychain">OpenPGP Keychain</a> is an OpenPGP implementation for Android. The development began as a fork of Android Privacy Guard (APG).</p>
<p><a href="http://www.openkeychain.org">http://www.openkeychain.org</a></p>
<p><a href="http://www.openkeychain.org">OpenKeychain</a> is an OpenPGP implementation for Android.</p>
<p>License: GPLv3+</p>
<h2>Developers OpenPGP Keychain</h2>
<h2>Developers OpenKeychain</h2>
<ul>
<li>Dominik Schürmann (Lead developer)</li>
<li>Ash Hughes (crypto patches)</li>
@ -36,6 +36,8 @@
<a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<li>
<a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>
<a href="https://github.com/johnkil/Android-AppMsg">Android AppMsg Library</a> (Apache License v2)</li>
<li>Icons from <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
<li>Icons from <a href="http://tango.freedesktop.org/">Tango Icon Set</a> (Public Domain)</li>
</ul>

View File

@ -6,14 +6,14 @@
<p>It is recommended that you install <a href="market://details?id=org.openintents.filemanager">OI File Manager</a> for enhanced file selection and <a href="market://details?id=com.google.zxing.client.android">Barcode Scanner</a> to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.</p>
<h2>I found a bug in OpenPGP Keychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenPGP Keychain</a>.</p>
<h2>I found a bug in OpenKeychain!</h2>
<p>Please report the bug using the <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">issue tracker of OpenKeychain</a>.</p>
<h2>Contribute</h2>
<p>If you want to help us developing OpenPGP Keychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<p>If you want to help us developing OpenKeychain by contributing code <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">follow our small guide on Github</a>.</p>
<h2>Translations</h2>
<p>Help translating OpenPGP Keychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenPGP Keychain on Transifex</a>.</p>
<p>Help translating OpenKeychain! Everybody can participate at <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain on Transifex</a>.</p>
</body>
</html>

View File

@ -111,6 +111,7 @@
<string name="label_passphrase_cache_ttl">Passwort-Cache</string>
<string name="label_message_compression">Nachrichten-Komprimierung</string>
<string name="label_file_compression">Datei-Komprimierung</string>
<string name="label_force_v3_signature">Alte OpenPGPv3 Unterschriften erzwingen</string>
<string name="label_key_servers">Schlüsselserver</string>
<string name="label_key_id">Schlüssel-ID</string>
<string name="label_creation">Erstellungsdatum</string>
@ -253,6 +254,7 @@
<string name="error_no_signature_key">kein Signaturschlüssel angegeben</string>
<string name="error_invalid_data">Verschlüsselte Daten nicht gültig</string>
<string name="error_corrupt_data">beschädigte Daten</string>
<string name="error_integrity_check_failed">Integritätscheck fehlgeschlagen! Die Daten wurden modifiziert!</string>
<string name="error_no_symmetric_encryption_packet">Paket mit symmetrischer Verschlüsselung konnte nicht gefunden werden</string>
<string name="error_wrong_passphrase">falsches Passwort</string>
<string name="error_saving_keys">Es trat ein Fehler beim Speichern einiger Schlüssel auf</string>
@ -262,6 +264,9 @@
<string name="error_nfc_needed">NFC steht auf diesem Gerät nicht zur Verfügung!</string>
<string name="error_nothing_import">Nichts zu importieren!</string>
<string name="error_expiry_must_come_after_creation">Ablaufdatum muss später sein als das Erstellungsdatum</string>
<string name="error_can_not_delete_contact">Sie können diesen Kontakt nicht löschen, denn es ist ihr eigener.</string>
<string name="error_can_not_delete_contacts">Sie können folgende Kontakte nicht löschen, denn sie gehören Ihnen selbst:\n%s</string>
<string name="error_keyserver_query">Keyserveranfrage fehlgeschlagen</string>
<plurals name="error_can_not_delete_info">
<item quantity="one">Bitte lösche ihn unter \'Meine Schlüssel\'!</item>
<item quantity="other">Bitte lösche sie unter \'Meine Schlüssel\'!</item>
@ -271,6 +276,7 @@
<string name="progress_saving">speichern...</string>
<string name="progress_importing">importieren...</string>
<string name="progress_exporting">exportieren...</string>
<string name="progress_generating">erstelle Schlüssel, dies kann bis zu 3 Minuten dauern...</string>
<string name="progress_building_key">erstelle Schlüssel...</string>
<string name="progress_preparing_master_key">Hauptschlüssel wird vorbereitet...</string>
<string name="progress_certifying_master_key">Hauptschlüssel wird beglaubigt...</string>
@ -332,11 +338,8 @@
<string name="import_nfc_help_button">Hilfe</string>
<string name="import_clipboard_button">Füge den Schlüssel aus der Zwischenablage ein</string>
<!--Intent labels-->
<string name="intent_decrypt_file">OpenPGP: Datei entschlüsseln</string>
<string name="intent_import_key">OpenPGP: Schlüssel importieren</string>
<string name="intent_send_encrypt">OpenPGP: Verschlüsseln</string>
<string name="intent_send_decrypt">OpenPGP: Entschlüsseln</string>
<!--Remote API-->
<string name="api_no_apps">Keine registrierten Anwendungen vorhanden!\n\nAnwendungen von Dritten können Zugriff auf OpenKeychain erbitten. Nachdem Zugriff gewährt wurde, werden diese hier aufgelistet.</string>
<string name="api_settings_show_advanced">Erweiterte Einstellungen anzeigen</string>
<string name="api_settings_hide_advanced">Erweiterte Einstellungen ausblenden</string>
<string name="api_settings_no_key">Kein Schlüssel ausgewählt</string>
@ -346,13 +349,14 @@
<string name="api_settings_revoke">Zugriff widerufen</string>
<string name="api_settings_package_name">Paketname</string>
<string name="api_settings_package_signature">SHA-256 der Paketsignatur</string>
<string name="api_register_text">Folgende Anwendung beantragt Zugriff zur API von OpenKeychain.\nZugriff erlauben?\n\nVORSICHT: Sollten Sie nicht wissen, warum dieses Fenster erscheint, sollten Sie den Zugriff nicht gewähren! Sie können Zugriffe später über das Menü \'Registrierte Anwendungen\' widerrufen.</string>
<string name="api_register_allow">Zugriff erlauben</string>
<string name="api_register_disallow">Zugriff verbieten</string>
<string name="api_register_error_select_key">Bitte einen Schlüssel auswählen!</string>
<string name="api_select_pub_keys_missing_text">Für diese Benutzer-IDs wurden keine öffentlichen Schlüssel gefunden:</string>
<string name="api_select_pub_keys_dublicates_text">Für diese Benutzer-IDs existieren mehrere öffentliche Schlüssel:</string>
<string name="api_select_pub_keys_text">Bitte die Liste der Empfänger überprüfen!</string>
<string name="api_error_wrong_signature">Signaturüberprüfung fehlgeschlagen! Haben Sie diese App von einer anderen Quelle installiert? Wenn Sie eine Attacke ausschliessen können, sollten Sie die Registrierung der App in OpenPGP Keychain widerrufen und die App erneut registrieren.</string>
<string name="api_error_wrong_signature">Signaturüberprüfung fehlgeschlagen! Haben Sie diese App von einer anderen Quelle installiert? Wenn Sie eine Attacke ausschliessen können, sollten Sie die Registrierung der App in OpenKeychain widerrufen und die App erneut registrieren.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Über QR Code teilen</string>
<string name="share_qr_code_dialog_start">Mit \'Weiter\' durch alle QR-Codes gehen und diese nacheinander scannen.</string>
@ -372,6 +376,8 @@
<!--Key view-->
<string name="key_view_action_encrypt">Für diesen Kontakt verschlüsseln</string>
<string name="key_view_action_certify">Schlüssel dieses Kontakts beglaubigen</string>
<string name="key_view_tab_main">Info</string>
<string name="key_view_tab_certs">Zertifikationen</string>
<!--Navigation Drawer-->
<string name="nav_contacts">Kontakte</string>
<string name="nav_encrypt">Verschlüsseln</string>

View File

@ -266,6 +266,9 @@
<string name="error_expiry_must_come_after_creation">la fecha de caducidad debe ser posterior a la fecha de creación</string>
<string name="error_can_not_delete_contact">no puedes eliminar este contacto porque eres tú mismo.</string>
<string name="error_can_not_delete_contacts">no puedes eliminar los siguientes contactos porque son tú mismo:\n%s</string>
<string name="error_keyserver_insufficient_query">Consulta al servidor insuficiente</string>
<string name="error_keyserver_query">La consulta al servidor de claves ha fallado</string>
<string name="error_keyserver_too_many_responses">Demasiadas respuestas</string>
<plurals name="error_can_not_delete_info">
<item quantity="one">Por favor, bórralo desde la pantalla \'Mis claves\'!</item>
<item quantity="other">Por favor, bórralos desde la pantalla \'Mis claves\'!</item>
@ -337,12 +340,12 @@
<string name="import_nfc_help_button">Ayuda</string>
<string name="import_clipboard_button">Tomar la clave desde el portapapeles</string>
<!--Intent labels-->
<string name="intent_decrypt_file">OpenPGP: Descifrar archivo</string>
<string name="intent_import_key">OpenPGP: Importar clave</string>
<string name="intent_send_encrypt">OpenPGP: Cifrar</string>
<string name="intent_send_decrypt">OpenPGP: Descifrar</string>
<string name="intent_decrypt_file">Descifrar archivo con OpenKeychain</string>
<string name="intent_import_key">Importar clave con OpenKeychain</string>
<string name="intent_send_encrypt">Cifrar con OpenKeychain</string>
<string name="intent_send_decrypt">Descifrar con OpenKeychain</string>
<!--Remote API-->
<string name="api_no_apps">¡No hay aplicaciones registradas¡\n\nLas aplicaciones de terceros pueden pedir acceso a OpenPGP Keychain. Después de recibir permiso, se mostrarán aquí.</string>
<string name="api_no_apps">¡No hay aplicaciones registradas!\n\nLas aplicaciones de terceros pueden pedir permiso de acceso a OpenKeychain. Después de obtener acceso, serán enumeradas aquí.</string>
<string name="api_settings_show_advanced">Mostrar la configuración avanzada</string>
<string name="api_settings_hide_advanced">Ocultar la configuración avanzada</string>
<string name="api_settings_no_key">No se ha seleccionado ninguna clave</string>
@ -352,14 +355,14 @@
<string name="api_settings_revoke">Revocar acceso</string>
<string name="api_settings_package_name">Nombre de paquete</string>
<string name="api_settings_package_signature">SHA-256 de firma de paquete</string>
<string name="api_register_text">La aplicación mostrada pide acceso a OpenPGP Keychain.\n¿Permitir acceso?\n\nAVISO: Si no sabes por qué ha aparecido esta pantalla, ¡deniega el acceso! Puedes revocar el acceso más tarde usando la ventana \'Aplicaciones Registradas\'.</string>
<string name="api_register_text">La aplicación mostrada solicita acceso a OpenKeychain.\n¿Permitir el acceso?\n\nAVISO: Si no sabes por qué aparece esta pantalla, ¡deniega el acceso! Puedes revocarlo después usando la pantalla \'Aplicaciones registradas\'.</string>
<string name="api_register_allow">Permitir el acceso</string>
<string name="api_register_disallow">Denegar el acceso</string>
<string name="api_register_error_select_key">¡Por favor, selecciona una clave!</string>
<string name="api_select_pub_keys_missing_text">No se han encontrado claves públicas para estas IDs de usuario:</string>
<string name="api_select_pub_keys_dublicates_text">Existe más de una clave pública para estos IDs de usuario:</string>
<string name="api_select_pub_keys_text">¡Por favor, revisa la lista de destinatarios!</string>
<string name="api_error_wrong_signature">¡La comprobación de la firma ha fallado! ¿Has instalado esta app desde una fuente distinta? Si estás seguro de que esto no es un ataque, revoca el registro de esta app en OpenPGP Keychain y regístrala de nuevo.</string>
<string name="api_error_wrong_signature">¡La comprobación de la firma ha fallado! ¿Has instalado esta app desde una fuente distinta? Si estás seguro de que esto no es un ataque, revoca el registro de esta app en OpenKeychain y regístrala de nuevo.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Compartir con código QR</string>
<string name="share_qr_code_dialog_start">Pasa por todos los códigos QR usando \'Siguiente\', y escanéalos de uno en uno.</string>

View File

@ -111,6 +111,7 @@
<string name="label_passphrase_cache_ttl">Cache de la phrase de passe</string>
<string name="label_message_compression">Compression des messages</string>
<string name="label_file_compression">Compression des fichiers</string>
<string name="label_force_v3_signature">Forcer les anciennes signatures OpenPGP v3</string>
<string name="label_key_servers">Serveurs de clefs</string>
<string name="label_key_id">ID de le clef</string>
<string name="label_creation">Création</string>
@ -253,6 +254,7 @@
<string name="error_no_signature_key">aucune clef de signature n\'a été donnée</string>
<string name="error_invalid_data">aucune donnée de chiffrement valide</string>
<string name="error_corrupt_data">données corrompues</string>
<string name="error_integrity_check_failed">la vérification de l\'intégrité a échoué ! Les données ont été modifiées !</string>
<string name="error_no_symmetric_encryption_packet">paquet avec chiffrement symétrique introuvable</string>
<string name="error_wrong_passphrase">phrase de passe erronnée</string>
<string name="error_saving_keys">erreur lors de la sauvegarde de certaines clefs</string>
@ -264,6 +266,9 @@
<string name="error_expiry_must_come_after_creation">la date d\'expiration doit venir après la date de création</string>
<string name="error_can_not_delete_contact">vous ne pouvez pas supprimer ce contact car c\'est le vôtre.</string>
<string name="error_can_not_delete_contacts">vous ne pouvez pas supprimer les contacts suivants car c\'est les vôtres.\n%s</string>
<string name="error_keyserver_insufficient_query">Requête serveur insuffisante</string>
<string name="error_keyserver_query">Échec lors de l\'interrogation du serveur de clefs</string>
<string name="error_keyserver_too_many_responses">Trop de réponses</string>
<plurals name="error_can_not_delete_info">
<item quantity="one">Veuillez le supprimer depuis l\'écran « Mes Clefs »!</item>
<item quantity="other">Veuillez les supprimer depuis l\'écran « Mes Clefs »!</item>
@ -335,12 +340,12 @@
<string name="import_nfc_help_button">Aide</string>
<string name="import_clipboard_button">Obtenir la clef depuis le presse-papiers</string>
<!--Intent labels-->
<string name="intent_decrypt_file">OpenPGP : déchiffrer le ficher</string>
<string name="intent_import_key">OpenPGP : importer la clef</string>
<string name="intent_send_encrypt">OpenPGP : chiffrer</string>
<string name="intent_send_decrypt">OpenPGP : déchiffrer</string>
<string name="intent_decrypt_file">Déchiffrer le fichier avec OpenKeychain</string>
<string name="intent_import_key">Importer la clef avec OpenKeychain</string>
<string name="intent_send_encrypt">Chiffrer avec OpenKeychain</string>
<string name="intent_send_decrypt">Déchiffrer avec OpenKeychain</string>
<!--Remote API-->
<string name="api_no_apps">Aucune application enregistrée !\n\nLes applications tierces peuvent demander l\'accès au Porte-clefs OpenPGP. Après avoir autoriser l\'accès, elles seront listées ici.</string>
<string name="api_no_apps">Aucune application enregistrée !\n\nLes applications tierces peuvent demander l\'accès à OpenKeychain. Après avoir autorisé l\'accès, elles seront listées ici.</string>
<string name="api_settings_show_advanced">Afficher les paramètres avancés</string>
<string name="api_settings_hide_advanced">Masquer les paramètres avancés</string>
<string name="api_settings_no_key">Aucune clef choisie</string>
@ -350,14 +355,14 @@
<string name="api_settings_revoke">Révoquer l\'accès</string>
<string name="api_settings_package_name">Nom du paquet</string>
<string name="api_settings_package_signature">SHA-256 de la signature du paquet</string>
<string name="api_register_text">L\'application affichée demande l\'accès au Porte-clefs OpenPGP.\nPermettre l\'accès ?\n\nAvertissement : si vous ne savez pas pourquoi cet écran est apparu, refusé l\'accès ! Vous pourrez révoquer l\'accès plus tard en utilisant l\'écran « Applications enregistrées ».</string>
<string name="api_register_text">L\'application affichée demande l\'accès à OpenKeychain.\nPermettre l\'accès ?\n\nAvertissement : si vous ne savez pas pourquoi cet écran est apparu, refusez l\'accès ! Vous pourrez révoquer l\'accès plus tard en utilisant l\'écran « Applications enregistrées ».</string>
<string name="api_register_allow">Permettre l\'accès</string>
<string name="api_register_disallow">Enlever l\'accès</string>
<string name="api_register_error_select_key">Veuillez choisir une clef !</string>
<string name="api_select_pub_keys_missing_text">Aucune clef publique n\'a été trouvée pour ces IDs utilisateur :</string>
<string name="api_select_pub_keys_dublicates_text">Plus d\'une clef publique existe pour ces IDs utilisateur</string>
<string name="api_select_pub_keys_text">Veuillez revoir la liste des destinataires !</string>
<string name="api_error_wrong_signature">La vérification de la signature a échoué ! Avez-vous installé cette appli à partir d\'une source différente ? Si vous êtes sûr que ce n\'est pas une attaque, révoquer l\'enregistrement de cette appli dans le Porte-clefs OpenPGP et l\'enregistrer à nouveau.</string>
<string name="api_error_wrong_signature">La vérification de la signature a échoué ! Avez-vous installé cette appli à partir d\'une source différente ? Si vous êtes sûr que ce n\'est pas une attaque, révoquez l\'enregistrement de cette appli dans OpenKeychain et enregistrez-la à nouveau.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Partager par un code QR</string>
<string name="share_qr_code_dialog_start">Balayer tous les codes QR un par un en utilisant « Suivant ».</string>

View File

@ -1,89 +1,396 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<!--title-->
<string name="title_select_recipients">Selezionare Chiave Pubblica</string>
<string name="title_select_secret_key">Selezionare Chiave Privata</string>
<string name="title_encrypt">Cifrare</string>
<string name="title_decrypt">Decifrare</string>
<string name="title_authentication">Passphrase</string>
<string name="title_create_key">Creare Chiave</string>
<string name="title_edit_key">Modificare Chiave</string>
<string name="title_manage_public_keys">Contatti</string>
<string name="title_manage_secret_keys">Chiavi Private</string>
<string name="title_select_recipients">Seleziona Chiave Pubblica</string>
<string name="title_select_secret_key">Seleziona Chiave Privata</string>
<string name="title_encrypt">Codifica</string>
<string name="title_decrypt">Decodifica</string>
<string name="title_authentication">Frase di accesso</string>
<string name="title_create_key">Crea Chiave</string>
<string name="title_edit_key">Modifica Chiave</string>
<string name="title_preferences">Preferenze</string>
<string name="title_set_passphrase">Impostare Passphrase</string>
<string name="title_send_email">Inviare Mail...</string>
<string name="title_import_keys">Importare Chiavi</string>
<string name="title_export_key">Esportare Chiave</string>
<string name="title_export_keys">Esportare Chiavi</string>
<string name="title_api_registered_apps">App Registrate</string>
<string name="title_key_server_preference">Preferenze Server delle Chiavi</string>
<string name="title_change_pass_phrase">Cambia Frase di Accesso</string>
<string name="title_set_passphrase">Imposta Frase di Accesso</string>
<string name="title_send_email">Invia Mail...</string>
<string name="title_encrypt_to_file">Codifica File</string>
<string name="title_decrypt_to_file">Decodifica File</string>
<string name="title_import_keys">Importa Chiavi</string>
<string name="title_export_key">Esporta Chiave</string>
<string name="title_export_keys">Esporta Chiavi</string>
<string name="title_key_not_found">Chiave Non Trovata</string>
<string name="title_key_server_query">Interroga Server delle Chiavi</string>
<string name="title_send_key">Carica sul Server delle Chiavi</string>
<string name="title_unknown_signature_key">Chiave di Firma Sconosciuta</string>
<string name="title_certify_key">Certifica Chiave</string>
<string name="title_key_details">Dettagli Chiave</string>
<string name="title_help">Aiuto</string>
<!--section-->
<string name="section_user_ids">ID Utente</string>
<string name="section_keys">Chiavi</string>
<string name="section_general">Generale</string>
<string name="section_defaults">Predefiniti</string>
<string name="section_advanced">Avanzato</string>
<string name="section_master_key">Chiave Principale</string>
<string name="section_master_user_id">ID Utente Principale</string>
<string name="section_actions">Azioni</string>
<string name="section_certification_key">La Tua Chiave usata per la certificazione</string>
<string name="section_upload_key">Carica Chiave</string>
<string name="section_key_server">Server delle Chiavi</string>
<string name="section_encrypt_and_or_sign">Codifica e/o Firma</string>
<string name="section_decrypt_verify">Decodifica e Verifica</string>
<!--button-->
<string name="btn_sign">Firmare</string>
<string name="btn_decrypt">Decifrare</string>
<string name="btn_encrypt_file">Cifrare File</string>
<string name="btn_sign">Firma</string>
<string name="btn_certify">Certifica</string>
<string name="btn_decrypt">Decodifica</string>
<string name="btn_decrypt_verify">Decodifica e Verifica</string>
<string name="btn_select_encrypt_keys">Seleziona Destinatari</string>
<string name="btn_encrypt_file">Codifica File</string>
<string name="btn_save">Salva</string>
<string name="btn_do_not_save">Cancella</string>
<string name="btn_delete">Eliminare</string>
<string name="btn_do_not_save">Annulla</string>
<string name="btn_delete">Elimina</string>
<string name="btn_no_date">Nessuno</string>
<string name="btn_okay">Okay</string>
<string name="btn_change_passphrase">Cambiare passphrase</string>
<string name="btn_search">Cercare</string>
<string name="btn_change_passphrase">Cambia Frase Di Accesso</string>
<string name="btn_set_passphrase">Imposta Frase di Accesso</string>
<string name="btn_search">Cerca</string>
<string name="btn_export_to_server">Carica sul Server delle Chiavi</string>
<string name="btn_next">Prossimo</string>
<string name="btn_back">Precedente</string>
<string name="btn_clipboard">Appunti</string>
<string name="btn_share">Condividi con...</string>
<string name="btn_lookup_key">Chiave di ricerca</string>
<!--menu-->
<string name="menu_preferences">Impostazioni</string>
<string name="menu_import_from_file">Importare da file</string>
<string name="menu_import_from_qr_code">Importare da QR Code</string>
<string name="menu_delete_key">Eliminare chiave</string>
<string name="menu_create_key">Creare chiave</string>
<string name="menu_search">Cercare</string>
<string name="menu_help">Aiuto</string>
<string name="menu_import_from_file">Importa da file</string>
<string name="menu_import_from_qr_code">Importa da Codice QR</string>
<string name="menu_import">Importa</string>
<string name="menu_import_from_nfc">Importa tramite NFC</string>
<string name="menu_export_keys">Esporta tutte le chiavi</string>
<string name="menu_export_key">Esporta su un file</string>
<string name="menu_delete_key">Cancella chiave</string>
<string name="menu_create_key">Crea chiave</string>
<string name="menu_create_key_expert">Crea chiave (esperto)</string>
<string name="menu_search">Cerca</string>
<string name="menu_key_server">Importa dal server delle chiavi</string>
<string name="menu_update_key">Aggiorna dal server delle chiavi</string>
<string name="menu_export_key_to_server">Carica chiave nel server</string>
<string name="menu_share">Condividi</string>
<string name="menu_share_title_fingerprint">Condivi impronta...</string>
<string name="menu_share_title">Condividi intera chiave...</string>
<string name="menu_share_default_fingerprint">con..</string>
<string name="menu_share_default">con...</string>
<string name="menu_share_qr_code">con Codice QR</string>
<string name="menu_share_qr_code_fingerprint">con Codice QR</string>
<string name="menu_share_nfc">con NFC</string>
<string name="menu_copy_to_clipboard">Copia negli appunti</string>
<string name="menu_sign_key">Firma chiave</string>
<string name="menu_beam_preferences">Impostazioni Beam</string>
<string name="menu_key_edit_cancel">Annulla</string>
<string name="menu_encrypt_to">Codifica su...</string>
<!--label-->
<string name="label_sign">Firma</string>
<string name="label_message">Messaggio</string>
<string name="label_file">File</string>
<string name="label_no_passphrase">Nessuna Frase di Accesso</string>
<string name="label_passphrase">Frase di Accesso</string>
<string name="label_passphrase_again">Ancora</string>
<string name="label_algorithm">Algortimo</string>
<string name="label_ascii_armor">Armatura ASCII</string>
<string name="label_select_public_keys">Destinatari</string>
<string name="label_delete_after_encryption">Cancella Dopo Codifica</string>
<string name="label_delete_after_decryption">Cancella Dopo Decodifica</string>
<string name="label_encryption_algorithm">Algoritmo di Codifica</string>
<string name="label_hash_algorithm">Algoritmo di Hash</string>
<string name="label_asymmetric">Chiave Pubblica</string>
<string name="label_symmetric">Frase di Accesso</string>
<string name="label_passphrase_cache_ttl">Cache Frase di Accesso</string>
<string name="label_message_compression">Compressione Messaggio</string>
<string name="label_file_compression">Compressione File</string>
<string name="label_force_v3_signature">Forza vecchie Firme OpenPGPv3</string>
<string name="label_key_servers">Server Chiavi</string>
<string name="label_key_id">ID Chiave</string>
<string name="label_creation">Creazione</string>
<string name="label_expiry">Scadenza</string>
<string name="label_usage">Utilizzo</string>
<string name="label_key_size">Dimensione Chiave</string>
<string name="label_main_user_id">ID Utente Principale</string>
<string name="label_name">Nome</string>
<string name="label_comment">Commento</string>
<string name="label_email">Email</string>
<string name="label_send_key">Carica chiave nel server delle chiavi selezionati dopo la certificazione</string>
<string name="label_fingerprint">Impronta</string>
<string name="select_keys_button_default">Seleziona</string>
<plurals name="select_keys_button">
<item quantity="one">%d selezionato</item>
<item quantity="other">%d selezionati</item>
</plurals>
<string name="user_id_no_name">&lt;nessun nome&gt;</string>
<string name="none">&lt;nessuno&gt;</string>
<string name="no_key">&lt;nessuna chiave&gt;</string>
<string name="unknown_status"></string>
<string name="can_encrypt">puo\'; codificare</string>
<string name="can_sign">puo\' firmare</string>
<string name="expired">scaduto</string>
<string name="revoked">revocato</string>
<plurals name="n_key_servers">
<item quantity="one">%d server delle chiavi</item>
<item quantity="other">%d server delle chiavi</item>
</plurals>
<string name="fingerprint">Impronta:</string>
<string name="secret_key">Chiave Privata:</string>
<!--choice-->
<string name="choice_none">Nessuno</string>
<string name="choice_sign_only">Firma soltanto</string>
<string name="choice_encrypt_only">Codifica soltanto</string>
<string name="choice_sign_and_encrypt">Firma e Codifica</string>
<string name="choice_15secs">15 sec</string>
<string name="choice_1min">1 min</string>
<string name="choice_3mins">3 min</string>
<string name="choice_5mins">5 min</string>
<string name="choice_10mins">10 min</string>
<string name="choice_20mins">20 min</string>
<string name="choice_40mins">40 min</string>
<string name="choice_1hour">1 ora</string>
<string name="choice_2hours">2 ore</string>
<string name="choice_4hours">4 ore</string>
<string name="choice_8hours">8 ore</string>
<string name="choice_forever">sempre</string>
<string name="dsa">DSA</string>
<string name="elgamal">ElGamal</string>
<string name="rsa">RSA</string>
<string name="filemanager_title_open">Apri...</string>
<string name="warning">Attenzione</string>
<string name="error">Errore</string>
<string name="error_message">Errore: %s</string>
<!--sentences-->
<string name="wrong_passphrase">Frase di Accesso errata</string>
<string name="using_clipboard_content">Utilizzo il contenuto degli appunti.</string>
<string name="set_a_passphrase">Imposta prima una frase di accesso.</string>
<string name="no_filemanager_installed">Nessun gestore file compatibile installato.</string>
<string name="passphrases_do_not_match">Le frasi di accesso non corrispondono.</string>
<string name="passphrase_must_not_be_empty">Frasi di accesso vuote non consentite.</string>
<string name="passphrase_for_symmetric_encryption">Codifica Simmetrica.</string>
<string name="passphrase_for">Inserisci la frase di accesso per \'%s\'</string>
<string name="file_delete_confirmation">Sei sicuro di voler cancellare\n%s?</string>
<string name="file_delete_successful">Eliminato correttamente.</string>
<string name="no_file_selected">Seleziona un file prima.</string>
<string name="decryption_successful">Decodificato correttamente.</string>
<string name="encryption_successful">Codificato correttamente.</string>
<string name="encryption_to_clipboard_successful">Codificato correttamente negli appunti.</string>
<string name="enter_passphrase_twice">Inserisci la frase di accesso due volte.</string>
<string name="select_encryption_key">Seleziona almeno una chiave di codifica.</string>
<string name="select_encryption_or_signature_key">Seleziona almeno una chiave di codifica o di firma.</string>
<string name="specify_file_to_encrypt_to">Perfavore specifica quale file codificare.\nATTENZIONE: Il file sara\' sovrascritto se esistente.</string>
<string name="specify_file_to_decrypt_to">Perfavore specifica quale file decodificare.\nATTENZIONE: Il file sara\' sovrascritto se esistente.</string>
<string name="specify_file_to_export_to">Perfavore specifica su quale file esportare.\nATTENZIONE: Il file sara\' sovrascritto se esistente.</string>
<string name="specify_file_to_export_secret_keys_to">Perfavore specifica quale file esportare.\nATTENZIONE: Stai esportanto chiavi PRIVATE.\nATTENZIONE: Il file sara\' sovrascritto se esistente.</string>
<string name="key_deletion_confirmation">Vuoi veramente eliminare la chiave \'%s\'?\nNon potrai annullare!</string>
<string name="key_deletion_confirmation_multi">Vuoi veramente eliminare le chiavi selezionate?\nNon potrai annullare!</string>
<string name="secret_key_deletion_confirmation">Vuoi veramente eliminare la chiave PRIVATA \'%s\'?\nNon potrai annullare!</string>
<plurals name="keys_added_and_updated_1">
<item quantity="one">%d chiave aggiunta correttamente</item>
<item quantity="other">%d chiavi aggiunte correttamente</item>
</plurals>
<plurals name="keys_added_and_updated_2">
<item quantity="one">e %d chiave aggiornata.</item>
<item quantity="other">e %d chiavi aggiornate.</item>
</plurals>
<plurals name="keys_added">
<item quantity="one">%d chiave aggiunta correttamente.</item>
<item quantity="other">%d chiavi aggiunte correttamente.</item>
</plurals>
<plurals name="keys_updated">
<item quantity="one">%d chiave aggiornata correttamente.</item>
<item quantity="other">%d chiavi aggiornate correttamente.</item>
</plurals>
<string name="no_keys_added_or_updated">Nessuna chiave aggiunta o aggiornata.</string>
<string name="key_exported">1 chiave esportata correttamente.</string>
<string name="keys_exported">%d chiavi esportate correttamente.</string>
<string name="no_keys_exported">Nessuna chiave esportata.</string>
<string name="key_creation_el_gamal_info">Nota: solo le sottochiavi supportano ElGamal, e per ElGamal verra\' usata la grandezza chiave piu\' vicina a 1536, 2048, 3072, 4096 o 8192.</string>
<string name="key_not_found">Impossibile trovare la chiave %08X.</string>
<plurals name="keys_found">
<item quantity="one">Trovata %d chiave.</item>
<item quantity="other">Trovate %d chiavi.</item>
</plurals>
<string name="unknown_signature">Firma sconosciuta, clicca il pulsante per ricercare la chiave mancante.</string>
<plurals name="bad_keys_encountered">
<item quantity="one">%d chiave segreta non valida ignorata. Forse hai esportato con opzione\n--export-secret-subkeys\nAssicurati di esportare con\n--export-secret-keys\ninvece.</item>
<item quantity="other">%d chiavi private non valide ignorate. Forse hai esportato con opzione\n--export-secret-subkeys\nAssicurati di esportare con\n--export-secret-keys\ninvece.</item>
</plurals>
<string name="key_send_success">Chiave caricata con successo sul server</string>
<string name="key_sign_success">Chiave firmata correttamente</string>
<string name="list_empty">Lista vuota!</string>
<string name="nfc_successfull">Chiave inviata tramite NFC Beam!</string>
<string name="key_copied_to_clipboard">Chiave copiata negli appunti!</string>
<string name="key_has_already_been_signed">La chiave e\' gia\' firmata!</string>
<string name="select_key_to_sign">Per favore seleziona la chiave per la firma!</string>
<string name="key_too_big_for_sharing">Chiave troppo grande per essere condivisa in questo modo!</string>
<!--errors
no punctuation, all lowercase,
they will be put after "error_message", e.g. "Error: file not found"-->
<string name="error_file_delete_failed">Cancellazione di \'%s\' fallita</string>
<string name="error_file_not_found">File non trovato</string>
<string name="error_no_secret_key_found">nessuna chiave privata adatta trovata</string>
<string name="error_no_known_encryption_found">nessun tipo conosciuto di codifica trovata</string>
<string name="error_external_storage_not_ready">memoria esterna non pronta</string>
<string name="error_invalid_email">email non valida \'%s\'</string>
<string name="error_key_size_minimum512bit">La grandezza della chiave deve essere almeno di 512bit</string>
<string name="error_master_key_must_not_be_el_gamal">La chiave principale non puo\' essere ElGamal</string>
<string name="error_unknown_algorithm_choice">opzione algoritmo sconosciuta</string>
<string name="error_user_id_needs_a_name">devi specificare un nome</string>
<string name="error_user_id_needs_an_email_address">devi specificare un indirizzo email</string>
<string name="error_key_needs_a_user_id">necessario almeno un id utente</string>
<string name="error_main_user_id_must_not_be_empty">id utente principale non puo\' essere vuoto</string>
<string name="error_key_needs_master_key">necessaria almeno una chiave principale</string>
<string name="error_no_encryption_keys_or_passphrase">nessuna chiave di codifica o frase di accesso fornita</string>
<string name="error_signature_failed">firma fallita</string>
<string name="error_no_signature_passphrase">nessuna frase di accesso inserita</string>
<string name="error_no_signature_key">nessuna chiave di firma inserita</string>
<string name="error_invalid_data">dati di codifica non validi</string>
<string name="error_corrupt_data">dati corrotti</string>
<string name="error_integrity_check_failed">Controllo di integrita\' fallito! I dati sono stati modificati!</string>
<string name="error_no_symmetric_encryption_packet">impossibile trovare una pacchetto con codifica simmetrica</string>
<string name="error_wrong_passphrase">frase di accesso errata</string>
<string name="error_saving_keys">errore nel salvataggio di alcune chiavi</string>
<string name="error_could_not_extract_private_key">impossibile estrarre la chiave privata</string>
<string name="error_only_files_are_supported">Flusso di dati diretto senza file corrispettivo nel filesystem non e\' supportato. Supportato soltanto da ACTION_ENCRYPT_STREAM_AND_RETURN.</string>
<string name="error_jelly_bean_needed">Devi avere Android 4.1 alias Jelly Bean per usare Android NFC Beam!</string>
<string name="error_nfc_needed">NFC non disponibile nel tuo dispositivo!</string>
<string name="error_nothing_import">Niente da importare!</string>
<string name="error_expiry_must_come_after_creation">La data di scadenza deve essere postuma quella di creazione</string>
<string name="error_can_not_delete_contact">Non è possibile eliminare questo contatto, perché è il proprio.</string>
<string name="error_can_not_delete_contacts">Non è possibile eliminare i seguenti contatti perché sono i propri:\n%s</string>
<string name="error_keyserver_insufficient_query">Query di server insufficiente</string>
<string name="error_keyserver_query">Interrogazione del server delle chiavi fallita</string>
<string name="error_keyserver_too_many_responses">Troppi responsi</string>
<plurals name="error_can_not_delete_info">
<item quantity="one">Per favore cancellala dalla schermata \'Mie Chavi\'</item>
<item quantity="other">Per favore cancellatele dalla schermata \'Mie Chavi\'</item>
</plurals>
<!--progress dialogs, usually ending in '…'-->
<string name="progress_done">fatto.</string>
<string name="progress_saving">salvataggio...</string>
<string name="progress_importing">importazione...</string>
<string name="progress_exporting">esportazione...</string>
<string name="progress_generating">generazione chiave, richiede fino a 3 minuti...</string>
<string name="progress_building_key">fabbricazione chiave...</string>
<string name="progress_preparing_master_key">preparazione chiave principale...</string>
<string name="progress_certifying_master_key">certificazione chiave principale...</string>
<string name="progress_building_master_key">fabbricazione portachiavi principale...</string>
<string name="progress_adding_sub_keys">aggiunta sottochiavi...</string>
<string name="progress_saving_key_ring">salvataggio chiavi...</string>
<plurals name="progress_exporting_key">
<item quantity="one">esportazione chiave...</item>
<item quantity="other">esportazione chiavi...</item>
</plurals>
<string name="progress_extracting_signature_key">estrazione chiavi di firma...</string>
<string name="progress_extracting_key">estrazione chiave...</string>
<string name="progress_preparing_streams">preparazione flussi...</string>
<string name="progress_encrypting">codifica dati...</string>
<string name="progress_decrypting">decodifica dati...</string>
<string name="progress_preparing_signature">preparazione firma...</string>
<string name="progress_generating_signature">generazione firma...</string>
<string name="progress_processing_signature">elaborazione firma...</string>
<string name="progress_verifying_signature">verifica firma...</string>
<string name="progress_signing">firma...</string>
<string name="progress_reading_data">lettura dati...</string>
<string name="progress_finding_key">ricerca chiave...</string>
<string name="progress_decompressing_data">decompressione dati...</string>
<string name="progress_verifying_integrity">verifica integrita\'...</string>
<string name="progress_deleting_securely">eliminazione sicura di \'%s\'...</string>
<string name="progress_querying">interrogazione...</string>
<!--action strings-->
<string name="hint_public_keys">Ricerca Chiavi Pubbliche</string>
<string name="hint_secret_keys">Cerca Chiave Privata</string>
<string name="action_share_key_with">Condividi chiave con...</string>
<!--key bit length selections-->
<string name="key_size_512">512</string>
<string name="key_size_1024">1024</string>
<string name="key_size_2048">2048</string>
<string name="key_size_4096">4096</string>
<!--compression-->
<string name="compression_fast">veloce</string>
<string name="compression_very_slow">molto lento</string>
<!--Help-->
<string name="help_tab_start">Inizia</string>
<string name="help_tab_nfc_beam">NFC Beam</string>
<string name="help_tab_changelog">Changelog</string>
<string name="help_tab_about">About</string>
<string name="help_tab_changelog">Novita\'</string>
<string name="help_tab_about">Info</string>
<string name="help_about_version">Versione:</string>
<!--Import-->
<string name="import_import">Importa chiavi selezionate</string>
<string name="import_sign_and_upload">Importa, Firma e carica le chiavi selezionate</string>
<string name="import_from_clipboard">Importa dagli appunti</string>
<plurals name="import_qr_code_missing">
<item quantity="one">Codice QR con ID %s mancante</item>
<item quantity="other">Codici QR con ID %s mancanti</item>
</plurals>
<string name="import_qr_code_start_with_one">Perfavore inizia col Codice QR con ID 1</string>
<string name="import_qr_code_wrong">Codica QR deformato! Prova di nuovo!</string>
<string name="import_qr_code_finished">Scansione codice QR completata!</string>
<string name="import_qr_code_too_short_fingerprint">Impronta contenuta nel Codice QR troppo corta (&lt; 16 caratteri)</string>
<string name="import_qr_scan_button">Scansiona il Codice QR con \'Barcode Scanner\'</string>
<string name="import_nfc_text">Per ricevere le chiavi via NFC, il dispositivo deve essere sbloccato.</string>
<string name="import_nfc_help_button">Aiuto</string>
<string name="import_clipboard_button">Ottieni chiave dagli appunti</string>
<!--Intent labels-->
<string name="intent_send_encrypt">OpenPGP: Cifrare</string>
<string name="intent_send_decrypt">OpenPGP: Decifrare</string>
<string name="intent_decrypt_file">Decodifica File con OpenKeychain</string>
<string name="intent_import_key">Importa Chiave con OpenKeychain</string>
<string name="intent_send_encrypt">Codifica con OpenKeychain</string>
<string name="intent_send_decrypt">Decodifica con OpenKeychain</string>
<!--Remote API-->
<string name="api_no_apps">Nessuna app registrata!\n\nApp di terza parti possono richiedere accesso a OpenKeychain. Dopo aver concesso l\'accesso, saranno elencate qui.</string>
<string name="api_settings_show_advanced">Mostra impostazioni avanzate</string>
<string name="api_settings_hide_advanced">Nascondi impostazioni avanzate</string>
<string name="api_settings_no_key">Nessuna chiave selezionata</string>
<string name="api_settings_select_key">Selezionare chiave</string>
<string name="api_settings_save">Salvare</string>
<string name="api_settings_cancel">Cancellare</string>
<string name="api_settings_revoke">Revocare l\'accesso</string>
<string name="api_register_allow">Permettere l\'accesso</string>
<string name="api_register_disallow">Disabilitare l\'accesso</string>
<string name="api_settings_select_key">Seleziona chiave</string>
<string name="api_settings_save">Salva</string>
<string name="api_settings_cancel">Annulla</string>
<string name="api_settings_revoke">Revoca accesso</string>
<string name="api_settings_package_name">Nome Pacchetto</string>
<string name="api_settings_package_signature">SHA-256 della Firma del Pacchetto</string>
<string name="api_register_text">Le app visualizzate hanno richiesto l\'accesso a OpenKeychain.\nPermetti accesso?\n\nATTENZIONE: Se non sai perche\' questo schermata e\' apparsa, nega l\'accesso! Puoi revocare l\'accesso dopo, usando la schermata \'App Registrate\'.</string>
<string name="api_register_allow">Permetti accesso</string>
<string name="api_register_disallow">Nega accesso</string>
<string name="api_register_error_select_key">Per favore selezionare una chiave!</string>
<string name="api_select_pub_keys_missing_text">Nessuna chiave pubblica trovata per id utente:</string>
<string name="api_select_pub_keys_dublicates_text">Esistono piu\' di una chiave pubblica per gli id utenti:</string>
<string name="api_select_pub_keys_text">Per favore ricontrolla la lista destinatari!</string>
<string name="api_error_wrong_signature">Controllo della firma fallito! Hai installato questa app da una fonte diversa? Se sei sicuro che non sia un attacco, revoca la registrazione di questa app in OpenKeychain e dopo registra di nuovo l\'app.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Condividi tramite Codice QR</string>
<string name="share_qr_code_dialog_start">Scorri tutti i Codici QR usando \'Prossimo\', a scansionali uno ad uno.</string>
<string name="share_qr_code_dialog_fingerprint_text">Impronta:</string>
<string name="share_qr_code_dialog_progress">Codice QR con ID %1$d di %2$d</string>
<string name="share_nfc_dialog">Condividi tramite NFC</string>
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 chiave selezionata.</item>
<item quantity="other">%d chiavi selezionate.</item>
</plurals>
<string name="key_list_empty_text1">Nessuna chiave disponibile...</string>
<string name="key_list_empty_text2">Puoi iniziare da</string>
<string name="key_list_empty_text3">o</string>
<string name="key_list_empty_button_create">creazione della tua chiave</string>
<string name="key_list_empty_button_import">importazione chiavi.</string>
<!--Key view-->
<string name="key_view_action_encrypt">Codifica a questo contatto</string>
<string name="key_view_action_certify">Certifica la chiave di questo contatto</string>
<string name="key_view_tab_main">Info</string>
<string name="key_view_tab_certs">Certificazioni</string>
<!--Navigation Drawer-->
<string name="nav_contacts">Contatti</string>
<string name="nav_encrypt">Codifica</string>
<string name="nav_decrypt">Decodifica</string>
<string name="nav_import">Importare Chiavi</string>
<string name="nav_secret_keys">Le Mie Chiavi</string>
<string name="nav_apps">App Registrate</string>
<string name="drawer_open">Apri drawer di navigazione</string>
<string name="drawer_close">Chiudi drawer di navigazione</string>
</resources>

View File

@ -258,6 +258,9 @@
<string name="error_expiry_must_come_after_creation">期限日時は生成日時より後である必要があります</string>
<string name="error_can_not_delete_contact">この連絡先はあなたなので削除できません。</string>
<string name="error_can_not_delete_contacts">この連絡先はあなたなので削除できません。:\n%s</string>
<string name="error_keyserver_insufficient_query">サーバへのクエリーが不足しています</string>
<string name="error_keyserver_query">鍵サーバへのクエリーが失敗</string>
<string name="error_keyserver_too_many_responses">レスポンスが多すぎます</string>
<plurals name="error_can_not_delete_info">
<item quantity="other">\'自分の鍵\'画面から削除してください!</item>
</plurals>
@ -326,12 +329,12 @@
<string name="import_nfc_help_button">ヘルプ</string>
<string name="import_clipboard_button">クリップボードから鍵を取得</string>
<!--Intent labels-->
<string name="intent_decrypt_file">OpenPGP: ファイル復号</string>
<string name="intent_import_key">OpenPGP: 鍵のインポート</string>
<string name="intent_send_encrypt">OpenPGP: 暗号化</string>
<string name="intent_send_decrypt">OpenPGP: 復号化</string>
<string name="intent_decrypt_file">OpenKeychainでファイルを復号化</string>
<string name="intent_import_key">OpenKeychainに鍵をインポート</string>
<string name="intent_send_encrypt">OpenKeychainで暗号化</string>
<string name="intent_send_decrypt">OpenKeychainで復号化</string>
<!--Remote API-->
<string name="api_no_apps">登録されていないアプリケーション!\n\nサードパーティアプリケーションはOpenPGP Keychainにアクセスを要求できます。アクセスを与えた後、それらはここにリストされます。</string>
<string name="api_no_apps">登録されていないアプリケーション!\n\nサードパーティアプリケーションはOpenKeychainにアクセスを要求できます。アクセスを与えた後、それらはここにリストされます。</string>
<string name="api_settings_show_advanced">拡張設定を表示</string>
<string name="api_settings_hide_advanced">拡張設定を非表示</string>
<string name="api_settings_no_key">鍵が選択されていない</string>
@ -341,14 +344,14 @@
<string name="api_settings_revoke">破棄されたアクセス</string>
<string name="api_settings_package_name">パッケージ名</string>
<string name="api_settings_package_signature">パッケージの署名 SHA-256</string>
<string name="api_register_text">表示されているアプリケーションはOpenPGP Keychainへのアクセスを要求しています。\nアクセスを許可しますか?\n\n注意: もしなぜスクリーンに表れたかわからないなら、アクセスを許可しないでください! あなたは\'登録済みアプリケーション\'スクリーンを使って、以降のアクセスを破棄するこもできます。</string>
<string name="api_register_text">表示されているアプリケーションはOpenKeychainへのアクセスを要求しています。\nアクセスを許可しますか?\n\n注意: もしなぜスクリーンに表れたかわからないなら、アクセスを許可しないでください! あなたは\'登録済みアプリケーション\'スクリーンを使って、以降のアクセスを破棄するこもできます。</string>
<string name="api_register_allow">許可されたアクセス</string>
<string name="api_register_disallow">許可されないアクセス</string>
<string name="api_register_error_select_key">鍵を選択してください!</string>
<string name="api_select_pub_keys_missing_text">このユーザIDについて公開鍵が見付かりません:</string>
<string name="api_select_pub_keys_dublicates_text">このユーザIDについて1つ以上の公開鍵が存在します:</string>
<string name="api_select_pub_keys_text">受信者リストを確認してください!</string>
<string name="api_error_wrong_signature">署名チェックが失敗! 違うところからこのアプリをインストールしましたか? もし攻撃されてでなくそうであるなら、OpenPGP Keychainにあるこのアプリの登録を破棄し、再度アプリを登録してください。</string>
<string name="api_error_wrong_signature">署名チェックが失敗! 違うところからこのアプリをインストールしましたか? もし攻撃されてでなくそうであるなら、OpenKeychainにあるこのアプリの登録を破棄し、再度アプリを登録してください。</string>
<!--Share-->
<string name="share_qr_code_dialog_title">QRコードで共有</string>
<string name="share_qr_code_dialog_start">すべてのQRコードを見る場合、\'次\' を押して一つ一つスキャンしてください。</string>

View File

@ -220,10 +220,6 @@
<string name="import_qr_code_wrong">QR-code ongeldig. Probeer het opnieuw</string>
<string name="import_qr_code_finished">QR-code gescand</string>
<!--Intent labels-->
<string name="intent_decrypt_file">OpenPGP: bestand ontsleutelen</string>
<string name="intent_import_key">OpenPGP: sleutel importeren</string>
<string name="intent_send_encrypt">OpenPGP: versleutelen</string>
<string name="intent_send_decrypt">OpenPGP: ontsleutelen</string>
<!--Remote API-->
<string name="api_settings_no_key">Geen sleutel geselecteerd</string>
<string name="api_settings_select_key">Sleutel selecteren</string>

View File

@ -111,6 +111,7 @@
<string name="label_passphrase_cache_ttl">Помнить пароль</string>
<string name="label_message_compression">Сжатие сообщения</string>
<string name="label_file_compression">Сжатие файла</string>
<string name="label_force_v3_signature">Использовать старые OpenPGPV3 подписи</string>
<string name="label_key_servers">Серверы ключей</string>
<string name="label_key_id">ID ключа</string>
<string name="label_creation">Создан</string>
@ -261,6 +262,7 @@
<string name="error_no_signature_key">ключ для подписи не задан</string>
<string name="error_invalid_data">некорректное шифрование</string>
<string name="error_corrupt_data">данные повреждены</string>
<string name="error_integrity_check_failed">Проверка целостности не удалась! Данные изменились!</string>
<string name="error_no_symmetric_encryption_packet">не найден блок симметричного шифрования</string>
<string name="error_wrong_passphrase">неправильный пароль</string>
<string name="error_saving_keys">ошибка сохранения ключей</string>
@ -272,6 +274,9 @@
<string name="error_expiry_must_come_after_creation">срок годности не может быть раньше даты создания</string>
<string name="error_can_not_delete_contact">нельзя удалить свой собственный контакт. Пожалуйста, удалите его в разделе \'Мои ключи\'!</string>
<string name="error_can_not_delete_contacts">это ваши собственные контакты, их нельзя удалить:\n%s</string>
<string name="error_keyserver_insufficient_query">Ограничение запроса сервера</string>
<string name="error_keyserver_query">Сбой запроса сервера ключей</string>
<string name="error_keyserver_too_many_responses">Слишком много ответов</string>
<plurals name="error_can_not_delete_info">
<item quantity="one">Пожалуйста, удалите его в разделе \'Мои ключи\'!</item>
<item quantity="few">Пожалуйста, удалите их в разделе \'Мои ключи\'!</item>
@ -346,12 +351,12 @@
<string name="import_nfc_help_button">Помощь</string>
<string name="import_clipboard_button">Получить ключ из буфера</string>
<!--Intent labels-->
<string name="intent_decrypt_file">OpenPGP: Расшифровать файл</string>
<string name="intent_import_key">OpenPGP: Импортировать ключ</string>
<string name="intent_send_encrypt">OpenPGP: Зашифровать</string>
<string name="intent_send_decrypt">OpenPGP: Расшифровать</string>
<string name="intent_decrypt_file">OpenKeychain: Расшифровать файл</string>
<string name="intent_import_key">OpenKeychain: Импортировать ключ</string>
<string name="intent_send_encrypt">OpenKeychain: Зашифровать</string>
<string name="intent_send_decrypt">OpenKeychain: Расшифровать</string>
<!--Remote API-->
<string name="api_no_apps">Нет связанных программ!\n\nСторонние программы могут запросить доступ к OpenPGP Keychain, после чего они будут отражаться здесь.</string>
<string name="api_no_apps">Нет связанных программ!\n\nСторонние программы могут запросить доступ к OpenKeychain, после чего они будут отражаться здесь.</string>
<string name="api_settings_show_advanced">Показать расширенные настройки</string>
<string name="api_settings_hide_advanced">Скрыть расширенные настройки</string>
<string name="api_settings_no_key">Ключ не выбран</string>
@ -361,14 +366,14 @@
<string name="api_settings_revoke">Отозвать доступ</string>
<string name="api_settings_package_name">Наименование пакета</string>
<string name="api_settings_package_signature">SHA-256 подписи пакета</string>
<string name="api_register_text">Данное приложение запрашивает доступ к OpenPGP Keychain.\nРазрешить доступ?\n\nВНИМАНИЕ: Если вы не знаете почему возник этот запрос, откажите в доступе!\nПозже вы можете отозвать право доступа в разделе \"Зарегистрированные программы\".</string>
<string name="api_register_text">Данное приложение запрашивает доступ к OpenKeychain.\nРазрешить доступ?\n\nВНИМАНИЕ: Если вы не знаете почему возник этот запрос, откажите в доступе!\nПозже вы можете отозвать право доступа в разделе \"Зарегистрированные программы\".</string>
<string name="api_register_allow">Разрешить доступ</string>
<string name="api_register_disallow">Запретить доступ</string>
<string name="api_register_error_select_key">Пожалуйста, выберите ключ!</string>
<string name="api_select_pub_keys_missing_text">Для этих id не найдены публичные ключи:</string>
<string name="api_select_pub_keys_dublicates_text">Для этих id найдено более одного ключа:</string>
<string name="api_select_pub_keys_text">Пожалуйста, проверьте получателей!</string>
<string name="api_error_wrong_signature">Проверка подписи пакета не удалась! Если вы установили программу из другого источника, отзовите или обновите право доступа.</string>
<string name="api_error_wrong_signature">Проверка подписи пакета не удалась! Если вы установили программу из другого источника, отзовите для неё доступ к этой программе или обновите право доступа.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Отправить как QR код</string>
<string name="share_qr_code_dialog_start">Сканируйте несколько QR подряд, нажимая \'Далее\' после каждого кода.</string>

View File

@ -274,6 +274,9 @@
<string name="error_expiry_must_come_after_creation">дата завершення дії має йти після дати створення</string>
<string name="error_can_not_delete_contact">ви не можете вилучити цей контакт, тому що він ваш власний.</string>
<string name="error_can_not_delete_contacts">ви не можете вилучити наступні контакти, тому що вони - ваші власні:\n%s</string>
<string name="error_keyserver_insufficient_query">Запит обмеженого сервера</string>
<string name="error_keyserver_query">Збій сервера ключа запиту</string>
<string name="error_keyserver_too_many_responses">Забагато відповідей</string>
<plurals name="error_can_not_delete_info">
<item quantity="one">Будь ласка, вилучіть його з екрану „Мої ключі“!</item>
<item quantity="few">Будь ласка, вилучіть їх з екрану „Мої ключі“!</item>
@ -348,10 +351,10 @@
<string name="import_nfc_help_button">Довідка</string>
<string name="import_clipboard_button">Отримати ключ з буфера обміну</string>
<!--Intent labels-->
<string name="intent_decrypt_file">OpenPGP: розшифрувати файл</string>
<string name="intent_import_key">OpenPGP: імпортувати ключ</string>
<string name="intent_send_encrypt">OpenPGP: зашифрувати</string>
<string name="intent_send_decrypt">OpenPGP: розшифрувати</string>
<string name="intent_decrypt_file">Розшифрувати файл з OpenKeychain</string>
<string name="intent_import_key">Імпортувати ключ з OpenKeychain</string>
<string name="intent_send_encrypt">Зашифрувати з OpenKeychain</string>
<string name="intent_send_decrypt">Розшифрувати з OpenKeychain</string>
<!--Remote API-->
<string name="api_no_apps">Нема зареєстрованих програм!\n\nСтороні програми можуть вимагати доступ до OpenPGP Keychain. Після надання доступу вони будуть наведені тут.</string>
<string name="api_settings_show_advanced">Показати додаткові налаштування</string>
@ -370,7 +373,7 @@
<string name="api_select_pub_keys_missing_text">Не знайдено публічних ключів для цих ІД користувачів:</string>
<string name="api_select_pub_keys_dublicates_text">Більше ніж один публічний ключ існує для цих ІД користувачів:</string>
<string name="api_select_pub_keys_text">Будь ласка, перевірте список одержувачів!</string>
<string name="api_error_wrong_signature">Перевірка підпису пакета не вдалася! Якщо ви встановили програму з іншого джерела, відкличте або поновіть право доступу.</string>
<string name="api_error_wrong_signature">Перевірка підпису пакету не вдалася! Може ви встановили програму з іншого джерела? Якщо ви впевнені, що це не атака, то відкличте реєстрацію програми у OpenKeychain та знову зареєструйте її.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Відправити як штрих-код</string>
<string name="share_qr_code_dialog_start">Пройдіть через усі штрих-коди за допомогою \"Далі\", а також проскануйте їх по одному.</string>

View File

@ -135,10 +135,6 @@
<string name="import_qr_code_finished">二维码扫描完成!</string>
<string name="import_nfc_help_button">帮助</string>
<!--Intent labels-->
<string name="intent_decrypt_file">OpenPGP: 解密文件</string>
<string name="intent_import_key">OpenPGP: 导入密钥</string>
<string name="intent_send_encrypt">OpenPGP: 加密</string>
<string name="intent_send_decrypt">OpenPGP: 解密</string>
<!--Remote API-->
<string name="api_settings_show_advanced">显示高级设置</string>
<string name="api_settings_hide_advanced">隐藏高级设置</string>

View File

@ -286,6 +286,9 @@
<string name="error_expiry_must_come_after_creation">expiry date must come after creation date</string>
<string name="error_can_not_delete_contact">you can not delete this contact because it is your own.</string>
<string name="error_can_not_delete_contacts">you can not delete the following contacts because they are your own:\n%s</string>
<string name="error_keyserver_insufficient_query">Insufficient server query</string>
<string name="error_keyserver_query">Querying keyserver failed</string>
<string name="error_keyserver_too_many_responses">Too many responses</string>
<plurals name="error_can_not_delete_info">
<item quantity="one">Please delete it from the \'My Keys\' screen!</item>
<item quantity="other">Please delete them from the \'My Keys\' screen!</item>
@ -293,6 +296,7 @@
<!-- progress dialogs, usually ending in '…' -->
<string name="progress_done">done.</string>
<string name="progress_cancel">cancel</string>
<string name="progress_saving">saving…</string>
<string name="progress_importing">importing…</string>
<string name="progress_exporting">exporting…</string>
@ -368,10 +372,10 @@
<string name="import_clipboard_button">Get key from clipboard</string>
<!-- Intent labels -->
<string name="intent_decrypt_file">OpenKeychain: Decrypt File</string>
<string name="intent_import_key">OpenKeychain: Import Key</string>
<string name="intent_send_encrypt">OpenKeychain: Encrypt</string>
<string name="intent_send_decrypt">OpenKeychain: Decrypt</string>
<string name="intent_decrypt_file">Decrypt File with OpenKeychain</string>
<string name="intent_import_key">Import Key with OpenKeychain</string>
<string name="intent_send_encrypt">Encrypt with OpenKeychain</string>
<string name="intent_send_decrypt">Decrypt with OpenKeychain</string>
<!-- Remote API -->
<string name="api_no_apps">No registered applications!\n\nThird-party applications can request access to OpenKeychain. After granting access, they will be listed here.</string>

View File

@ -1,9 +1,11 @@
# OpenKeychain (for Android)
OpenKeychain is an OpenPGP implementation for Android.
The development began as a fork of Android Privacy Guard (APG).
OpenKeychain is an OpenPGP implementation for Android.
For a more detailed description and installation instructions go to http://www.openkeychain.org .
see http://sufficientlysecure.org/keychain
### Travis CI Build Status
[![Build Status](https://travis-ci.org/openpgp-keychain/openpgp-keychain.png?branch=master)](https://travis-ci.org/openpgp-keychain/openpgp-keychain)
## How to help the project?
@ -53,65 +55,17 @@ I am using the newest [Android Studio](http://developer.android.com/sdk/installi
* Select the "OpenPGP-Keychain-API" folder if you want to develop on the API example
3. Import project from external model -> choose Gradle
## Keychain API
## OpenKeychain's API
### Intent API
All Intents require user interaction, e.g. to finally encrypt the user needs to press the "Encrypt" button.
To do automatic encryption/decryption/sign/verify use the OpenPGP Remote API.
OpenKeychain provides two APIs, namely the Intent API and the Remote OpenPGP API.
The Intent API can be used without permissions to start OpenKeychain's activities for cryptographic operations, import of keys, etc.
However, it always requires user input, so that no malicious application can use this API without user intervention.
The Remote OpenPGP API is more sophisticated and allows to to operations without user interaction in the background.
When utilizing this API, OpenKeychain asks the user on first use to grant access for the calling client application.
#### Android Intent actions:
* ``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
#### OpenKeychain Intent actions:
* ``org.sufficientlysecure.keychain.action.ENCRYPT``
* To encrypt or sign text, use extra ``text`` (type: ``String``)
* or set data ``Uri`` (``intent.setData()``) pointing to a file
* Enable ASCII Armor for file encryption (encoding to Radix-64, 33% overhead) by adding the extra ``ascii_armor`` with value ``true``
* ``org.sufficientlysecure.keychain.action.DECRYPT``
* To decrypt or verify text, use extra ``text`` (type: ``String``)
* or set data ``Uri`` (``intent.setData()``) pointing to a file
* ``org.sufficientlysecure.keychain.action.IMPORT_KEY``
* Extras: ``key_bytes`` (type: ``byte[]``)
* or set data ``Uri`` (``intent.setData()``) pointing to a file
* ``org.sufficientlysecure.keychain.action.IMPORT_KEY_FROM_KEYSERVER``
* Extras: ``query`` (type: ``String``)
* or ``fingerprint`` (type: ``String``)
* ``org.sufficientlysecure.keychain.action.IMPORT_KEY_FROM_QR_CODE``
* without extras, starts Barcode Scanner to get QR Code
#### OpenKeychain special registered Intents:
* ``android.intent.action.VIEW`` with URIs following the ``openpgp4fpr`` schema. For example: ``openpgp4fpr:73EE2314F65FA92EC2390D3A718C070100012282``. This is used in QR Codes, but could also be embedded into your website. (compatible with Monkeysphere's and Guardian Project's QR Codes)
* NFC (``android.nfc.action.NDEF_DISCOVERED``) on mime type ``application/pgp-keys`` (as specified in http://tools.ietf.org/html/rfc3156, section 7)
### OpenPGP Remote API
To do fast encryption/decryption/sign/verify operations without user interaction bind to the OpenPGP remote service.
#### Try out the API
Keychain: https://play.google.com/store/apps/details?id=org.sufficientlysecure.keychain
API Demo: https://play.google.com/store/apps/details?id=org.sufficientlysecure.keychain.demo
#### Design
All apps wanting to use this generic API
just need to include the AIDL files and connect to the service. Other
OpenPGP apps can implement a service based on this AIDL definition.
The API is designed to be as easy as possible to use by apps like K-9 Mail.
The service definition defines sign, encrypt, signAndEncrypt, decryptAndVerify, and getKeyIds.
As can be seen in the API Demo, the apps themselves never need to handle key ids directly.
You can use user ids (emails) to define recipients.
If more than one public key exists for an email, OpenKeychain will handle the problem by showing a selection screen. Additionally, it is also possible to use key ids.
Also app devs never need to fiddle with private keys.
On first operation, OpenKeychain shows an activity to allow or disallow access, while also allowing to choose the private key used for this app.
Please try the Demo app out to see how it works.
#### Integration
Copy the api library from "libraries/keychain-api-library" to your project and add it as an dependency to your gradle build.
Inspect the ode found in "OpenPGP-Keychain-API" to understand how to use the API.
More technical information and examples about these APIs can be found in the project's wiki:
* [Intent API](https://github.com/openpgp-keychain/openpgp-keychain/wiki/Intent-API)
* [Remote OpenPGP API](https://github.com/openpgp-keychain/openpgp-keychain/wiki/OpenPGP-API)
## Libraries

View File

@ -11,5 +11,5 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-17
target=android-19
android.library=true

View File

@ -1,29 +0,0 @@
#Android specific
bin
gen
obj
lint.xml
local.properties
release.properties
ant.properties
*.class
*.apk
#Gradle
.gradle
build
gradle.properties
#Maven
target
pom.xml.*
#Eclipse
.project
.classpath
.settings
.metadata
#IntelliJ IDEA
.idea
*.iml

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.sufficientlysecure.keychain.api"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="19" />
<application/>
</manifest>

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -1,15 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19
android.library=true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="openpgp_list_preference_none">None</string>
</resources>

View File

@ -1,85 +0,0 @@
/*
* Copyright (C) 2014 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.openintents.openpgp;
interface IOpenPgpService {
/**
* General extras
* --------------
*
* Bundle params:
* int api_version (required)
* boolean ascii_armor (request ascii armor for ouput)
*
* returned Bundle:
* int result_code (0, 1, or 2 (see OpenPgpConstants))
* OpenPgpError error (if result_code == 0)
* Intent intent (if result_code == 2)
*
*/
/**
* Sign only
*
* optional params:
* String passphrase (for key passphrase)
*/
Bundle sign(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* Encrypt
*
* Bundle params:
* long[] key_ids
* or
* String[] user_ids (= emails of recipients) (if more than one key has this user_id, a PendingIntent is returned)
*
* optional params:
* String passphrase (for key passphrase)
*/
Bundle encrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* Sign and encrypt
*
* Bundle params:
* same as in encrypt()
*/
Bundle signAndEncrypt(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* Decrypts and verifies given input bytes. This methods handles encrypted-only, signed-and-encrypted,
* and also signed-only input.
*
* returned Bundle:
* OpenPgpSignatureResult signature_result
*/
Bundle decryptAndVerify(in Bundle params, in ParcelFileDescriptor input, in ParcelFileDescriptor output);
/**
* Retrieves key ids based on given user ids (=emails)
*
* Bundle params:
* String[] user_ids
*
* returned Bundle:
* long[] key_ids
*/
Bundle getKeyIds(in Bundle params);
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (C) 2014 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.openintents.openpgp;
import android.os.Parcel;
import android.os.Parcelable;
public class OpenPgpError implements Parcelable {
public static final int CLIENT_SIDE_ERROR = -1;
public static final int GENERIC_ERROR = 0;
public static final int INCOMPATIBLE_API_VERSIONS = 1;
public static final int NO_OR_WRONG_PASSPHRASE = 2;
public static final int NO_USER_IDS = 3;
int errorId;
String message;
public OpenPgpError() {
}
public OpenPgpError(int errorId, String message) {
this.errorId = errorId;
this.message = message;
}
public OpenPgpError(OpenPgpError b) {
this.errorId = b.errorId;
this.message = b.message;
}
public int getErrorId() {
return errorId;
}
public void setErrorId(int errorId) {
this.errorId = errorId;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(errorId);
dest.writeString(message);
}
public static final Creator<OpenPgpError> CREATOR = new Creator<OpenPgpError>() {
public OpenPgpError createFromParcel(final Parcel source) {
OpenPgpError error = new OpenPgpError();
error.errorId = source.readInt();
error.message = source.readString();
return error;
}
public OpenPgpError[] newArray(final int size) {
return new OpenPgpError[size];
}
};
}

Some files were not shown because too many files have changed in this diff Show More