aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src
diff options
context:
space:
mode:
Diffstat (limited to 'OpenPGP-Keychain/src')
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Constants.java6
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpHelper.java651
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpImportExport.java280
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java510
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java457
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpMain.java1884
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpOperation.java1068
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpToX509.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/exception/NoAsymmetricEncryptionException.java9
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralException.java9
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java24
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java104
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java6
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java6
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java7
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java39
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java4
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java33
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java140
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java18
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java6
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java57
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java6
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java12
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java6
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/LookupUnknownKeyDialogFragment.java4
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java17
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ImportKeysListLoader.java6
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java18
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java8
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java4
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/HkpKeyServer.java10
33 files changed, 2792 insertions, 2621 deletions
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Constants.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Constants.java
index 846180c0c..74b407cd4 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Constants.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Constants.java
@@ -16,6 +16,8 @@
package org.sufficientlysecure.keychain;
+import org.spongycastle.jce.provider.BouncyCastleProvider;
+
import android.os.Environment;
public final class Constants {
@@ -29,6 +31,10 @@ public final class Constants {
// as defined in http://tools.ietf.org/html/rfc3156, section 7
public static final String NFC_MIME = "application/pgp-keys";
+ // Not BC due to the use of Spongy Castle for Android
+ public static final String SC = BouncyCastleProvider.PROVIDER_NAME;
+ public static final String BOUNCY_CASTLE_PROVIDER_NAME = SC;
+
public static final String INTENT_PREFIX = PACKAGE_NAME + ".action.";
public static final class path {
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpHelper.java
index b1e332441..c5f6c5891 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,494 +17,203 @@
package org.sufficientlysecure.keychain.pgp;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.Vector;
-
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.openpgp.PGPPublicKey;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.security.SecureRandom;
+import java.util.Iterator;
+import java.util.regex.Pattern;
+
+import org.spongycastle.openpgp.PGPEncryptedDataList;
+import org.spongycastle.openpgp.PGPObjectFactory;
+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.PGPSignatureSubpacketVector;
+import org.spongycastle.openpgp.PGPUtil;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.exception.NoAsymmetricEncryptionException;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
public class PgpHelper {
- public static Date getCreationDate(PGPPublicKey key) {
- return key.getCreationTime();
- }
-
- public static Date getCreationDate(PGPSecretKey key) {
- return key.getPublicKey().getCreationTime();
- }
-
- @SuppressWarnings("unchecked")
- public static PGPPublicKey getMasterKey(PGPPublicKeyRing keyRing) {
- if (keyRing == null) {
- return null;
- }
- for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) {
- if (key.isMasterKey()) {
- return key;
- }
- }
-
- return null;
- }
-
- @SuppressWarnings("unchecked")
- public static PGPSecretKey getMasterKey(PGPSecretKeyRing keyRing) {
- if (keyRing == null) {
- return null;
- }
- for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
- if (key.isMasterKey()) {
- return key;
- }
- }
-
- return null;
- }
-
- @SuppressWarnings("unchecked")
- public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) {
- long cnt = 0;
- if (keyRing == null) {
- return null;
- }
- for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
- if (cnt == num) {
- return key;
- }
- cnt++;
- }
-
- return null;
- }
-
- @SuppressWarnings("unchecked")
- public static Vector<PGPPublicKey> getEncryptKeys(PGPPublicKeyRing keyRing) {
- Vector<PGPPublicKey> encryptKeys = new Vector<PGPPublicKey>();
-
- for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) {
- if (isEncryptionKey(key)) {
- encryptKeys.add(key);
- }
- }
-
- return encryptKeys;
- }
-
- @SuppressWarnings("unchecked")
- public static Vector<PGPSecretKey> getSigningKeys(PGPSecretKeyRing keyRing) {
- Vector<PGPSecretKey> signingKeys = new Vector<PGPSecretKey>();
-
- for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
- if (isSigningKey(key)) {
- signingKeys.add(key);
- }
- }
-
- return signingKeys;
- }
-
- @SuppressWarnings("unchecked")
- public static Vector<PGPSecretKey> getCertificationKeys(PGPSecretKeyRing keyRing) {
- Vector<PGPSecretKey> signingKeys = new Vector<PGPSecretKey>();
-
- for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
- if (isCertificationKey(key)) {
- signingKeys.add(key);
- }
- }
-
- return signingKeys;
- }
-
- public static Vector<PGPPublicKey> getUsableEncryptKeys(PGPPublicKeyRing keyRing) {
- Vector<PGPPublicKey> usableKeys = new Vector<PGPPublicKey>();
- Vector<PGPPublicKey> encryptKeys = getEncryptKeys(keyRing);
- PGPPublicKey masterKey = null;
- for (int i = 0; i < encryptKeys.size(); ++i) {
- PGPPublicKey key = encryptKeys.get(i);
- if (!isExpired(key)) {
- if (key.isMasterKey()) {
- masterKey = key;
- } else {
- usableKeys.add(key);
+ public static Pattern PGP_MESSAGE = Pattern.compile(
+ ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL);
+
+ public static Pattern PGP_SIGNED_MESSAGE = Pattern
+ .compile(
+ ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
+ Pattern.DOTALL);
+
+ public static Pattern PGP_PUBLIC_KEY = Pattern.compile(
+ ".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
+ Pattern.DOTALL);
+
+ public static String getVersion(Context context) {
+ String version = null;
+ try {
+ PackageInfo pi = context.getPackageManager().getPackageInfo(Constants.PACKAGE_NAME, 0);
+ version = pi.versionName;
+ return version;
+ } catch (NameNotFoundException e) {
+ Log.e(Constants.TAG, "Version could not be retrieved!", e);
+ return "0.0.0";
+ }
+ }
+
+ public static String getFullVersion(Context context) {
+ return "OpenPGP Keychain v" + getVersion(context);
+ }
+
+ public static long getDecryptionKeyId(Context context, InputStream inputStream)
+ throws PgpGeneralException, NoAsymmetricEncryptionException, IOException {
+ InputStream in = PGPUtil.getDecoderStream(inputStream);
+ PGPObjectFactory pgpF = new PGPObjectFactory(in);
+ PGPEncryptedDataList enc;
+ Object o = pgpF.nextObject();
+
+ // the first object might be a PGP marker packet.
+ if (o instanceof PGPEncryptedDataList) {
+ enc = (PGPEncryptedDataList) o;
+ } else {
+ enc = (PGPEncryptedDataList) pgpF.nextObject();
+ }
+
+ if (enc == null) {
+ throw new PgpGeneralException(context.getString(R.string.error_invalidData));
+ }
+
+ // TODO: currently we always only look at the first known key
+ // find the secret key
+ PGPSecretKey secretKey = null;
+ Iterator<?> it = enc.getEncryptedDataObjects();
+ boolean gotAsymmetricEncryption = false;
+ while (it.hasNext()) {
+ Object obj = it.next();
+ if (obj instanceof PGPPublicKeyEncryptedData) {
+ gotAsymmetricEncryption = true;
+ PGPPublicKeyEncryptedData pbe = (PGPPublicKeyEncryptedData) obj;
+ secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, pbe.getKeyID());
+ if (secretKey != null) {
+ break;
}
}
}
- if (masterKey != null) {
- usableKeys.add(masterKey);
- }
- return usableKeys;
- }
- public static boolean isExpired(PGPPublicKey key) {
- Date creationDate = getCreationDate(key);
- Date expiryDate = getExpiryDate(key);
- Date now = new Date();
- if (now.compareTo(creationDate) >= 0
- && (expiryDate == null || now.compareTo(expiryDate) <= 0)) {
- return false;
+ if (!gotAsymmetricEncryption) {
+ throw new NoAsymmetricEncryptionException();
}
- return true;
- }
- public static boolean isExpired(PGPSecretKey key) {
- return isExpired(key.getPublicKey());
- }
-
- public static Vector<PGPSecretKey> getUsableCertificationKeys(PGPSecretKeyRing keyRing) {
- Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>();
- Vector<PGPSecretKey> signingKeys = getCertificationKeys(keyRing);
- PGPSecretKey masterKey = null;
- for (int i = 0; i < signingKeys.size(); ++i) {
- PGPSecretKey key = signingKeys.get(i);
- if (key.isMasterKey()) {
- masterKey = key;
- } else {
- usableKeys.add(key);
- }
- }
- if (masterKey != null) {
- usableKeys.add(masterKey);
- }
- return usableKeys;
- }
-
- public static Vector<PGPSecretKey> getUsableSigningKeys(PGPSecretKeyRing keyRing) {
- Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>();
- Vector<PGPSecretKey> signingKeys = getSigningKeys(keyRing);
- PGPSecretKey masterKey = null;
- for (int i = 0; i < signingKeys.size(); ++i) {
- PGPSecretKey key = signingKeys.get(i);
- if (key.isMasterKey()) {
- masterKey = key;
- } else {
- usableKeys.add(key);
- }
- }
- if (masterKey != null) {
- usableKeys.add(masterKey);
- }
- return usableKeys;
- }
-
- public static Date getExpiryDate(PGPPublicKey key) {
- Date creationDate = getCreationDate(key);
- if (key.getValidDays() == 0) {
- // no expiry
- return null;
- }
- Calendar calendar = GregorianCalendar.getInstance();
- calendar.setTime(creationDate);
- calendar.add(Calendar.DATE, key.getValidDays());
- Date expiryDate = calendar.getTime();
-
- return expiryDate;
- }
-
- public static Date getExpiryDate(PGPSecretKey key) {
- return getExpiryDate(key.getPublicKey());
- }
-
- public static PGPPublicKey getEncryptPublicKey(Context context, long masterKeyId) {
- PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(context,
- masterKeyId);
- if (keyRing == null) {
- Log.e(Constants.TAG, "keyRing is null!");
- return null;
- }
- Vector<PGPPublicKey> encryptKeys = getUsableEncryptKeys(keyRing);
- if (encryptKeys.size() == 0) {
- Log.e(Constants.TAG, "encryptKeys is null!");
- return null;
- }
- return encryptKeys.get(0);
- }
-
- public static PGPSecretKey getCertificationKey(Context context, long masterKeyId) {
- PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context,
- masterKeyId);
- if (keyRing == null) {
- return null;
- }
- Vector<PGPSecretKey> signingKeys = getUsableCertificationKeys(keyRing);
- if (signingKeys.size() == 0) {
- return null;
- }
- return signingKeys.get(0);
- }
-
- public static PGPSecretKey getSigningKey(Context context, long masterKeyId) {
- PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context,
- masterKeyId);
- if (keyRing == null) {
- return null;
- }
- Vector<PGPSecretKey> signingKeys = getUsableSigningKeys(keyRing);
- if (signingKeys.size() == 0) {
- return null;
- }
- return signingKeys.get(0);
- }
-
- @SuppressWarnings("unchecked")
- public static String getMainUserId(PGPPublicKey key) {
- for (String userId : new IterableIterator<String>(key.getUserIDs())) {
- return userId;
- }
- return null;
- }
-
- @SuppressWarnings("unchecked")
- public static String getMainUserId(PGPSecretKey key) {
- for (String userId : new IterableIterator<String>(key.getUserIDs())) {
- return userId;
- }
- return null;
- }
-
- public static String getMainUserIdSafe(Context context, PGPPublicKey key) {
- String userId = getMainUserId(key);
- if (userId == null || userId.equals("")) {
- userId = context.getString(R.string.unknownUserId);
- }
- return userId;
- }
-
- public static String getMainUserIdSafe(Context context, PGPSecretKey key) {
- String userId = getMainUserId(key);
- if (userId == null || userId.equals("")) {
- userId = context.getString(R.string.unknownUserId);
- }
- return userId;
- }
-
- @SuppressWarnings("unchecked")
- public static boolean isEncryptionKey(PGPPublicKey key) {
- if (!key.isEncryptionKey()) {
- return false;
- }
-
- if (key.getVersion() <= 3) {
- // this must be true now
- return key.isEncryptionKey();
- }
-
- // special cases
- if (key.getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT) {
- return true;
- }
-
- if (key.getAlgorithm() == PGPPublicKey.RSA_ENCRYPT) {
- return true;
- }
-
- for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) {
- if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) {
- continue;
- }
- PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
-
- if (hashed != null
- && (hashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
- return true;
- }
-
- PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
-
- if (unhashed != null
- && (unhashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
- return true;
- }
- }
- return false;
- }
-
- public static boolean isEncryptionKey(PGPSecretKey key) {
- return isEncryptionKey(key.getPublicKey());
- }
-
- @SuppressWarnings("unchecked")
- public static boolean isSigningKey(PGPPublicKey key) {
- if (key.getVersion() <= 3) {
- return true;
- }
-
- // special case
- if (key.getAlgorithm() == PGPPublicKey.RSA_SIGN) {
- return true;
- }
-
- for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) {
- if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) {
- continue;
- }
- PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
-
- if (hashed != null && (hashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) {
- return true;
- }
-
- PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
-
- if (unhashed != null && (unhashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) {
- return true;
- }
- }
-
- return false;
- }
-
- public static boolean isSigningKey(PGPSecretKey key) {
- return isSigningKey(key.getPublicKey());
- }
-
- @SuppressWarnings("unchecked")
- public static boolean isCertificationKey(PGPPublicKey key) {
- if (key.getVersion() <= 3) {
- return true;
- }
-
- for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) {
- if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) {
- continue;
- }
- PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
-
- if (hashed != null && (hashed.getKeyFlags() & KeyFlags.CERTIFY_OTHER) != 0) {
- return true;
- }
-
- PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
-
- if (unhashed != null && (unhashed.getKeyFlags() & KeyFlags.CERTIFY_OTHER) != 0) {
- return true;
- }
- }
-
- return false;
- }
-
- public static boolean isCertificationKey(PGPSecretKey key) {
- return isCertificationKey(key.getPublicKey());
- }
-
- public static String getAlgorithmInfo(PGPPublicKey key) {
- return getAlgorithmInfo(key.getAlgorithm(), key.getBitStrength());
- }
-
- public static String getAlgorithmInfo(PGPSecretKey key) {
- return getAlgorithmInfo(key.getPublicKey());
- }
-
- public static String getAlgorithmInfo(int algorithm, int keySize) {
- String algorithmStr = null;
-
- switch (algorithm) {
- case PGPPublicKey.RSA_ENCRYPT:
- case PGPPublicKey.RSA_GENERAL:
- case PGPPublicKey.RSA_SIGN: {
- algorithmStr = "RSA";
- break;
- }
-
- case PGPPublicKey.DSA: {
- algorithmStr = "DSA";
- break;
- }
-
- case PGPPublicKey.ELGAMAL_ENCRYPT:
- case PGPPublicKey.ELGAMAL_GENERAL: {
- algorithmStr = "ElGamal";
- break;
- }
-
- default: {
- algorithmStr = "???";
- break;
- }
- }
- return algorithmStr + ", " + keySize + "bit";
- }
-
- public static String convertFingerprintToHex(byte[] fp) {
- String fingerPrint = "";
- for (int i = 0; i < fp.length; ++i) {
- if (i != 0 && i % 10 == 0) {
- fingerPrint += " ";
- } else if (i != 0 && i % 2 == 0) {
- fingerPrint += " ";
- }
- String chunk = Integer.toHexString((fp[i] + 256) % 256).toUpperCase(Locale.US);
- while (chunk.length() < 2) {
- chunk = "0" + chunk;
- }
- fingerPrint += chunk;
- }
-
- return fingerPrint;
-
- }
-
- public static String getFingerPrint(Context context, long keyId) {
- PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, keyId);
- // if it is no public key get it from your own keys...
- if (key == null) {
- PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId);
- if (secretKey == null) {
- Log.e(Constants.TAG, "Key could not be found!");
- return null;
- }
- key = secretKey.getPublicKey();
- }
-
- return convertFingerprintToHex(key.getFingerprint());
- }
-
- public static boolean isSecretKeyPrivateEmpty(PGPSecretKey secretKey) {
- return secretKey.isPrivateKeyEmpty();
- }
-
- public static boolean isSecretKeyPrivateEmpty(Context context, long keyId) {
- PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId);
if (secretKey == null) {
- Log.e(Constants.TAG, "Key could not be found!");
- return false; // could be a public key, assume it is not empty
- }
- return isSecretKeyPrivateEmpty(secretKey);
- }
-
- public static String getSmallFingerPrint(long keyId) {
- String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US);
- while (fingerPrint.length() < 8) {
- fingerPrint = "0" + fingerPrint;
- }
- return fingerPrint;
+ return Id.key.none;
+ }
+
+ return secretKey.getKeyID();
+ }
+
+ public static int getStreamContent(Context context, InputStream inStream) throws IOException {
+ InputStream in = PGPUtil.getDecoderStream(inStream);
+ PGPObjectFactory pgpF = new PGPObjectFactory(in);
+ Object object = pgpF.nextObject();
+ while (object != null) {
+ if (object instanceof PGPPublicKeyRing || object instanceof PGPSecretKeyRing) {
+ return Id.content.keys;
+ } else if (object instanceof PGPEncryptedDataList) {
+ return Id.content.encrypted_data;
+ }
+ object = pgpF.nextObject();
+ }
+
+ return Id.content.unknown;
+ }
+
+ /**
+ * Generate a random filename
+ *
+ * @param length
+ * @return
+ */
+ public static String generateRandomFilename(int length) {
+ SecureRandom random = new SecureRandom();
+
+ byte bytes[] = new byte[length];
+ random.nextBytes(bytes);
+ String result = "";
+ for (int i = 0; i < length; ++i) {
+ int v = (bytes[i] + 256) % 64;
+ if (v < 10) {
+ result += (char) ('0' + v);
+ } else if (v < 36) {
+ result += (char) ('A' + v - 10);
+ } else if (v < 62) {
+ result += (char) ('a' + v - 36);
+ } else if (v == 62) {
+ result += '_';
+ } else if (v == 63) {
+ result += '.';
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Go once through stream to get length of stream. The length is later used to display progress
+ * when encrypting/decrypting
+ *
+ * @param in
+ * @return
+ * @throws IOException
+ */
+ public static long getLengthOfStream(InputStream in) throws IOException {
+ long size = 0;
+ long n = 0;
+ byte dummy[] = new byte[0x10000];
+ while ((n = in.read(dummy)) > 0) {
+ size += n;
+ }
+ return size;
+ }
+
+ /**
+ * Deletes file securely by overwriting it with random data before deleting it.
+ *
+ * TODO: Does this really help on flash storage?
+ *
+ * @param context
+ * @param progress
+ * @param file
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ public static void deleteFileSecurely(Context context, ProgressDialogUpdater progress, File file)
+ throws FileNotFoundException, IOException {
+ long length = file.length();
+ SecureRandom random = new SecureRandom();
+ RandomAccessFile raf = new RandomAccessFile(file, "rws");
+ raf.seek(0);
+ raf.getFilePointer();
+ byte[] data = new byte[1 << 16];
+ int pos = 0;
+ String msg = context.getString(R.string.progress_deletingSecurely, file.getName());
+ while (pos < length) {
+ if (progress != null)
+ progress.setProgress(msg, (int) (100 * pos / length), 100);
+ random.nextBytes(data);
+ raf.write(data);
+ pos += data.length;
+ }
+ raf.close();
+ file.delete();
}
-
- public static String keyToHex(long keyId) {
- return getSmallFingerPrint(keyId >> 32) + getSmallFingerPrint(keyId);
- }
-
- public static long keyFromHex(String data) {
- int len = data.length();
- String s2 = data.substring(len - 8);
- String s1 = data.substring(0, len - 8);
- return (Long.parseLong(s1, 16) << 32) | Long.parseLong(s2, 16);
- }
-
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
new file mode 100644
index 000000000..c4ce3d29a
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.sufficientlysecure.keychain.pgp;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+import org.spongycastle.bcpg.ArmoredOutputStream;
+import org.spongycastle.openpgp.PGPException;
+import org.spongycastle.openpgp.PGPKeyRing;
+import org.spongycastle.openpgp.PGPObjectFactory;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.spongycastle.openpgp.PGPSecretKey;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.spongycastle.openpgp.PGPUtil;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Id;
+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.util.HkpKeyServer;
+import org.sufficientlysecure.keychain.util.InputData;
+import org.sufficientlysecure.keychain.util.IterableIterator;
+import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
+import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Environment;
+
+public class PgpImportExport {
+ private Context mContext;
+ private ProgressDialogUpdater mProgress;
+
+ public PgpImportExport(Context context, ProgressDialogUpdater progress) {
+ super();
+ this.mContext = context;
+ this.mProgress = progress;
+ }
+
+ public void updateProgress(int message, int current, int total) {
+ if (mProgress != null) {
+ mProgress.setProgress(message, current, total);
+ }
+ }
+
+ public void updateProgress(int current, int total) {
+ if (mProgress != null) {
+ mProgress.setProgress(current, total);
+ }
+ }
+
+ public boolean uploadKeyRingToServer(HkpKeyServer server, PGPPublicKeyRing keyring) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ArmoredOutputStream aos = new ArmoredOutputStream(bos);
+ try {
+ aos.write(keyring.getEncoded());
+ aos.close();
+
+ String armouredKey = bos.toString("UTF-8");
+ server.add(armouredKey);
+
+ return true;
+ } catch (IOException e) {
+ return false;
+ } catch (AddKeyException e) {
+ // TODO: tell the user?
+ return false;
+ } finally {
+ try {
+ bos.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ public Bundle importKeyRings(InputData data) throws PgpGeneralException, FileNotFoundException,
+ PGPException, IOException {
+ Bundle returnData = new Bundle();
+
+ updateProgress(R.string.progress_importingSecretKeys, 0, 100);
+
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_externalStorageNotReady));
+ }
+
+ PositionAwareInputStream progressIn = new PositionAwareInputStream(data.getInputStream());
+
+ // need to have access to the bufferedInput, so we can reuse it for the possible
+ // PGPObject chunks after the first one, e.g. files with several consecutive ASCII
+ // armour blocks
+ BufferedInputStream bufferedInput = new BufferedInputStream(progressIn);
+ int newKeys = 0;
+ int oldKeys = 0;
+ int badKeys = 0;
+ try {
+
+ // read all available blocks... (asc files can contain many blocks with BEGIN END)
+ while (bufferedInput.available() > 0) {
+ InputStream in = PGPUtil.getDecoderStream(bufferedInput);
+ PGPObjectFactory objectFactory = new PGPObjectFactory(in);
+
+ // go through all objects in this block
+ Object obj;
+ while ((obj = objectFactory.nextObject()) != null) {
+ Log.d(Constants.TAG, "Found class: " + obj.getClass());
+
+ if (obj instanceof PGPKeyRing) {
+ PGPKeyRing keyring = (PGPKeyRing) obj;
+
+ int status = Integer.MIN_VALUE; // out of bounds value
+
+ status = storeKeyRingInCache(keyring);
+
+ if (status == Id.return_value.error) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_savingKeys));
+ }
+
+ // update the counts to display to the user at the end
+ if (status == Id.return_value.updated) {
+ ++oldKeys;
+ } else if (status == Id.return_value.ok) {
+ ++newKeys;
+ } else if (status == Id.return_value.bad) {
+ ++badKeys;
+ }
+
+ updateProgress((int) (100 * progressIn.position() / data.getSize()), 100);
+ } else {
+ Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!");
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e(Constants.TAG, "Exception on parsing key file!", e);
+ }
+
+ returnData.putInt(KeychainIntentService.RESULT_IMPORT_ADDED, newKeys);
+ returnData.putInt(KeychainIntentService.RESULT_IMPORT_UPDATED, oldKeys);
+ returnData.putInt(KeychainIntentService.RESULT_IMPORT_BAD, badKeys);
+
+ updateProgress(R.string.progress_done, 100, 100);
+
+ return returnData;
+ }
+
+ public Bundle exportKeyRings(ArrayList<Long> keyRingMasterKeyIds, int keyType,
+ OutputStream outStream) throws PgpGeneralException, FileNotFoundException,
+ PGPException, IOException {
+ Bundle returnData = new Bundle();
+
+ if (keyRingMasterKeyIds.size() == 1) {
+ updateProgress(R.string.progress_exportingKey, 0, 100);
+ } else {
+ updateProgress(R.string.progress_exportingKeys, 0, 100);
+ }
+
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_externalStorageNotReady));
+ }
+
+ // export public keyrings...
+ ArmoredOutputStream outPub = new ArmoredOutputStream(outStream);
+ outPub.setHeader("Version", PgpHelper.getFullVersion(mContext));
+
+ int numKeys = 0;
+ for (int i = 0; i < keyRingMasterKeyIds.size(); ++i) {
+ // double the needed time if exporting both public and secret parts
+ if (keyType == Id.type.secret_key) {
+ updateProgress(i * 100 / keyRingMasterKeyIds.size() / 2, 100);
+ } else {
+ updateProgress(i * 100 / keyRingMasterKeyIds.size(), 100);
+ }
+
+ PGPPublicKeyRing publicKeyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(
+ mContext, keyRingMasterKeyIds.get(i));
+
+ if (publicKeyRing != null) {
+ publicKeyRing.encode(outPub);
+ }
+ ++numKeys;
+ }
+ outPub.close();
+
+ // if we export secret keyrings, append all secret parts after the public parts
+ if (keyType == Id.type.secret_key) {
+ ArmoredOutputStream outSec = new ArmoredOutputStream(outStream);
+ outSec.setHeader("Version", PgpHelper.getFullVersion(mContext));
+
+ for (int i = 0; i < keyRingMasterKeyIds.size(); ++i) {
+ updateProgress(i * 100 / keyRingMasterKeyIds.size() / 2, 100);
+
+ PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(
+ mContext, keyRingMasterKeyIds.get(i));
+
+ if (secretKeyRing != null) {
+ secretKeyRing.encode(outSec);
+ }
+ }
+ outSec.close();
+ }
+
+ returnData.putInt(KeychainIntentService.RESULT_EXPORT, numKeys);
+
+ updateProgress(R.string.progress_done, 100, 100);
+
+ return returnData;
+ }
+
+ /**
+ * TODO: implement Id.return_value.updated as status when key already existed
+ *
+ * @param context
+ * @param keyring
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public int storeKeyRingInCache(PGPKeyRing keyring) {
+ int status = Integer.MIN_VALUE; // out of bounds value (Id.return_value.*)
+ try {
+ if (keyring instanceof PGPSecretKeyRing) {
+ PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
+ boolean save = true;
+
+ for (PGPSecretKey testSecretKey : new IterableIterator<PGPSecretKey>(
+ secretKeyRing.getSecretKeys())) {
+ if (!testSecretKey.isMasterKey()) {
+ if (PgpKeyHelper.isSecretKeyPrivateEmpty(testSecretKey)) {
+ // this is bad, something is very wrong...
+ save = false;
+ status = Id.return_value.bad;
+ }
+ }
+ }
+
+ if (save) {
+ ProviderHelper.saveKeyRing(mContext, secretKeyRing);
+ // TODO: remove status returns, use exceptions!
+ status = Id.return_value.ok;
+ }
+ } else if (keyring instanceof PGPPublicKeyRing) {
+ PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring;
+ ProviderHelper.saveKeyRing(mContext, publicKeyRing);
+ // TODO: remove status returns, use exceptions!
+ status = Id.return_value.ok;
+ }
+ } catch (IOException e) {
+ status = Id.return_value.error;
+ }
+
+ return status;
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
new file mode 100644
index 000000000..be4f25bb0
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.sufficientlysecure.keychain.pgp;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.Vector;
+
+import org.spongycastle.bcpg.sig.KeyFlags;
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.spongycastle.openpgp.PGPSecretKey;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.spongycastle.openpgp.PGPSignature;
+import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.util.IterableIterator;
+import org.sufficientlysecure.keychain.util.Log;
+
+import android.content.Context;
+
+public class PgpKeyHelper {
+
+ public static Date getCreationDate(PGPPublicKey key) {
+ return key.getCreationTime();
+ }
+
+ public static Date getCreationDate(PGPSecretKey key) {
+ return key.getPublicKey().getCreationTime();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static PGPPublicKey getMasterKey(PGPPublicKeyRing keyRing) {
+ if (keyRing == null) {
+ return null;
+ }
+ for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) {
+ if (key.isMasterKey()) {
+ return key;
+ }
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static PGPSecretKey getMasterKey(PGPSecretKeyRing keyRing) {
+ if (keyRing == null) {
+ return null;
+ }
+ for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
+ if (key.isMasterKey()) {
+ return key;
+ }
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) {
+ long cnt = 0;
+ if (keyRing == null) {
+ return null;
+ }
+ for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
+ if (cnt == num) {
+ return key;
+ }
+ cnt++;
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Vector<PGPPublicKey> getEncryptKeys(PGPPublicKeyRing keyRing) {
+ Vector<PGPPublicKey> encryptKeys = new Vector<PGPPublicKey>();
+
+ for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) {
+ if (isEncryptionKey(key)) {
+ encryptKeys.add(key);
+ }
+ }
+
+ return encryptKeys;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Vector<PGPSecretKey> getSigningKeys(PGPSecretKeyRing keyRing) {
+ Vector<PGPSecretKey> signingKeys = new Vector<PGPSecretKey>();
+
+ for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
+ if (isSigningKey(key)) {
+ signingKeys.add(key);
+ }
+ }
+
+ return signingKeys;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Vector<PGPSecretKey> getCertificationKeys(PGPSecretKeyRing keyRing) {
+ Vector<PGPSecretKey> signingKeys = new Vector<PGPSecretKey>();
+
+ for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
+ if (isCertificationKey(key)) {
+ signingKeys.add(key);
+ }
+ }
+
+ return signingKeys;
+ }
+
+ public static Vector<PGPPublicKey> getUsableEncryptKeys(PGPPublicKeyRing keyRing) {
+ Vector<PGPPublicKey> usableKeys = new Vector<PGPPublicKey>();
+ Vector<PGPPublicKey> encryptKeys = getEncryptKeys(keyRing);
+ PGPPublicKey masterKey = null;
+ for (int i = 0; i < encryptKeys.size(); ++i) {
+ PGPPublicKey key = encryptKeys.get(i);
+ if (!isExpired(key)) {
+ if (key.isMasterKey()) {
+ masterKey = key;
+ } else {
+ usableKeys.add(key);
+ }
+ }
+ }
+ if (masterKey != null) {
+ usableKeys.add(masterKey);
+ }
+ return usableKeys;
+ }
+
+ public static boolean isExpired(PGPPublicKey key) {
+ Date creationDate = getCreationDate(key);
+ Date expiryDate = getExpiryDate(key);
+ Date now = new Date();
+ if (now.compareTo(creationDate) >= 0
+ && (expiryDate == null || now.compareTo(expiryDate) <= 0)) {
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean isExpired(PGPSecretKey key) {
+ return isExpired(key.getPublicKey());
+ }
+
+ public static Vector<PGPSecretKey> getUsableCertificationKeys(PGPSecretKeyRing keyRing) {
+ Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>();
+ Vector<PGPSecretKey> signingKeys = getCertificationKeys(keyRing);
+ PGPSecretKey masterKey = null;
+ for (int i = 0; i < signingKeys.size(); ++i) {
+ PGPSecretKey key = signingKeys.get(i);
+ if (key.isMasterKey()) {
+ masterKey = key;
+ } else {
+ usableKeys.add(key);
+ }
+ }
+ if (masterKey != null) {
+ usableKeys.add(masterKey);
+ }
+ return usableKeys;
+ }
+
+ public static Vector<PGPSecretKey> getUsableSigningKeys(PGPSecretKeyRing keyRing) {
+ Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>();
+ Vector<PGPSecretKey> signingKeys = getSigningKeys(keyRing);
+ PGPSecretKey masterKey = null;
+ for (int i = 0; i < signingKeys.size(); ++i) {
+ PGPSecretKey key = signingKeys.get(i);
+ if (key.isMasterKey()) {
+ masterKey = key;
+ } else {
+ usableKeys.add(key);
+ }
+ }
+ if (masterKey != null) {
+ usableKeys.add(masterKey);
+ }
+ return usableKeys;
+ }
+
+ public static Date getExpiryDate(PGPPublicKey key) {
+ Date creationDate = getCreationDate(key);
+ if (key.getValidDays() == 0) {
+ // no expiry
+ return null;
+ }
+ Calendar calendar = GregorianCalendar.getInstance();
+ calendar.setTime(creationDate);
+ calendar.add(Calendar.DATE, key.getValidDays());
+ Date expiryDate = calendar.getTime();
+
+ return expiryDate;
+ }
+
+ public static Date getExpiryDate(PGPSecretKey key) {
+ return getExpiryDate(key.getPublicKey());
+ }
+
+ public static PGPPublicKey getEncryptPublicKey(Context context, long masterKeyId) {
+ PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(context,
+ masterKeyId);
+ if (keyRing == null) {
+ Log.e(Constants.TAG, "keyRing is null!");
+ return null;
+ }
+ Vector<PGPPublicKey> encryptKeys = getUsableEncryptKeys(keyRing);
+ if (encryptKeys.size() == 0) {
+ Log.e(Constants.TAG, "encryptKeys is null!");
+ return null;
+ }
+ return encryptKeys.get(0);
+ }
+
+ public static PGPSecretKey getCertificationKey(Context context, long masterKeyId) {
+ PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context,
+ masterKeyId);
+ if (keyRing == null) {
+ return null;
+ }
+ Vector<PGPSecretKey> signingKeys = getUsableCertificationKeys(keyRing);
+ if (signingKeys.size() == 0) {
+ return null;
+ }
+ return signingKeys.get(0);
+ }
+
+ public static PGPSecretKey getSigningKey(Context context, long masterKeyId) {
+ PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(context,
+ masterKeyId);
+ if (keyRing == null) {
+ return null;
+ }
+ Vector<PGPSecretKey> signingKeys = getUsableSigningKeys(keyRing);
+ if (signingKeys.size() == 0) {
+ return null;
+ }
+ return signingKeys.get(0);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static String getMainUserId(PGPPublicKey key) {
+ for (String userId : new IterableIterator<String>(key.getUserIDs())) {
+ return userId;
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static String getMainUserId(PGPSecretKey key) {
+ for (String userId : new IterableIterator<String>(key.getUserIDs())) {
+ return userId;
+ }
+ return null;
+ }
+
+ public static String getMainUserIdSafe(Context context, PGPPublicKey key) {
+ String userId = getMainUserId(key);
+ if (userId == null || userId.equals("")) {
+ userId = context.getString(R.string.unknownUserId);
+ }
+ return userId;
+ }
+
+ public static String getMainUserIdSafe(Context context, PGPSecretKey key) {
+ String userId = getMainUserId(key);
+ if (userId == null || userId.equals("")) {
+ userId = context.getString(R.string.unknownUserId);
+ }
+ return userId;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static boolean isEncryptionKey(PGPPublicKey key) {
+ if (!key.isEncryptionKey()) {
+ return false;
+ }
+
+ if (key.getVersion() <= 3) {
+ // this must be true now
+ return key.isEncryptionKey();
+ }
+
+ // special cases
+ if (key.getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT) {
+ return true;
+ }
+
+ if (key.getAlgorithm() == PGPPublicKey.RSA_ENCRYPT) {
+ return true;
+ }
+
+ for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) {
+ if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) {
+ continue;
+ }
+ PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
+
+ if (hashed != null
+ && (hashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
+ return true;
+ }
+
+ PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
+
+ if (unhashed != null
+ && (unhashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean isEncryptionKey(PGPSecretKey key) {
+ return isEncryptionKey(key.getPublicKey());
+ }
+
+ @SuppressWarnings("unchecked")
+ public static boolean isSigningKey(PGPPublicKey key) {
+ if (key.getVersion() <= 3) {
+ return true;
+ }
+
+ // special case
+ if (key.getAlgorithm() == PGPPublicKey.RSA_SIGN) {
+ return true;
+ }
+
+ for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) {
+ if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) {
+ continue;
+ }
+ PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
+
+ if (hashed != null && (hashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) {
+ return true;
+ }
+
+ PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
+
+ if (unhashed != null && (unhashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean isSigningKey(PGPSecretKey key) {
+ return isSigningKey(key.getPublicKey());
+ }
+
+ @SuppressWarnings("unchecked")
+ public static boolean isCertificationKey(PGPPublicKey key) {
+ if (key.getVersion() <= 3) {
+ return true;
+ }
+
+ for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) {
+ if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) {
+ continue;
+ }
+ PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
+
+ if (hashed != null && (hashed.getKeyFlags() & KeyFlags.CERTIFY_OTHER) != 0) {
+ return true;
+ }
+
+ PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
+
+ if (unhashed != null && (unhashed.getKeyFlags() & KeyFlags.CERTIFY_OTHER) != 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean isCertificationKey(PGPSecretKey key) {
+ return isCertificationKey(key.getPublicKey());
+ }
+
+ public static String getAlgorithmInfo(PGPPublicKey key) {
+ return getAlgorithmInfo(key.getAlgorithm(), key.getBitStrength());
+ }
+
+ public static String getAlgorithmInfo(PGPSecretKey key) {
+ return getAlgorithmInfo(key.getPublicKey());
+ }
+
+ public static String getAlgorithmInfo(int algorithm, int keySize) {
+ String algorithmStr = null;
+
+ switch (algorithm) {
+ case PGPPublicKey.RSA_ENCRYPT:
+ case PGPPublicKey.RSA_GENERAL:
+ case PGPPublicKey.RSA_SIGN: {
+ algorithmStr = "RSA";
+ break;
+ }
+
+ case PGPPublicKey.DSA: {
+ algorithmStr = "DSA";
+ break;
+ }
+
+ case PGPPublicKey.ELGAMAL_ENCRYPT:
+ case PGPPublicKey.ELGAMAL_GENERAL: {
+ algorithmStr = "ElGamal";
+ break;
+ }
+
+ default: {
+ algorithmStr = "???";
+ break;
+ }
+ }
+ return algorithmStr + ", " + keySize + "bit";
+ }
+
+ public static String convertFingerprintToHex(byte[] fp) {
+ String fingerPrint = "";
+ for (int i = 0; i < fp.length; ++i) {
+ if (i != 0 && i % 10 == 0) {
+ fingerPrint += " ";
+ } else if (i != 0 && i % 2 == 0) {
+ fingerPrint += " ";
+ }
+ String chunk = Integer.toHexString((fp[i] + 256) % 256).toUpperCase(Locale.US);
+ while (chunk.length() < 2) {
+ chunk = "0" + chunk;
+ }
+ fingerPrint += chunk;
+ }
+
+ return fingerPrint;
+
+ }
+
+ public static String getFingerPrint(Context context, long keyId) {
+ PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, keyId);
+ // if it is no public key get it from your own keys...
+ if (key == null) {
+ PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId);
+ if (secretKey == null) {
+ Log.e(Constants.TAG, "Key could not be found!");
+ return null;
+ }
+ key = secretKey.getPublicKey();
+ }
+
+ return convertFingerprintToHex(key.getFingerprint());
+ }
+
+ public static boolean isSecretKeyPrivateEmpty(PGPSecretKey secretKey) {
+ return secretKey.isPrivateKeyEmpty();
+ }
+
+ public static boolean isSecretKeyPrivateEmpty(Context context, long keyId) {
+ PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId);
+ if (secretKey == null) {
+ Log.e(Constants.TAG, "Key could not be found!");
+ return false; // could be a public key, assume it is not empty
+ }
+ return isSecretKeyPrivateEmpty(secretKey);
+ }
+
+ public static String getSmallFingerPrint(long keyId) {
+ String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US);
+ while (fingerPrint.length() < 8) {
+ fingerPrint = "0" + fingerPrint;
+ }
+ return fingerPrint;
+ }
+
+ public static String keyToHex(long keyId) {
+ return getSmallFingerPrint(keyId >> 32) + getSmallFingerPrint(keyId);
+ }
+
+ public static long keyFromHex(String data) {
+ int len = data.length();
+ String s2 = data.substring(len - 8);
+ String s1 = data.substring(0, len - 8);
+ return (Long.parseLong(s1, 16) << 32) | Long.parseLong(s2, 16);
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
new file mode 100644
index 000000000..1ef5060ca
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.sufficientlysecure.keychain.pgp;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.SignatureException;
+import java.util.ArrayList;
+import java.util.Date;
+
+import org.spongycastle.bcpg.CompressionAlgorithmTags;
+import org.spongycastle.bcpg.HashAlgorithmTags;
+import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
+import org.spongycastle.bcpg.sig.KeyFlags;
+import org.spongycastle.jce.provider.BouncyCastleProvider;
+import org.spongycastle.jce.spec.ElGamalParameterSpec;
+import org.spongycastle.openpgp.PGPEncryptedData;
+import org.spongycastle.openpgp.PGPException;
+import org.spongycastle.openpgp.PGPKeyPair;
+import org.spongycastle.openpgp.PGPKeyRingGenerator;
+import org.spongycastle.openpgp.PGPPrivateKey;
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.spongycastle.openpgp.PGPSecretKey;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.spongycastle.openpgp.PGPSignature;
+import org.spongycastle.openpgp.PGPSignatureGenerator;
+import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
+import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
+import org.spongycastle.openpgp.PGPUtil;
+import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
+import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
+import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
+import org.spongycastle.openpgp.operator.PGPDigestCalculator;
+import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
+import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
+import org.spongycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
+import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
+import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Primes;
+import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
+
+import android.content.Context;
+
+public class PgpKeyOperation {
+ private Context mContext;
+ private ProgressDialogUpdater mProgress;
+
+ private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[] {
+ SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192,
+ SymmetricKeyAlgorithmTags.AES_128, SymmetricKeyAlgorithmTags.CAST5,
+ SymmetricKeyAlgorithmTags.TRIPLE_DES };
+ private static final int[] PREFERRED_HASH_ALGORITHMS = new int[] { HashAlgorithmTags.SHA1,
+ HashAlgorithmTags.SHA256, HashAlgorithmTags.RIPEMD160 };
+ private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[] {
+ CompressionAlgorithmTags.ZLIB, CompressionAlgorithmTags.BZIP2,
+ CompressionAlgorithmTags.ZIP };
+
+ public PgpKeyOperation(Context context, ProgressDialogUpdater progress) {
+ super();
+ this.mContext = context;
+ this.mProgress = progress;
+ }
+
+ public void updateProgress(int message, int current, int total) {
+ if (mProgress != null) {
+ mProgress.setProgress(message, current, total);
+ }
+ }
+
+ public void updateProgress(int current, int total) {
+ if (mProgress != null) {
+ mProgress.setProgress(current, total);
+ }
+ }
+
+ /**
+ * Creates new secret key. The returned PGPSecretKeyRing contains only one newly generated key
+ * when this key is the new masterkey. If a masterkey is supplied in the parameters
+ * PGPSecretKeyRing contains the masterkey and the new key as a subkey (certified by the
+ * masterkey).
+ *
+ * @param context
+ * @param algorithmChoice
+ * @param keySize
+ * @param passPhrase
+ * @param masterSecretKey
+ * @return
+ * @throws NoSuchAlgorithmException
+ * @throws PGPException
+ * @throws NoSuchProviderException
+ * @throws PgpGeneralException
+ * @throws InvalidAlgorithmParameterException
+ */
+ public PGPSecretKeyRing createKey(int algorithmChoice, int keySize, String passPhrase,
+ PGPSecretKey masterSecretKey) throws NoSuchAlgorithmException, PGPException,
+ NoSuchProviderException, PgpGeneralException, InvalidAlgorithmParameterException {
+
+ if (keySize < 512) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_keySizeMinimum512bit));
+ }
+
+ if (passPhrase == null) {
+ passPhrase = "";
+ }
+
+ int algorithm = 0;
+ KeyPairGenerator keyGen = null;
+
+ switch (algorithmChoice) {
+ case Id.choice.algorithm.dsa: {
+ keyGen = KeyPairGenerator.getInstance("DSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+ keyGen.initialize(keySize, new SecureRandom());
+ algorithm = PGPPublicKey.DSA;
+ break;
+ }
+
+ case Id.choice.algorithm.elgamal: {
+ if (masterSecretKey == null) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_masterKeyMustNotBeElGamal));
+ }
+ keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+ BigInteger p = Primes.getBestPrime(keySize);
+ BigInteger g = new BigInteger("2");
+
+ ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g);
+
+ keyGen.initialize(elParams);
+ algorithm = PGPPublicKey.ELGAMAL_ENCRYPT;
+ break;
+ }
+
+ case Id.choice.algorithm.rsa: {
+ keyGen = KeyPairGenerator.getInstance("RSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+ keyGen.initialize(keySize, new SecureRandom());
+
+ algorithm = PGPPublicKey.RSA_GENERAL;
+ break;
+ }
+
+ default: {
+ throw new PgpGeneralException(mContext.getString(R.string.error_unknownAlgorithmChoice));
+ }
+ }
+
+ // build new key pair
+ PGPKeyPair keyPair = new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date());
+
+ // define hashing and signing algos
+ PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
+ HashAlgorithmTags.SHA1);
+
+ // Build key encrypter and decrypter based on passphrase
+ PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
+ PGPEncryptedData.CAST5, sha1Calc)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passPhrase.toCharArray());
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passPhrase.toCharArray());
+
+ PGPKeyRingGenerator ringGen = null;
+ PGPContentSignerBuilder certificationSignerBuilder = null;
+ if (masterSecretKey == null) {
+ certificationSignerBuilder = new JcaPGPContentSignerBuilder(keyPair.getPublicKey()
+ .getAlgorithm(), HashAlgorithmTags.SHA1);
+
+ // build keyRing with only this one master key in it!
+ ringGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, keyPair, "",
+ sha1Calc, null, null, certificationSignerBuilder, keyEncryptor);
+ } else {
+ PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
+ PGPPrivateKey masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
+ PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
+
+ certificationSignerBuilder = new JcaPGPContentSignerBuilder(masterKeyPair
+ .getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);
+
+ // build keyRing with master key and new key as subkey (certified by masterkey)
+ ringGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, masterKeyPair,
+ "", sha1Calc, null, null, certificationSignerBuilder, keyEncryptor);
+
+ ringGen.addSubKey(keyPair);
+ }
+
+ PGPSecretKeyRing secKeyRing = ringGen.generateSecretKeyRing();
+
+ return secKeyRing;
+ }
+
+ public void changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassPhrase,
+ String newPassPhrase) throws IOException, PGPException, PGPException,
+ NoSuchProviderException {
+
+ updateProgress(R.string.progress_buildingKey, 0, 100);
+ if (oldPassPhrase == null) {
+ oldPassPhrase = "";
+ }
+ if (newPassPhrase == null) {
+ newPassPhrase = "";
+ }
+
+ PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword(
+ keyRing,
+ new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build()).setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray()),
+ new JcePBESecretKeyEncryptorBuilder(keyRing.getSecretKey()
+ .getKeyEncryptionAlgorithm()).build(newPassPhrase.toCharArray()));
+
+ updateProgress(R.string.progress_savingKeyRing, 50, 100);
+
+ ProviderHelper.saveKeyRing(mContext, newKeyRing);
+
+ updateProgress(R.string.progress_done, 100, 100);
+
+ }
+
+ public void buildSecretKey(ArrayList<String> userIds, ArrayList<PGPSecretKey> keys,
+ ArrayList<Integer> keysUsages, long masterKeyId, String oldPassPhrase,
+ String newPassPhrase) throws PgpGeneralException, NoSuchProviderException,
+ PGPException, NoSuchAlgorithmException, SignatureException, IOException {
+
+ Log.d(Constants.TAG, "userIds: " + userIds.toString());
+
+ updateProgress(R.string.progress_buildingKey, 0, 100);
+
+ if (oldPassPhrase == null) {
+ oldPassPhrase = "";
+ }
+ if (newPassPhrase == null) {
+ newPassPhrase = "";
+ }
+
+ updateProgress(R.string.progress_preparingMasterKey, 10, 100);
+
+ int usageId = keysUsages.get(0);
+ boolean canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
+ boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
+
+ String mainUserId = userIds.get(0);
+
+ PGPSecretKey masterKey = keys.get(0);
+
+ // this removes all userIds and certifications previously attached to the masterPublicKey
+ PGPPublicKey tmpKey = masterKey.getPublicKey();
+ PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
+ tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
+
+ // already done by code above:
+ // PGPPublicKey masterPublicKey = masterKey.getPublicKey();
+ // // Somehow, the PGPPublicKey already has an empty certification attached to it when the
+ // // keyRing is generated the first time, we remove that when it exists, before adding the
+ // new
+ // // ones
+ // PGPPublicKey masterPublicKeyRmCert = PGPPublicKey.removeCertification(masterPublicKey,
+ // "");
+ // if (masterPublicKeyRmCert != null) {
+ // masterPublicKey = masterPublicKeyRmCert;
+ // }
+
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray());
+ PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor);
+
+ updateProgress(R.string.progress_certifyingMasterKey, 20, 100);
+
+ for (String userId : userIds) {
+ PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
+ masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA1)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+ PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
+
+ sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey);
+
+ PGPSignature certification = sGen.generateCertification(userId, masterPublicKey);
+
+ masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, certification);
+ }
+
+ // TODO: cross-certify the master key with every sub key (APG 1)
+
+ PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
+
+ PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
+ PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
+
+ int keyFlags = KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA;
+ if (canEncrypt) {
+ keyFlags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE;
+ }
+ hashedPacketsGen.setKeyFlags(true, keyFlags);
+
+ hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS);
+ hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS);
+ hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS);
+
+ // TODO: this doesn't work quite right yet (APG 1)
+ // if (keyEditor.getExpiryDate() != null) {
+ // GregorianCalendar creationDate = new GregorianCalendar();
+ // creationDate.setTime(getCreationDate(masterKey));
+ // GregorianCalendar expiryDate = keyEditor.getExpiryDate();
+ // long numDays = Utils.getNumDaysBetween(creationDate, expiryDate);
+ // if (numDays <= 0) {
+ // throw new GeneralException(
+ // context.getString(R.string.error_expiryMustComeAfterCreation));
+ // }
+ // hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
+ // }
+
+ updateProgress(R.string.progress_buildingMasterKeyRing, 30, 100);
+
+ // define hashing and signing algos
+ PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
+ HashAlgorithmTags.SHA1);
+ PGPContentSignerBuilder certificationSignerBuilder = new JcaPGPContentSignerBuilder(
+ masterKeyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);
+
+ // Build key encrypter based on passphrase
+ PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
+ PGPEncryptedData.CAST5, sha1Calc)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ newPassPhrase.toCharArray());
+
+ PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
+ masterKeyPair, mainUserId, sha1Calc, hashedPacketsGen.generate(),
+ unhashedPacketsGen.generate(), certificationSignerBuilder, keyEncryptor);
+
+ updateProgress(R.string.progress_addingSubKeys, 40, 100);
+
+ for (int i = 1; i < keys.size(); ++i) {
+ updateProgress(40 + 50 * (i - 1) / (keys.size() - 1), 100);
+
+ PGPSecretKey subKey = keys.get(i);
+ PGPPublicKey subPublicKey = subKey.getPublicKey();
+
+ PBESecretKeyDecryptor keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ oldPassPhrase.toCharArray());
+ PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor2);
+
+ // TODO: now used without algorithm and creation time?! (APG 1)
+ PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey, subPrivateKey);
+
+ hashedPacketsGen = new PGPSignatureSubpacketGenerator();
+ unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
+
+ keyFlags = 0;
+
+ usageId = keysUsages.get(i);
+ canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
+ canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
+ if (canSign) {
+ keyFlags |= KeyFlags.SIGN_DATA;
+ }
+ if (canEncrypt) {
+ keyFlags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE;
+ }
+ hashedPacketsGen.setKeyFlags(true, keyFlags);
+
+ // TODO: this doesn't work quite right yet (APG 1)
+ // if (keyEditor.getExpiryDate() != null) {
+ // GregorianCalendar creationDate = new GregorianCalendar();
+ // creationDate.setTime(getCreationDate(masterKey));
+ // GregorianCalendar expiryDate = keyEditor.getExpiryDate();
+ // long numDays = Utils.getNumDaysBetween(creationDate, expiryDate);
+ // if (numDays <= 0) {
+ // throw new GeneralException(
+ // context.getString(R.string.error_expiryMustComeAfterCreation));
+ // }
+ // hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
+ // }
+
+ keyGen.addSubKey(subKeyPair, hashedPacketsGen.generate(), unhashedPacketsGen.generate());
+ }
+
+ PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
+ PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing();
+
+ updateProgress(R.string.progress_savingKeyRing, 90, 100);
+
+ ProviderHelper.saveKeyRing(mContext, secretKeyRing);
+ ProviderHelper.saveKeyRing(mContext, publicKeyRing);
+
+ updateProgress(R.string.progress_done, 100, 100);
+ }
+
+ public PGPPublicKeyRing signKey(long masterKeyId, long pubKeyId, String passphrase)
+ throws PgpGeneralException, NoSuchAlgorithmException, NoSuchProviderException,
+ PGPException, SignatureException {
+ if (passphrase == null || passphrase.length() <= 0) {
+ throw new PgpGeneralException("Unable to obtain passphrase");
+ } else {
+ PGPPublicKeyRing pubring = ProviderHelper
+ .getPGPPublicKeyRingByKeyId(mContext, pubKeyId);
+
+ PGPSecretKey signingKey = PgpKeyHelper.getCertificationKey(mContext, masterKeyId);
+ if (signingKey == null) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_signatureFailed));
+ }
+
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
+ PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
+ if (signaturePrivateKey == null) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_couldNotExtractPrivateKey));
+ }
+
+ // TODO: SHA256 fixed?
+ JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
+ signingKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+
+ PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
+ contentSignerBuilder);
+
+ signatureGenerator.init(PGPSignature.DIRECT_KEY, signaturePrivateKey);
+
+ PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
+
+ PGPSignatureSubpacketVector packetVector = spGen.generate();
+ signatureGenerator.setHashedSubpackets(packetVector);
+
+ PGPPublicKey signedKey = PGPPublicKey.addCertification(pubring.getPublicKey(pubKeyId),
+ signatureGenerator.generate());
+ pubring = PGPPublicKeyRing.insertPublicKey(pubring, signedKey);
+
+ return pubring;
+ }
+ }
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpMain.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpMain.java
deleted file mode 100644
index f6c9ebda8..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpMain.java
+++ /dev/null
@@ -1,1884 +0,0 @@
-/*
- * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.pgp;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.SignatureException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.regex.Pattern;
-
-import org.spongycastle.bcpg.ArmoredInputStream;
-import org.spongycastle.bcpg.ArmoredOutputStream;
-import org.spongycastle.bcpg.BCPGOutputStream;
-import org.spongycastle.bcpg.CompressionAlgorithmTags;
-import org.spongycastle.bcpg.HashAlgorithmTags;
-import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
-import org.spongycastle.bcpg.sig.KeyFlags;
-import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.spongycastle.jce.spec.ElGamalParameterSpec;
-import org.spongycastle.openpgp.PGPCompressedData;
-import org.spongycastle.openpgp.PGPCompressedDataGenerator;
-import org.spongycastle.openpgp.PGPEncryptedData;
-import org.spongycastle.openpgp.PGPEncryptedDataGenerator;
-import org.spongycastle.openpgp.PGPEncryptedDataList;
-import org.spongycastle.openpgp.PGPException;
-import org.spongycastle.openpgp.PGPKeyPair;
-import org.spongycastle.openpgp.PGPKeyRing;
-import org.spongycastle.openpgp.PGPKeyRingGenerator;
-import org.spongycastle.openpgp.PGPLiteralData;
-import org.spongycastle.openpgp.PGPLiteralDataGenerator;
-import org.spongycastle.openpgp.PGPObjectFactory;
-import org.spongycastle.openpgp.PGPOnePassSignature;
-import org.spongycastle.openpgp.PGPOnePassSignatureList;
-import org.spongycastle.openpgp.PGPPBEEncryptedData;
-import org.spongycastle.openpgp.PGPPrivateKey;
-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.PGPSignatureGenerator;
-import org.spongycastle.openpgp.PGPSignatureList;
-import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
-import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
-import org.spongycastle.openpgp.PGPUtil;
-import org.spongycastle.openpgp.PGPV3SignatureGenerator;
-import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
-import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
-import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
-import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
-import org.spongycastle.openpgp.operator.PGPDigestCalculator;
-import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
-import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
-import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
-import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
-import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator;
-import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.util.HkpKeyServer;
-import org.sufficientlysecure.keychain.util.InputData;
-import org.sufficientlysecure.keychain.util.IterableIterator;
-import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
-import org.sufficientlysecure.keychain.util.Primes;
-import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Bundle;
-import android.os.Environment;
-
-/**
- * TODO:
- *
- * - Separate this file into different helpers
- *
- */
-public class PgpMain {
-
- static {
- // Define Java Security Provider to be Bouncy Castle
- Security.insertProviderAt(new BouncyCastleProvider(), 1);
- }
-
- // Not BC due to the use of Spongy Castle for Android
- public static final String SC = BouncyCastleProvider.PROVIDER_NAME;
- public static final String BOUNCY_CASTLE_PROVIDER_NAME = SC;
-
- private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[] {
- SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192,
- SymmetricKeyAlgorithmTags.AES_128, SymmetricKeyAlgorithmTags.CAST5,
- SymmetricKeyAlgorithmTags.TRIPLE_DES };
- private static final int[] PREFERRED_HASH_ALGORITHMS = new int[] { HashAlgorithmTags.SHA1,
- HashAlgorithmTags.SHA256, HashAlgorithmTags.RIPEMD160 };
- private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[] {
- CompressionAlgorithmTags.ZLIB, CompressionAlgorithmTags.BZIP2,
- CompressionAlgorithmTags.ZIP };
-
- public static Pattern PGP_MESSAGE = Pattern.compile(
- ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL);
-
- public static Pattern PGP_SIGNED_MESSAGE = Pattern
- .compile(
- ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
- Pattern.DOTALL);
-
- public static Pattern PGP_PUBLIC_KEY = Pattern.compile(
- ".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*",
- Pattern.DOTALL);
-
- private static String mEditPassPhrase = null;
-
- public static class PgpGeneralException extends Exception {
- static final long serialVersionUID = 0xf812773342L;
-
- public PgpGeneralException(String message) {
- super(message);
- }
- }
-
- public static class NoAsymmetricEncryptionException extends Exception {
- static final long serialVersionUID = 0xf812773343L;
-
- public NoAsymmetricEncryptionException() {
- super();
- }
- }
-
- public static void setEditPassPhrase(String passPhrase) {
- mEditPassPhrase = passPhrase;
- }
-
- public static String getEditPassPhrase() {
- return mEditPassPhrase;
- }
-
- public static void updateProgress(ProgressDialogUpdater progress, int message, int current,
- int total) {
- if (progress != null) {
- progress.setProgress(message, current, total);
- }
- }
-
- public static void updateProgress(ProgressDialogUpdater progress, int current, int total) {
- if (progress != null) {
- progress.setProgress(current, total);
- }
- }
-
- /**
- * Creates new secret key. The returned PGPSecretKeyRing contains only one newly generated key
- * when this key is the new masterkey. If a masterkey is supplied in the parameters
- * PGPSecretKeyRing contains the masterkey and the new key as a subkey (certified by the
- * masterkey).
- *
- * @param context
- * @param algorithmChoice
- * @param keySize
- * @param passPhrase
- * @param masterSecretKey
- * @return
- * @throws NoSuchAlgorithmException
- * @throws PGPException
- * @throws NoSuchProviderException
- * @throws PgpGeneralException
- * @throws InvalidAlgorithmParameterException
- */
- public static PGPSecretKeyRing createKey(Context context, int algorithmChoice, int keySize,
- String passPhrase, PGPSecretKey masterSecretKey) throws NoSuchAlgorithmException,
- PGPException, NoSuchProviderException, PgpGeneralException,
- InvalidAlgorithmParameterException {
-
- if (keySize < 512) {
- throw new PgpGeneralException(context.getString(R.string.error_keySizeMinimum512bit));
- }
-
- if (passPhrase == null) {
- passPhrase = "";
- }
-
- int algorithm = 0;
- KeyPairGenerator keyGen = null;
-
- switch (algorithmChoice) {
- case Id.choice.algorithm.dsa: {
- keyGen = KeyPairGenerator.getInstance("DSA", BOUNCY_CASTLE_PROVIDER_NAME);
- keyGen.initialize(keySize, new SecureRandom());
- algorithm = PGPPublicKey.DSA;
- break;
- }
-
- case Id.choice.algorithm.elgamal: {
- if (masterSecretKey == null) {
- throw new PgpGeneralException(
- context.getString(R.string.error_masterKeyMustNotBeElGamal));
- }
- keyGen = KeyPairGenerator.getInstance("ElGamal", BOUNCY_CASTLE_PROVIDER_NAME);
- BigInteger p = Primes.getBestPrime(keySize);
- BigInteger g = new BigInteger("2");
-
- ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g);
-
- keyGen.initialize(elParams);
- algorithm = PGPPublicKey.ELGAMAL_ENCRYPT;
- break;
- }
-
- case Id.choice.algorithm.rsa: {
- keyGen = KeyPairGenerator.getInstance("RSA", BOUNCY_CASTLE_PROVIDER_NAME);
- keyGen.initialize(keySize, new SecureRandom());
-
- algorithm = PGPPublicKey.RSA_GENERAL;
- break;
- }
-
- default: {
- throw new PgpGeneralException(context.getString(R.string.error_unknownAlgorithmChoice));
- }
- }
-
- // build new key pair
- PGPKeyPair keyPair = new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date());
-
- // define hashing and signing algos
- PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
- HashAlgorithmTags.SHA1);
-
- // Build key encrypter and decrypter based on passphrase
- PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
- PGPEncryptedData.CAST5, sha1Calc).setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(
- passPhrase.toCharArray());
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- BOUNCY_CASTLE_PROVIDER_NAME).build(passPhrase.toCharArray());
-
- PGPKeyRingGenerator ringGen = null;
- PGPContentSignerBuilder certificationSignerBuilder = null;
- if (masterSecretKey == null) {
- certificationSignerBuilder = new JcaPGPContentSignerBuilder(keyPair.getPublicKey()
- .getAlgorithm(), HashAlgorithmTags.SHA1);
-
- // build keyRing with only this one master key in it!
- ringGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, keyPair, "",
- sha1Calc, null, null, certificationSignerBuilder, keyEncryptor);
- } else {
- PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
- PGPPrivateKey masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
- PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
-
- certificationSignerBuilder = new JcaPGPContentSignerBuilder(masterKeyPair
- .getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);
-
- // build keyRing with master key and new key as subkey (certified by masterkey)
- ringGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, masterKeyPair,
- "", sha1Calc, null, null, certificationSignerBuilder, keyEncryptor);
-
- ringGen.addSubKey(keyPair);
- }
-
- PGPSecretKeyRing secKeyRing = ringGen.generateSecretKeyRing();
-
- return secKeyRing;
- }
-
- public static void changeSecretKeyPassphrase(Context context, PGPSecretKeyRing keyRing,
- String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress)
- throws IOException, PGPException, PGPException, NoSuchProviderException {
-
- updateProgress(progress, R.string.progress_buildingKey, 0, 100);
- if (oldPassPhrase == null) {
- oldPassPhrase = "";
- }
- if (newPassPhrase == null) {
- newPassPhrase = "";
- }
-
- PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword(
- keyRing,
- new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder()
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build()).setProvider(
- BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray()),
- new JcePBESecretKeyEncryptorBuilder(keyRing.getSecretKey()
- .getKeyEncryptionAlgorithm()).build(newPassPhrase.toCharArray()));
-
- updateProgress(progress, R.string.progress_savingKeyRing, 50, 100);
-
- ProviderHelper.saveKeyRing(context, newKeyRing);
-
- updateProgress(progress, R.string.progress_done, 100, 100);
-
- }
-
- public static void buildSecretKey(Context context, ArrayList<String> userIds,
- ArrayList<PGPSecretKey> keys, ArrayList<Integer> keysUsages, long masterKeyId,
- String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress)
- throws PgpGeneralException, NoSuchProviderException, PGPException,
- NoSuchAlgorithmException, SignatureException, IOException {
-
- Log.d(Constants.TAG, "userIds: " + userIds.toString());
-
- updateProgress(progress, R.string.progress_buildingKey, 0, 100);
-
- if (oldPassPhrase == null) {
- oldPassPhrase = "";
- }
- if (newPassPhrase == null) {
- newPassPhrase = "";
- }
-
- updateProgress(progress, R.string.progress_preparingMasterKey, 10, 100);
-
- int usageId = keysUsages.get(0);
- boolean canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
- boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
-
- String mainUserId = userIds.get(0);
-
- PGPSecretKey masterKey = keys.get(0);
-
- // this removes all userIds and certifications previously attached to the masterPublicKey
- PGPPublicKey tmpKey = masterKey.getPublicKey();
- PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
- tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
-
- // already done by code above:
- // PGPPublicKey masterPublicKey = masterKey.getPublicKey();
- // // Somehow, the PGPPublicKey already has an empty certification attached to it when the
- // // keyRing is generated the first time, we remove that when it exists, before adding the
- // new
- // // ones
- // PGPPublicKey masterPublicKeyRmCert = PGPPublicKey.removeCertification(masterPublicKey,
- // "");
- // if (masterPublicKeyRmCert != null) {
- // masterPublicKey = masterPublicKeyRmCert;
- // }
-
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray());
- PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor);
-
- updateProgress(progress, R.string.progress_certifyingMasterKey, 20, 100);
-
- for (String userId : userIds) {
- PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
- masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA1)
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME);
- PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
-
- sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey);
-
- PGPSignature certification = sGen.generateCertification(userId, masterPublicKey);
-
- masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, certification);
- }
-
- // TODO: cross-certify the master key with every sub key (APG 1)
-
- PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
-
- PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
- PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
-
- int keyFlags = KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA;
- if (canEncrypt) {
- keyFlags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE;
- }
- hashedPacketsGen.setKeyFlags(true, keyFlags);
-
- hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS);
- hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS);
- hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS);
-
- // TODO: this doesn't work quite right yet (APG 1)
- // if (keyEditor.getExpiryDate() != null) {
- // GregorianCalendar creationDate = new GregorianCalendar();
- // creationDate.setTime(getCreationDate(masterKey));
- // GregorianCalendar expiryDate = keyEditor.getExpiryDate();
- // long numDays = Utils.getNumDaysBetween(creationDate, expiryDate);
- // if (numDays <= 0) {
- // throw new GeneralException(
- // context.getString(R.string.error_expiryMustComeAfterCreation));
- // }
- // hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
- // }
-
- updateProgress(progress, R.string.progress_buildingMasterKeyRing, 30, 100);
-
- // define hashing and signing algos
- PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
- HashAlgorithmTags.SHA1);
- PGPContentSignerBuilder certificationSignerBuilder = new JcaPGPContentSignerBuilder(
- masterKeyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);
-
- // Build key encrypter based on passphrase
- PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
- PGPEncryptedData.CAST5, sha1Calc).setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(
- newPassPhrase.toCharArray());
-
- PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
- masterKeyPair, mainUserId, sha1Calc, hashedPacketsGen.generate(),
- unhashedPacketsGen.generate(), certificationSignerBuilder, keyEncryptor);
-
- updateProgress(progress, R.string.progress_addingSubKeys, 40, 100);
-
- for (int i = 1; i < keys.size(); ++i) {
- updateProgress(progress, 40 + 50 * (i - 1) / (keys.size() - 1), 100);
-
- PGPSecretKey subKey = keys.get(i);
- PGPPublicKey subPublicKey = subKey.getPublicKey();
-
- PBESecretKeyDecryptor keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder()
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray());
- PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor2);
-
- // TODO: now used without algorithm and creation time?! (APG 1)
- PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey, subPrivateKey);
-
- hashedPacketsGen = new PGPSignatureSubpacketGenerator();
- unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
-
- keyFlags = 0;
-
- usageId = keysUsages.get(i);
- canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
- canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
- if (canSign) {
- keyFlags |= KeyFlags.SIGN_DATA;
- }
- if (canEncrypt) {
- keyFlags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE;
- }
- hashedPacketsGen.setKeyFlags(true, keyFlags);
-
- // TODO: this doesn't work quite right yet (APG 1)
- // if (keyEditor.getExpiryDate() != null) {
- // GregorianCalendar creationDate = new GregorianCalendar();
- // creationDate.setTime(getCreationDate(masterKey));
- // GregorianCalendar expiryDate = keyEditor.getExpiryDate();
- // long numDays = Utils.getNumDaysBetween(creationDate, expiryDate);
- // if (numDays <= 0) {
- // throw new GeneralException(
- // context.getString(R.string.error_expiryMustComeAfterCreation));
- // }
- // hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400);
- // }
-
- keyGen.addSubKey(subKeyPair, hashedPacketsGen.generate(), unhashedPacketsGen.generate());
- }
-
- PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
- PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing();
-
- updateProgress(progress, R.string.progress_savingKeyRing, 90, 100);
-
- ProviderHelper.saveKeyRing(context, secretKeyRing);
- ProviderHelper.saveKeyRing(context, publicKeyRing);
-
- updateProgress(progress, R.string.progress_done, 100, 100);
- }
-
- /**
- * TODO: implement Id.return_value.updated as status when key already existed
- *
- * @param context
- * @param keyring
- * @return
- */
- @SuppressWarnings("unchecked")
- public static int storeKeyRingInCache(Context context, PGPKeyRing keyring) {
- int status = Integer.MIN_VALUE; // out of bounds value (Id.return_value.*)
- try {
- if (keyring instanceof PGPSecretKeyRing) {
- PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
- boolean save = true;
-
- for (PGPSecretKey testSecretKey : new IterableIterator<PGPSecretKey>(
- secretKeyRing.getSecretKeys())) {
- if (!testSecretKey.isMasterKey()) {
- if (PgpHelper.isSecretKeyPrivateEmpty(testSecretKey)) {
- // this is bad, something is very wrong...
- save = false;
- status = Id.return_value.bad;
- }
- }
- }
-
- if (save) {
- ProviderHelper.saveKeyRing(context, secretKeyRing);
- // TODO: remove status returns, use exceptions!
- status = Id.return_value.ok;
- }
- } else if (keyring instanceof PGPPublicKeyRing) {
- PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring;
- ProviderHelper.saveKeyRing(context, publicKeyRing);
- // TODO: remove status returns, use exceptions!
- status = Id.return_value.ok;
- }
- } catch (IOException e) {
- status = Id.return_value.error;
- }
-
- return status;
- }
-
- public static boolean uploadKeyRingToServer(HkpKeyServer server, PGPPublicKeyRing keyring) {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ArmoredOutputStream aos = new ArmoredOutputStream(bos);
- try {
- aos.write(keyring.getEncoded());
- aos.close();
-
- String armouredKey = bos.toString("UTF-8");
- server.add(armouredKey);
-
- return true;
- } catch (IOException e) {
- return false;
- } catch (AddKeyException e) {
- // TODO: tell the user?
- return false;
- } finally {
- try {
- bos.close();
- } catch (IOException e) {
- }
- }
- }
-
- public static Bundle importKeyRings(Context context, InputData data,
- ProgressDialogUpdater progress) throws PgpGeneralException, FileNotFoundException,
- PGPException, IOException {
- Bundle returnData = new Bundle();
-
- updateProgress(progress, R.string.progress_importingSecretKeys, 0, 100);
-
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- throw new PgpGeneralException(context.getString(R.string.error_externalStorageNotReady));
- }
-
- PositionAwareInputStream progressIn = new PositionAwareInputStream(data.getInputStream());
-
- // need to have access to the bufferedInput, so we can reuse it for the possible
- // PGPObject chunks after the first one, e.g. files with several consecutive ASCII
- // armour blocks
- BufferedInputStream bufferedInput = new BufferedInputStream(progressIn);
- int newKeys = 0;
- int oldKeys = 0;
- int badKeys = 0;
- try {
-
- // read all available blocks... (asc files can contain many blocks with BEGIN END)
- while (bufferedInput.available() > 0) {
- InputStream in = PGPUtil.getDecoderStream(bufferedInput);
- PGPObjectFactory objectFactory = new PGPObjectFactory(in);
-
- // go through all objects in this block
- Object obj;
- while ((obj = objectFactory.nextObject()) != null) {
- Log.d(Constants.TAG, "Found class: " + obj.getClass());
-
- if (obj instanceof PGPKeyRing) {
- PGPKeyRing keyring = (PGPKeyRing) obj;
-
- int status = Integer.MIN_VALUE; // out of bounds value
-
- status = storeKeyRingInCache(context, keyring);
-
- if (status == Id.return_value.error) {
- throw new PgpGeneralException(
- context.getString(R.string.error_savingKeys));
- }
-
- // update the counts to display to the user at the end
- if (status == Id.return_value.updated) {
- ++oldKeys;
- } else if (status == Id.return_value.ok) {
- ++newKeys;
- } else if (status == Id.return_value.bad) {
- ++badKeys;
- }
-
- updateProgress(progress,
- (int) (100 * progressIn.position() / data.getSize()), 100);
- } else {
- Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!");
- }
- }
- }
- } catch (Exception e) {
- Log.e(Constants.TAG, "Exception on parsing key file!", e);
- }
-
- returnData.putInt(KeychainIntentService.RESULT_IMPORT_ADDED, newKeys);
- returnData.putInt(KeychainIntentService.RESULT_IMPORT_UPDATED, oldKeys);
- returnData.putInt(KeychainIntentService.RESULT_IMPORT_BAD, badKeys);
-
- updateProgress(progress, R.string.progress_done, 100, 100);
-
- return returnData;
- }
-
- public static Bundle exportKeyRings(Context context, ArrayList<Long> keyRingMasterKeyIds,
- int keyType, OutputStream outStream, ProgressDialogUpdater progress)
- throws PgpGeneralException, FileNotFoundException, PGPException, IOException {
- Bundle returnData = new Bundle();
-
- if (keyRingMasterKeyIds.size() == 1) {
- updateProgress(progress, R.string.progress_exportingKey, 0, 100);
- } else {
- updateProgress(progress, R.string.progress_exportingKeys, 0, 100);
- }
-
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- throw new PgpGeneralException(context.getString(R.string.error_externalStorageNotReady));
- }
-
- // export public keyrings...
- ArmoredOutputStream outPub = new ArmoredOutputStream(outStream);
- outPub.setHeader("Version", getFullVersion(context));
-
- int numKeys = 0;
- for (int i = 0; i < keyRingMasterKeyIds.size(); ++i) {
- // double the needed time if exporting both public and secret parts
- if (keyType == Id.type.secret_key) {
- updateProgress(progress, i * 100 / keyRingMasterKeyIds.size() / 2, 100);
- } else {
- updateProgress(progress, i * 100 / keyRingMasterKeyIds.size(), 100);
- }
-
- PGPPublicKeyRing publicKeyRing = ProviderHelper.getPGPPublicKeyRingByMasterKeyId(
- context, keyRingMasterKeyIds.get(i));
-
- if (publicKeyRing != null) {
- publicKeyRing.encode(outPub);
- }
- ++numKeys;
- }
- outPub.close();
-
- // if we export secret keyrings, append all secret parts after the public parts
- if (keyType == Id.type.secret_key) {
- ArmoredOutputStream outSec = new ArmoredOutputStream(outStream);
- outSec.setHeader("Version", getFullVersion(context));
-
- for (int i = 0; i < keyRingMasterKeyIds.size(); ++i) {
- updateProgress(progress, i * 100 / keyRingMasterKeyIds.size() / 2, 100);
-
- PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(
- context, keyRingMasterKeyIds.get(i));
-
- if (secretKeyRing != null) {
- secretKeyRing.encode(outSec);
- }
- }
- outSec.close();
- }
-
- returnData.putInt(KeychainIntentService.RESULT_EXPORT, numKeys);
-
- updateProgress(progress, R.string.progress_done, 100, 100);
-
- return returnData;
- }
-
- /**
- * Encrypt and Sign data
- *
- * @param context
- * @param progress
- * @param data
- * @param outStream
- * @param useAsciiArmor
- * @param compression
- * @param encryptionKeyIds
- * @param symmetricEncryptionAlgorithm
- * @param encryptionPassphrase
- * @param signatureKeyId
- * @param signatureHashAlgorithm
- * @param signatureForceV3
- * @param signaturePassphrase
- * @throws IOException
- * @throws PgpGeneralException
- * @throws PGPException
- * @throws NoSuchProviderException
- * @throws NoSuchAlgorithmException
- * @throws SignatureException
- */
- public static void encryptAndSign(Context context, ProgressDialogUpdater progress,
- InputData data, OutputStream outStream, boolean useAsciiArmor, int compression,
- long[] encryptionKeyIds, String encryptionPassphrase,
- int symmetricEncryptionAlgorithm, long signatureKeyId, int signatureHashAlgorithm,
- boolean signatureForceV3, String signaturePassphrase) throws IOException,
- PgpGeneralException, PGPException, NoSuchProviderException, NoSuchAlgorithmException,
- SignatureException {
-
- if (encryptionKeyIds == null) {
- encryptionKeyIds = new long[0];
- }
-
- ArmoredOutputStream armorOut = null;
- OutputStream out = null;
- OutputStream encryptOut = null;
- if (useAsciiArmor) {
- armorOut = new ArmoredOutputStream(outStream);
- armorOut.setHeader("Version", getFullVersion(context));
- out = armorOut;
- } else {
- out = outStream;
- }
- PGPSecretKey signingKey = null;
- PGPSecretKeyRing signingKeyRing = null;
- PGPPrivateKey signaturePrivateKey = null;
-
- if (encryptionKeyIds.length == 0 && encryptionPassphrase == null) {
- throw new PgpGeneralException(
- context.getString(R.string.error_noEncryptionKeysOrPassPhrase));
- }
-
- if (signatureKeyId != Id.key.none) {
- signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, signatureKeyId);
- signingKey = PgpHelper.getSigningKey(context, signatureKeyId);
- if (signingKey == null) {
- throw new PgpGeneralException(context.getString(R.string.error_signatureFailed));
- }
-
- if (signaturePassphrase == null) {
- throw new PgpGeneralException(
- context.getString(R.string.error_noSignaturePassPhrase));
- }
-
- updateProgress(progress, R.string.progress_extractingSignatureKey, 0, 100);
-
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassphrase.toCharArray());
- signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
- if (signaturePrivateKey == null) {
- throw new PgpGeneralException(
- context.getString(R.string.error_couldNotExtractPrivateKey));
- }
- }
- updateProgress(progress, R.string.progress_preparingStreams, 5, 100);
-
- // encrypt and compress input file content
- JcePGPDataEncryptorBuilder encryptorBuilder = new JcePGPDataEncryptorBuilder(
- symmetricEncryptionAlgorithm).setProvider(BOUNCY_CASTLE_PROVIDER_NAME)
- .setWithIntegrityPacket(true);
-
- PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(encryptorBuilder);
-
- if (encryptionKeyIds.length == 0) {
- // Symmetric encryption
- Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption");
-
- JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator = new JcePBEKeyEncryptionMethodGenerator(
- encryptionPassphrase.toCharArray());
- cPk.addMethod(symmetricEncryptionGenerator);
- } else {
- // Asymmetric encryption
- for (long id : encryptionKeyIds) {
- PGPPublicKey key = PgpHelper.getEncryptPublicKey(context, id);
- if (key != null) {
-
- JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator = new JcePublicKeyKeyEncryptionMethodGenerator(
- key);
- cPk.addMethod(pubKeyEncryptionGenerator);
- }
- }
- }
- encryptOut = cPk.open(out, new byte[1 << 16]);
-
- PGPSignatureGenerator signatureGenerator = null;
- PGPV3SignatureGenerator signatureV3Generator = null;
-
- if (signatureKeyId != Id.key.none) {
- updateProgress(progress, R.string.progress_preparingSignature, 10, 100);
-
- // content signer based on signing key algorithm and choosen hash algorithm
- JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
- signingKey.getPublicKey().getAlgorithm(), signatureHashAlgorithm)
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME);
-
- if (signatureForceV3) {
- signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
- signatureV3Generator.init(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
- } else {
- signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
- signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
-
- String userId = PgpHelper.getMainUserId(PgpHelper.getMasterKey(signingKeyRing));
- PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
- spGen.setSignerUserID(false, userId);
- signatureGenerator.setHashedSubpackets(spGen.generate());
- }
- }
-
- PGPCompressedDataGenerator compressGen = null;
- BCPGOutputStream bcpgOut = null;
- if (compression == Id.choice.compression.none) {
- bcpgOut = new BCPGOutputStream(encryptOut);
- } else {
- compressGen = new PGPCompressedDataGenerator(compression);
- bcpgOut = new BCPGOutputStream(compressGen.open(encryptOut));
- }
- if (signatureKeyId != Id.key.none) {
- if (signatureForceV3) {
- signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut);
- } else {
- signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
- }
- }
-
- PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
- // file name not needed, so empty string
- OutputStream pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", new Date(),
- new byte[1 << 16]);
- updateProgress(progress, R.string.progress_encrypting, 20, 100);
-
- long done = 0;
- int n = 0;
- byte[] buffer = new byte[1 << 16];
- InputStream in = data.getInputStream();
- while ((n = in.read(buffer)) > 0) {
- pOut.write(buffer, 0, n);
- if (signatureKeyId != Id.key.none) {
- if (signatureForceV3) {
- signatureV3Generator.update(buffer, 0, n);
- } else {
- signatureGenerator.update(buffer, 0, n);
- }
- }
- done += n;
- if (data.getSize() != 0) {
- updateProgress(progress, (int) (20 + (95 - 20) * done / data.getSize()), 100);
- }
- }
-
- literalGen.close();
-
- if (signatureKeyId != Id.key.none) {
- updateProgress(progress, R.string.progress_generatingSignature, 95, 100);
- if (signatureForceV3) {
- signatureV3Generator.generate().encode(pOut);
- } else {
- signatureGenerator.generate().encode(pOut);
- }
- }
- if (compressGen != null) {
- compressGen.close();
- }
- encryptOut.close();
- if (useAsciiArmor) {
- armorOut.close();
- }
-
- updateProgress(progress, R.string.progress_done, 100, 100);
- }
-
- public static void signText(Context context, ProgressDialogUpdater progress, InputData data,
- OutputStream outStream, long signatureKeyId, String signaturePassphrase,
- int signatureHashAlgorithm, boolean forceV3Signature) throws PgpGeneralException,
- PGPException, IOException, NoSuchAlgorithmException, SignatureException {
-
- ArmoredOutputStream armorOut = new ArmoredOutputStream(outStream);
- armorOut.setHeader("Version", getFullVersion(context));
-
- PGPSecretKey signingKey = null;
- PGPSecretKeyRing signingKeyRing = null;
- PGPPrivateKey signaturePrivateKey = null;
-
- if (signatureKeyId == 0) {
- armorOut.close();
- throw new PgpGeneralException(context.getString(R.string.error_noSignatureKey));
- }
-
- signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, signatureKeyId);
- signingKey = PgpHelper.getSigningKey(context, signatureKeyId);
- if (signingKey == null) {
- armorOut.close();
- throw new PgpGeneralException(context.getString(R.string.error_signatureFailed));
- }
-
- if (signaturePassphrase == null) {
- armorOut.close();
- throw new PgpGeneralException(context.getString(R.string.error_noSignaturePassPhrase));
- }
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassphrase.toCharArray());
- signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
- if (signaturePrivateKey == null) {
- armorOut.close();
- throw new PgpGeneralException(
- context.getString(R.string.error_couldNotExtractPrivateKey));
- }
- updateProgress(progress, R.string.progress_preparingStreams, 0, 100);
-
- updateProgress(progress, R.string.progress_preparingSignature, 30, 100);
-
- PGPSignatureGenerator signatureGenerator = null;
- PGPV3SignatureGenerator signatureV3Generator = null;
-
- // content signer based on signing key algorithm and choosen hash algorithm
- JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
- .getPublicKey().getAlgorithm(), signatureHashAlgorithm)
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME);
-
- if (forceV3Signature) {
- signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
- signatureV3Generator.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
- } else {
- signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
- signatureGenerator.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
-
- PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
- String userId = PgpHelper.getMainUserId(PgpHelper.getMasterKey(signingKeyRing));
- spGen.setSignerUserID(false, userId);
- signatureGenerator.setHashedSubpackets(spGen.generate());
- }
-
- updateProgress(progress, R.string.progress_signing, 40, 100);
-
- armorOut.beginClearText(signatureHashAlgorithm);
-
- InputStream inStream = data.getInputStream();
- final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
-
- final byte[] newline = "\r\n".getBytes("UTF-8");
-
- if (forceV3Signature) {
- processLine(reader.readLine(), armorOut, signatureV3Generator);
- } else {
- processLine(reader.readLine(), armorOut, signatureGenerator);
- }
-
- while (true) {
- final String line = reader.readLine();
-
- if (line == null) {
- armorOut.write(newline);
- break;
- }
-
- armorOut.write(newline);
- if (forceV3Signature) {
- signatureV3Generator.update(newline);
- processLine(line, armorOut, signatureV3Generator);
- } else {
- signatureGenerator.update(newline);
- processLine(line, armorOut, signatureGenerator);
- }
- }
-
- armorOut.endClearText();
-
- BCPGOutputStream bOut = new BCPGOutputStream(armorOut);
- if (forceV3Signature) {
- signatureV3Generator.generate().encode(bOut);
- } else {
- signatureGenerator.generate().encode(bOut);
- }
- armorOut.close();
-
- updateProgress(progress, R.string.progress_done, 100, 100);
- }
-
- public static void generateSignature(Context context, ProgressDialogUpdater progress,
- InputData data, OutputStream outStream, boolean armored, boolean binary,
- long signatureKeyId, String signaturePassPhrase, int hashAlgorithm,
- boolean forceV3Signature) throws PgpGeneralException, PGPException, IOException,
- NoSuchAlgorithmException, SignatureException {
-
- OutputStream out = null;
-
- // Ascii Armor (Base64)
- ArmoredOutputStream armorOut = null;
- if (armored) {
- armorOut = new ArmoredOutputStream(outStream);
- armorOut.setHeader("Version", getFullVersion(context));
- out = armorOut;
- } else {
- out = outStream;
- }
-
- PGPSecretKey signingKey = null;
- PGPSecretKeyRing signingKeyRing = null;
- PGPPrivateKey signaturePrivateKey = null;
-
- if (signatureKeyId == 0) {
- throw new PgpGeneralException(context.getString(R.string.error_noSignatureKey));
- }
-
- signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, signatureKeyId);
- signingKey = PgpHelper.getSigningKey(context, signatureKeyId);
- if (signingKey == null) {
- throw new PgpGeneralException(context.getString(R.string.error_signatureFailed));
- }
-
- if (signaturePassPhrase == null) {
- throw new PgpGeneralException(context.getString(R.string.error_noSignaturePassPhrase));
- }
-
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassPhrase.toCharArray());
- signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
- if (signaturePrivateKey == null) {
- throw new PgpGeneralException(
- context.getString(R.string.error_couldNotExtractPrivateKey));
- }
- updateProgress(progress, R.string.progress_preparingStreams, 0, 100);
-
- updateProgress(progress, R.string.progress_preparingSignature, 30, 100);
-
- PGPSignatureGenerator signatureGenerator = null;
- PGPV3SignatureGenerator signatureV3Generator = null;
-
- int type = PGPSignature.CANONICAL_TEXT_DOCUMENT;
- if (binary) {
- type = PGPSignature.BINARY_DOCUMENT;
- }
-
- // content signer based on signing key algorithm and choosen hash algorithm
- JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
- .getPublicKey().getAlgorithm(), hashAlgorithm)
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME);
-
- if (forceV3Signature) {
- signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
- signatureV3Generator.init(type, signaturePrivateKey);
- } else {
- signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
- signatureGenerator.init(type, signaturePrivateKey);
-
- PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
- String userId = PgpHelper.getMainUserId(PgpHelper.getMasterKey(signingKeyRing));
- spGen.setSignerUserID(false, userId);
- signatureGenerator.setHashedSubpackets(spGen.generate());
- }
-
- updateProgress(progress, R.string.progress_signing, 40, 100);
-
- InputStream inStream = data.getInputStream();
- if (binary) {
- byte[] buffer = new byte[1 << 16];
- int n = 0;
- while ((n = inStream.read(buffer)) > 0) {
- if (forceV3Signature) {
- signatureV3Generator.update(buffer, 0, n);
- } else {
- signatureGenerator.update(buffer, 0, n);
- }
- }
- } else {
- final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
- final byte[] newline = "\r\n".getBytes("UTF-8");
-
- while (true) {
- final String line = reader.readLine();
-
- if (line == null) {
- break;
- }
-
- if (forceV3Signature) {
- processLine(line, null, signatureV3Generator);
- signatureV3Generator.update(newline);
- } else {
- processLine(line, null, signatureGenerator);
- signatureGenerator.update(newline);
- }
- }
- }
-
- BCPGOutputStream bOut = new BCPGOutputStream(out);
- if (forceV3Signature) {
- signatureV3Generator.generate().encode(bOut);
- } else {
- signatureGenerator.generate().encode(bOut);
- }
- out.close();
- outStream.close();
-
- if (progress != null)
- progress.setProgress(R.string.progress_done, 100, 100);
- }
-
- public static PGPPublicKeyRing signKey(Context context, long masterKeyId, long pubKeyId,
- String passphrase) throws PgpGeneralException, NoSuchAlgorithmException,
- NoSuchProviderException, PGPException, SignatureException {
- if (passphrase == null || passphrase.length() <= 0) {
- throw new PgpGeneralException("Unable to obtain passphrase");
- } else {
- PGPPublicKeyRing pubring = ProviderHelper.getPGPPublicKeyRingByKeyId(context, pubKeyId);
-
- PGPSecretKey signingKey = PgpHelper.getCertificationKey(context, masterKeyId);
- if (signingKey == null) {
- throw new PgpGeneralException(context.getString(R.string.error_signatureFailed));
- }
-
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
- PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
- if (signaturePrivateKey == null) {
- throw new PgpGeneralException(
- context.getString(R.string.error_couldNotExtractPrivateKey));
- }
-
- // TODO: SHA256 fixed?
- JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
- signingKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256)
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME);
-
- PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
- contentSignerBuilder);
-
- signatureGenerator.init(PGPSignature.DIRECT_KEY, signaturePrivateKey);
-
- PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
-
- PGPSignatureSubpacketVector packetVector = spGen.generate();
- signatureGenerator.setHashedSubpackets(packetVector);
-
- PGPPublicKey signedKey = PGPPublicKey.addCertification(pubring.getPublicKey(pubKeyId),
- signatureGenerator.generate());
- pubring = PGPPublicKeyRing.insertPublicKey(pubring, signedKey);
-
- return pubring;
- }
- }
-
- public static long getDecryptionKeyId(Context context, InputStream inputStream)
- throws PgpGeneralException, NoAsymmetricEncryptionException, IOException {
- InputStream in = PGPUtil.getDecoderStream(inputStream);
- PGPObjectFactory pgpF = new PGPObjectFactory(in);
- PGPEncryptedDataList enc;
- Object o = pgpF.nextObject();
-
- // the first object might be a PGP marker packet.
- if (o instanceof PGPEncryptedDataList) {
- enc = (PGPEncryptedDataList) o;
- } else {
- enc = (PGPEncryptedDataList) pgpF.nextObject();
- }
-
- if (enc == null) {
- throw new PgpGeneralException(context.getString(R.string.error_invalidData));
- }
-
- // TODO: currently we always only look at the first known key
- // find the secret key
- PGPSecretKey secretKey = null;
- Iterator<?> it = enc.getEncryptedDataObjects();
- boolean gotAsymmetricEncryption = false;
- while (it.hasNext()) {
- Object obj = it.next();
- if (obj instanceof PGPPublicKeyEncryptedData) {
- gotAsymmetricEncryption = true;
- PGPPublicKeyEncryptedData pbe = (PGPPublicKeyEncryptedData) obj;
- secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, pbe.getKeyID());
- if (secretKey != null) {
- break;
- }
- }
- }
-
- if (!gotAsymmetricEncryption) {
- throw new NoAsymmetricEncryptionException();
- }
-
- if (secretKey == null) {
- return Id.key.none;
- }
-
- return secretKey.getKeyID();
- }
-
- public static boolean hasSymmetricEncryption(Context context, InputStream inputStream)
- throws PgpGeneralException, IOException {
- InputStream in = PGPUtil.getDecoderStream(inputStream);
- PGPObjectFactory pgpF = new PGPObjectFactory(in);
- PGPEncryptedDataList enc;
- Object o = pgpF.nextObject();
-
- // the first object might be a PGP marker packet.
- if (o instanceof PGPEncryptedDataList) {
- enc = (PGPEncryptedDataList) o;
- } else {
- enc = (PGPEncryptedDataList) pgpF.nextObject();
- }
-
- if (enc == null) {
- throw new PgpGeneralException(context.getString(R.string.error_invalidData));
- }
-
- Iterator<?> it = enc.getEncryptedDataObjects();
- while (it.hasNext()) {
- Object obj = it.next();
- if (obj instanceof PGPPBEEncryptedData) {
- return true;
- }
- }
-
- return false;
- }
-
- public static Bundle decryptAndVerify(Context context, ProgressDialogUpdater progress,
- InputData data, OutputStream outStream, String passphrase, boolean assumeSymmetric)
- throws IOException, PgpGeneralException, PGPException, SignatureException {
- if (passphrase == null) {
- passphrase = "";
- }
-
- Bundle returnData = new Bundle();
- InputStream in = PGPUtil.getDecoderStream(data.getInputStream());
- PGPObjectFactory pgpF = new PGPObjectFactory(in);
- PGPEncryptedDataList enc;
- Object o = pgpF.nextObject();
- long signatureKeyId = 0;
-
- int currentProgress = 0;
- if (progress != null)
- progress.setProgress(R.string.progress_readingData, currentProgress, 100);
-
- if (o instanceof PGPEncryptedDataList) {
- enc = (PGPEncryptedDataList) o;
- } else {
- enc = (PGPEncryptedDataList) pgpF.nextObject();
- }
-
- if (enc == null) {
- throw new PgpGeneralException(context.getString(R.string.error_invalidData));
- }
-
- InputStream clear = null;
- PGPEncryptedData encryptedData = null;
-
- currentProgress += 5;
-
- // TODO: currently we always only look at the first known key or symmetric encryption,
- // there might be more...
- if (assumeSymmetric) {
- PGPPBEEncryptedData pbe = null;
- Iterator<?> it = enc.getEncryptedDataObjects();
- // find secret key
- while (it.hasNext()) {
- Object obj = it.next();
- if (obj instanceof PGPPBEEncryptedData) {
- pbe = (PGPPBEEncryptedData) obj;
- break;
- }
- }
-
- if (pbe == null) {
- throw new PgpGeneralException(
- context.getString(R.string.error_noSymmetricEncryptionPacket));
- }
-
- updateProgress(progress, R.string.progress_preparingStreams, currentProgress, 100);
-
- PGPDigestCalculatorProvider digestCalcProvider = new JcaPGPDigestCalculatorProviderBuilder()
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build();
- PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
- digestCalcProvider).setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(
- passphrase.toCharArray());
-
- clear = pbe.getDataStream(decryptorFactory);
-
- encryptedData = pbe;
- currentProgress += 5;
- } else {
- if (progress != null)
- progress.setProgress(R.string.progress_findingKey, currentProgress, 100);
- PGPPublicKeyEncryptedData pbe = null;
- PGPSecretKey secretKey = null;
- Iterator<?> it = enc.getEncryptedDataObjects();
- // find secret key
- while (it.hasNext()) {
- Object obj = it.next();
- if (obj instanceof PGPPublicKeyEncryptedData) {
- PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj;
- secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, encData.getKeyID());
- if (secretKey != null) {
- pbe = encData;
- break;
- }
- }
- }
-
- if (secretKey == null) {
- throw new PgpGeneralException(context.getString(R.string.error_noSecretKeyFound));
- }
-
- currentProgress += 5;
- updateProgress(progress, R.string.progress_extractingKey, currentProgress, 100);
- PGPPrivateKey privateKey = null;
- try {
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
- privateKey = secretKey.extractPrivateKey(keyDecryptor);
- } catch (PGPException e) {
- throw new PGPException(context.getString(R.string.error_wrongPassPhrase));
- }
- if (privateKey == null) {
- throw new PgpGeneralException(
- context.getString(R.string.error_couldNotExtractPrivateKey));
- }
- currentProgress += 5;
- updateProgress(progress, R.string.progress_preparingStreams, currentProgress, 100);
-
- PublicKeyDataDecryptorFactory decryptorFactory = new JcePublicKeyDataDecryptorFactoryBuilder()
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(privateKey);
-
- clear = pbe.getDataStream(decryptorFactory);
-
- encryptedData = pbe;
- currentProgress += 5;
- }
-
- PGPObjectFactory plainFact = new PGPObjectFactory(clear);
- Object dataChunk = plainFact.nextObject();
- PGPOnePassSignature signature = null;
- PGPPublicKey signatureKey = null;
- int signatureIndex = -1;
-
- if (dataChunk instanceof PGPCompressedData) {
- if (progress != null)
- progress.setProgress(R.string.progress_decompressingData, currentProgress, 100);
- PGPObjectFactory fact = new PGPObjectFactory(
- ((PGPCompressedData) dataChunk).getDataStream());
- dataChunk = fact.nextObject();
- plainFact = fact;
- currentProgress += 10;
- }
-
- if (dataChunk instanceof PGPOnePassSignatureList) {
- if (progress != null)
- progress.setProgress(R.string.progress_processingSignature, currentProgress, 100);
- returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE, true);
- PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk;
- for (int i = 0; i < sigList.size(); ++i) {
- signature = sigList.get(i);
- signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(context, signature.getKeyID());
- if (signatureKeyId == 0) {
- signatureKeyId = signature.getKeyID();
- }
- if (signatureKey == null) {
- signature = null;
- } else {
- signatureIndex = i;
- signatureKeyId = signature.getKeyID();
- String userId = null;
- PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(
- context, signatureKeyId);
- if (signKeyRing != null) {
- userId = PgpHelper.getMainUserId(PgpHelper.getMasterKey(signKeyRing));
- }
- returnData.putString(KeychainIntentService.RESULT_SIGNATURE_USER_ID, userId);
- break;
- }
- }
-
- returnData.putLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, signatureKeyId);
-
- if (signature != null) {
- JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME);
-
- signature.init(contentVerifierBuilderProvider, signatureKey);
- } else {
- returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN, true);
- }
-
- dataChunk = plainFact.nextObject();
- currentProgress += 10;
- }
-
- if (dataChunk instanceof PGPSignatureList) {
- dataChunk = plainFact.nextObject();
- }
-
- if (dataChunk instanceof PGPLiteralData) {
- if (progress != null)
- progress.setProgress(R.string.progress_decrypting, currentProgress, 100);
- PGPLiteralData literalData = (PGPLiteralData) dataChunk;
- OutputStream out = outStream;
-
- byte[] buffer = new byte[1 << 16];
- InputStream dataIn = literalData.getInputStream();
-
- int startProgress = currentProgress;
- int endProgress = 100;
- if (signature != null) {
- endProgress = 90;
- } else if (encryptedData.isIntegrityProtected()) {
- endProgress = 95;
- }
- int n = 0;
- int done = 0;
- long startPos = data.getStreamPosition();
- while ((n = dataIn.read(buffer)) > 0) {
- out.write(buffer, 0, n);
- done += n;
- if (signature != null) {
- try {
- signature.update(buffer, 0, n);
- } catch (SignatureException e) {
- returnData
- .putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, false);
- signature = null;
- }
- }
- // unknown size, but try to at least have a moving, slowing down progress bar
- currentProgress = startProgress + (endProgress - startProgress) * done
- / (done + 100000);
- if (data.getSize() - startPos == 0) {
- currentProgress = endProgress;
- } else {
- currentProgress = (int) (startProgress + (endProgress - startProgress)
- * (data.getStreamPosition() - startPos) / (data.getSize() - startPos));
- }
- updateProgress(progress, currentProgress, 100);
- }
-
- if (signature != null) {
- if (progress != null)
- progress.setProgress(R.string.progress_verifyingSignature, 90, 100);
- PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
- PGPSignature messageSignature = signatureList.get(signatureIndex);
- if (signature.verify(messageSignature)) {
- returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, true);
- } else {
- returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, false);
- }
- }
- }
-
- // TODO: add integrity somewhere
- if (encryptedData.isIntegrityProtected()) {
- if (progress != null)
- progress.setProgress(R.string.progress_verifyingIntegrity, 95, 100);
- if (encryptedData.verify()) {
- // passed
- } else {
- // failed
- }
- } else {
- // no integrity check
- }
-
- updateProgress(progress, R.string.progress_done, 100, 100);
- return returnData;
- }
-
- public static Bundle verifyText(Context context, ProgressDialogUpdater progress,
- InputData data, OutputStream outStream, boolean lookupUnknownKey) throws IOException,
- PgpGeneralException, PGPException, SignatureException {
- Bundle returnData = new Bundle();
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ArmoredInputStream aIn = new ArmoredInputStream(data.getInputStream());
-
- updateProgress(progress, R.string.progress_done, 0, 100);
-
- // mostly taken from ClearSignedFileProcessor
- ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
- int lookAhead = readInputLine(lineOut, aIn);
- byte[] lineSep = getLineSeparator();
-
- byte[] line = lineOut.toByteArray();
- out.write(line, 0, getLengthWithoutSeparator(line));
- out.write(lineSep);
-
- while (lookAhead != -1 && aIn.isClearText()) {
- lookAhead = readInputLine(lineOut, lookAhead, aIn);
- line = lineOut.toByteArray();
- out.write(line, 0, getLengthWithoutSeparator(line));
- out.write(lineSep);
- }
-
- out.close();
-
- byte[] clearText = out.toByteArray();
- outStream.write(clearText);
-
- returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE, true);
-
- updateProgress(progress, R.string.progress_processingSignature, 60, 100);
- PGPObjectFactory pgpFact = new PGPObjectFactory(aIn);
-
- PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
- if (sigList == null) {
- throw new PgpGeneralException(context.getString(R.string.error_corruptData));
- }
- PGPSignature signature = null;
- long signatureKeyId = 0;
- PGPPublicKey signatureKey = null;
- for (int i = 0; i < sigList.size(); ++i) {
- signature = sigList.get(i);
- signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(context, signature.getKeyID());
- if (signatureKeyId == 0) {
- signatureKeyId = signature.getKeyID();
- }
- // if key is not known and we want to lookup unknown ones...
- if (signatureKey == null && lookupUnknownKey) {
-
- returnData = new Bundle();
- returnData.putLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, signatureKeyId);
- returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_LOOKUP_KEY, true);
-
- // return directly now, decrypt will be done again after importing unknown key
- return returnData;
- }
-
- if (signatureKey == null) {
- signature = null;
- } else {
- signatureKeyId = signature.getKeyID();
- String userId = null;
- PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(context,
- signatureKeyId);
- if (signKeyRing != null) {
- userId = PgpHelper.getMainUserId(PgpHelper.getMasterKey(signKeyRing));
- }
- returnData.putString(KeychainIntentService.RESULT_SIGNATURE_USER_ID, userId);
- break;
- }
- }
-
- returnData.putLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, signatureKeyId);
-
- if (signature == null) {
- returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN, true);
- if (progress != null)
- progress.setProgress(R.string.progress_done, 100, 100);
- return returnData;
- }
-
- JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
- .setProvider(BOUNCY_CASTLE_PROVIDER_NAME);
-
- signature.init(contentVerifierBuilderProvider, signatureKey);
-
- InputStream sigIn = new BufferedInputStream(new ByteArrayInputStream(clearText));
-
- lookAhead = readInputLine(lineOut, sigIn);
-
- processLine(signature, lineOut.toByteArray());
-
- if (lookAhead != -1) {
- do {
- lookAhead = readInputLine(lineOut, lookAhead, sigIn);
-
- signature.update((byte) '\r');
- signature.update((byte) '\n');
-
- processLine(signature, lineOut.toByteArray());
- } while (lookAhead != -1);
- }
-
- returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, signature.verify());
-
- updateProgress(progress, R.string.progress_done, 100, 100);
- return returnData;
- }
-
- public static int getStreamContent(Context context, InputStream inStream) throws IOException {
- InputStream in = PGPUtil.getDecoderStream(inStream);
- PGPObjectFactory pgpF = new PGPObjectFactory(in);
- Object object = pgpF.nextObject();
- while (object != null) {
- if (object instanceof PGPPublicKeyRing || object instanceof PGPSecretKeyRing) {
- return Id.content.keys;
- } else if (object instanceof PGPEncryptedDataList) {
- return Id.content.encrypted_data;
- }
- object = pgpF.nextObject();
- }
-
- return Id.content.unknown;
- }
-
- private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
- final PGPSignatureGenerator pSignatureGenerator) throws IOException, SignatureException {
-
- if (pLine == null) {
- return;
- }
-
- final char[] chars = pLine.toCharArray();
- int len = chars.length;
-
- while (len > 0) {
- if (!Character.isWhitespace(chars[len - 1])) {
- break;
- }
- len--;
- }
-
- final byte[] data = pLine.substring(0, len).getBytes("UTF-8");
-
- if (pArmoredOutput != null) {
- pArmoredOutput.write(data);
- }
- pSignatureGenerator.update(data);
- }
-
- private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
- final PGPV3SignatureGenerator pSignatureGenerator) throws IOException,
- SignatureException {
-
- if (pLine == null) {
- return;
- }
-
- final char[] chars = pLine.toCharArray();
- int len = chars.length;
-
- while (len > 0) {
- if (!Character.isWhitespace(chars[len - 1])) {
- break;
- }
- len--;
- }
-
- final byte[] data = pLine.substring(0, len).getBytes("UTF-8");
-
- if (pArmoredOutput != null) {
- pArmoredOutput.write(data);
- }
- pSignatureGenerator.update(data);
- }
-
- // taken from ClearSignedFileProcessor in BC
- private static void processLine(PGPSignature sig, byte[] line) throws SignatureException,
- IOException {
- int length = getLengthWithoutWhiteSpace(line);
- if (length > 0) {
- sig.update(line, 0, length);
- }
- }
-
- private static int readInputLine(ByteArrayOutputStream bOut, InputStream fIn)
- throws IOException {
- bOut.reset();
-
- int lookAhead = -1;
- int ch;
-
- while ((ch = fIn.read()) >= 0) {
- bOut.write(ch);
- if (ch == '\r' || ch == '\n') {
- lookAhead = readPassedEOL(bOut, ch, fIn);
- break;
- }
- }
-
- return lookAhead;
- }
-
- private static int readInputLine(ByteArrayOutputStream bOut, int lookAhead, InputStream fIn)
- throws IOException {
- bOut.reset();
-
- int ch = lookAhead;
-
- do {
- bOut.write(ch);
- if (ch == '\r' || ch == '\n') {
- lookAhead = readPassedEOL(bOut, ch, fIn);
- break;
- }
- } while ((ch = fIn.read()) >= 0);
-
- if (ch < 0) {
- lookAhead = -1;
- }
-
- return lookAhead;
- }
-
- private static int readPassedEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn)
- throws IOException {
- int lookAhead = fIn.read();
-
- if (lastCh == '\r' && lookAhead == '\n') {
- bOut.write(lookAhead);
- lookAhead = fIn.read();
- }
-
- return lookAhead;
- }
-
- private static int getLengthWithoutSeparator(byte[] line) {
- int end = line.length - 1;
-
- while (end >= 0 && isLineEnding(line[end])) {
- end--;
- }
-
- return end + 1;
- }
-
- private static boolean isLineEnding(byte b) {
- return b == '\r' || b == '\n';
- }
-
- private static int getLengthWithoutWhiteSpace(byte[] line) {
- int end = line.length - 1;
-
- while (end >= 0 && isWhiteSpace(line[end])) {
- end--;
- }
-
- return end + 1;
- }
-
- private static boolean isWhiteSpace(byte b) {
- return b == '\r' || b == '\n' || b == '\t' || b == ' ';
- }
-
- private static byte[] getLineSeparator() {
- String nl = System.getProperty("line.separator");
- byte[] nlBytes = new byte[nl.length()];
-
- for (int i = 0; i != nlBytes.length; i++) {
- nlBytes[i] = (byte) nl.charAt(i);
- }
-
- return nlBytes;
- }
-
- public static boolean isReleaseVersion(Context context) {
- try {
- PackageInfo pi = context.getPackageManager().getPackageInfo(Constants.PACKAGE_NAME, 0);
- if (pi.versionCode % 100 == 99) {
- return true;
- } else {
- return false;
- }
- } catch (NameNotFoundException e) {
- // impossible!
- return false;
- }
- }
-
- public static String getVersion(Context context) {
- String version = null;
- try {
- PackageInfo pi = context.getPackageManager().getPackageInfo(Constants.PACKAGE_NAME, 0);
- version = pi.versionName;
- return version;
- } catch (NameNotFoundException e) {
- Log.e(Constants.TAG, "Version could not be retrieved!", e);
- return "0.0.0";
- }
- }
-
- public static String getFullVersion(Context context) {
- return "OpenPGP Keychain v" + getVersion(context);
- }
-
- /**
- * Generate a random filename
- *
- * @param length
- * @return
- */
- public static String generateRandomFilename(int length) {
- SecureRandom random = new SecureRandom();
-
- byte bytes[] = new byte[length];
- random.nextBytes(bytes);
- String result = "";
- for (int i = 0; i < length; ++i) {
- int v = (bytes[i] + 256) % 64;
- if (v < 10) {
- result += (char) ('0' + v);
- } else if (v < 36) {
- result += (char) ('A' + v - 10);
- } else if (v < 62) {
- result += (char) ('a' + v - 36);
- } else if (v == 62) {
- result += '_';
- } else if (v == 63) {
- result += '.';
- }
- }
- return result;
- }
-
- /**
- * Go once through stream to get length of stream. The length is later used to display progress
- * when encrypting/decrypting
- *
- * @param in
- * @return
- * @throws IOException
- */
- public static long getLengthOfStream(InputStream in) throws IOException {
- long size = 0;
- long n = 0;
- byte dummy[] = new byte[0x10000];
- while ((n = in.read(dummy)) > 0) {
- size += n;
- }
- return size;
- }
-
- /**
- * Deletes file securely by overwriting it with random data before deleting it.
- *
- * TODO: Does this really help on flash storage?
- *
- * @param context
- * @param progress
- * @param file
- * @throws FileNotFoundException
- * @throws IOException
- */
- public static void deleteFileSecurely(Context context, ProgressDialogUpdater progress, File file)
- throws FileNotFoundException, IOException {
- long length = file.length();
- SecureRandom random = new SecureRandom();
- RandomAccessFile raf = new RandomAccessFile(file, "rws");
- raf.seek(0);
- raf.getFilePointer();
- byte[] data = new byte[1 << 16];
- int pos = 0;
- String msg = context.getString(R.string.progress_deletingSecurely, file.getName());
- while (pos < length) {
- if (progress != null)
- progress.setProgress(msg, (int) (100 * pos / length), 100);
- random.nextBytes(data);
- raf.write(data);
- pos += data.length;
- }
- raf.close();
- file.delete();
- }
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpOperation.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpOperation.java
new file mode 100644
index 000000000..823fb1f2e
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpOperation.java
@@ -0,0 +1,1068 @@
+/*
+ * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.sufficientlysecure.keychain.pgp;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SignatureException;
+import java.util.Date;
+import java.util.Iterator;
+
+import org.spongycastle.bcpg.ArmoredInputStream;
+import org.spongycastle.bcpg.ArmoredOutputStream;
+import org.spongycastle.bcpg.BCPGOutputStream;
+import org.spongycastle.openpgp.PGPCompressedData;
+import org.spongycastle.openpgp.PGPCompressedDataGenerator;
+import org.spongycastle.openpgp.PGPEncryptedData;
+import org.spongycastle.openpgp.PGPEncryptedDataGenerator;
+import org.spongycastle.openpgp.PGPEncryptedDataList;
+import org.spongycastle.openpgp.PGPException;
+import org.spongycastle.openpgp.PGPLiteralData;
+import org.spongycastle.openpgp.PGPLiteralDataGenerator;
+import org.spongycastle.openpgp.PGPObjectFactory;
+import org.spongycastle.openpgp.PGPOnePassSignature;
+import org.spongycastle.openpgp.PGPOnePassSignatureList;
+import org.spongycastle.openpgp.PGPPBEEncryptedData;
+import org.spongycastle.openpgp.PGPPrivateKey;
+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.PGPSignatureGenerator;
+import org.spongycastle.openpgp.PGPSignatureList;
+import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
+import org.spongycastle.openpgp.PGPUtil;
+import org.spongycastle.openpgp.PGPV3SignatureGenerator;
+import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
+import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
+import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
+import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
+import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
+import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
+import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
+import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;
+import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator;
+import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
+import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
+import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder;
+import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Id;
+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.util.InputData;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
+
+import android.content.Context;
+import android.os.Bundle;
+
+public class PgpOperation {
+ private Context mContext;
+ private ProgressDialogUpdater mProgress;
+ private InputData mData;
+ private OutputStream mOutStream;
+
+ public PgpOperation(Context context, ProgressDialogUpdater progress, InputData data,
+ OutputStream outStream) {
+ super();
+ this.mContext = context;
+ this.mProgress = progress;
+ this.mData = data;
+ this.mOutStream = outStream;
+ }
+
+ public void updateProgress(int message, int current, int total) {
+ if (mProgress != null) {
+ mProgress.setProgress(message, current, total);
+ }
+ }
+
+ public void updateProgress(int current, int total) {
+ if (mProgress != null) {
+ mProgress.setProgress(current, total);
+ }
+ }
+
+ /**
+ * Encrypt and Sign data
+ *
+ * @param mContext
+ * @param mProgress
+ * @param mData
+ * @param mOutStream
+ * @param useAsciiArmor
+ * @param compression
+ * @param encryptionKeyIds
+ * @param symmetricEncryptionAlgorithm
+ * @param encryptionPassphrase
+ * @param signatureKeyId
+ * @param signatureHashAlgorithm
+ * @param signatureForceV3
+ * @param signaturePassphrase
+ * @throws IOException
+ * @throws PgpGeneralException
+ * @throws PGPException
+ * @throws NoSuchProviderException
+ * @throws NoSuchAlgorithmException
+ * @throws SignatureException
+ */
+ public void encryptAndSign(boolean useAsciiArmor, int compression, long[] encryptionKeyIds,
+ String encryptionPassphrase, int symmetricEncryptionAlgorithm, long signatureKeyId,
+ int signatureHashAlgorithm, boolean signatureForceV3, String signaturePassphrase)
+ throws IOException, PgpGeneralException, PGPException, NoSuchProviderException,
+ NoSuchAlgorithmException, SignatureException {
+
+ if (encryptionKeyIds == null) {
+ encryptionKeyIds = new long[0];
+ }
+
+ ArmoredOutputStream armorOut = null;
+ OutputStream out = null;
+ OutputStream encryptOut = null;
+ if (useAsciiArmor) {
+ armorOut = new ArmoredOutputStream(mOutStream);
+ armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
+ out = armorOut;
+ } else {
+ out = mOutStream;
+ }
+ PGPSecretKey signingKey = null;
+ PGPSecretKeyRing signingKeyRing = null;
+ PGPPrivateKey signaturePrivateKey = null;
+
+ if (encryptionKeyIds.length == 0 && encryptionPassphrase == null) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_noEncryptionKeysOrPassPhrase));
+ }
+
+ if (signatureKeyId != Id.key.none) {
+ signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, signatureKeyId);
+ signingKey = PgpKeyHelper.getSigningKey(mContext, signatureKeyId);
+ if (signingKey == null) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_signatureFailed));
+ }
+
+ if (signaturePassphrase == null) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_noSignaturePassPhrase));
+ }
+
+ updateProgress(R.string.progress_extractingSignatureKey, 0, 100);
+
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassphrase.toCharArray());
+ signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
+ if (signaturePrivateKey == null) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_couldNotExtractPrivateKey));
+ }
+ }
+ updateProgress(R.string.progress_preparingStreams, 5, 100);
+
+ // encrypt and compress input file content
+ JcePGPDataEncryptorBuilder encryptorBuilder = new JcePGPDataEncryptorBuilder(
+ symmetricEncryptionAlgorithm).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
+ .setWithIntegrityPacket(true);
+
+ PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(encryptorBuilder);
+
+ if (encryptionKeyIds.length == 0) {
+ // Symmetric encryption
+ Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption");
+
+ JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator = new JcePBEKeyEncryptionMethodGenerator(
+ encryptionPassphrase.toCharArray());
+ cPk.addMethod(symmetricEncryptionGenerator);
+ } else {
+ // Asymmetric encryption
+ for (long id : encryptionKeyIds) {
+ PGPPublicKey key = PgpKeyHelper.getEncryptPublicKey(mContext, id);
+ if (key != null) {
+
+ JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator = new JcePublicKeyKeyEncryptionMethodGenerator(
+ key);
+ cPk.addMethod(pubKeyEncryptionGenerator);
+ }
+ }
+ }
+ encryptOut = cPk.open(out, new byte[1 << 16]);
+
+ PGPSignatureGenerator signatureGenerator = null;
+ PGPV3SignatureGenerator signatureV3Generator = null;
+
+ if (signatureKeyId != Id.key.none) {
+ updateProgress(R.string.progress_preparingSignature, 10, 100);
+
+ // content signer based on signing key algorithm and choosen hash algorithm
+ JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
+ signingKey.getPublicKey().getAlgorithm(), signatureHashAlgorithm)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+
+ if (signatureForceV3) {
+ signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
+ signatureV3Generator.init(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
+ } else {
+ signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
+ signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey);
+
+ String userId = PgpKeyHelper.getMainUserId(PgpKeyHelper
+ .getMasterKey(signingKeyRing));
+ PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
+ spGen.setSignerUserID(false, userId);
+ signatureGenerator.setHashedSubpackets(spGen.generate());
+ }
+ }
+
+ PGPCompressedDataGenerator compressGen = null;
+ BCPGOutputStream bcpgOut = null;
+ if (compression == Id.choice.compression.none) {
+ bcpgOut = new BCPGOutputStream(encryptOut);
+ } else {
+ compressGen = new PGPCompressedDataGenerator(compression);
+ bcpgOut = new BCPGOutputStream(compressGen.open(encryptOut));
+ }
+ if (signatureKeyId != Id.key.none) {
+ if (signatureForceV3) {
+ signatureV3Generator.generateOnePassVersion(false).encode(bcpgOut);
+ } else {
+ signatureGenerator.generateOnePassVersion(false).encode(bcpgOut);
+ }
+ }
+
+ PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
+ // file name not needed, so empty string
+ OutputStream pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", new Date(),
+ new byte[1 << 16]);
+ updateProgress(R.string.progress_encrypting, 20, 100);
+
+ long done = 0;
+ int n = 0;
+ byte[] buffer = new byte[1 << 16];
+ InputStream in = mData.getInputStream();
+ while ((n = in.read(buffer)) > 0) {
+ pOut.write(buffer, 0, n);
+ if (signatureKeyId != Id.key.none) {
+ if (signatureForceV3) {
+ signatureV3Generator.update(buffer, 0, n);
+ } else {
+ signatureGenerator.update(buffer, 0, n);
+ }
+ }
+ done += n;
+ if (mData.getSize() != 0) {
+ updateProgress((int) (20 + (95 - 20) * done / mData.getSize()), 100);
+ }
+ }
+
+ literalGen.close();
+
+ if (signatureKeyId != Id.key.none) {
+ updateProgress(R.string.progress_generatingSignature, 95, 100);
+ if (signatureForceV3) {
+ signatureV3Generator.generate().encode(pOut);
+ } else {
+ signatureGenerator.generate().encode(pOut);
+ }
+ }
+ if (compressGen != null) {
+ compressGen.close();
+ }
+ encryptOut.close();
+ if (useAsciiArmor) {
+ armorOut.close();
+ }
+
+ updateProgress(R.string.progress_done, 100, 100);
+ }
+
+ public void signText(long signatureKeyId, String signaturePassphrase,
+ int signatureHashAlgorithm, boolean forceV3Signature) throws PgpGeneralException,
+ PGPException, IOException, NoSuchAlgorithmException, SignatureException {
+
+ ArmoredOutputStream armorOut = new ArmoredOutputStream(mOutStream);
+ armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
+
+ PGPSecretKey signingKey = null;
+ PGPSecretKeyRing signingKeyRing = null;
+ PGPPrivateKey signaturePrivateKey = null;
+
+ if (signatureKeyId == 0) {
+ armorOut.close();
+ throw new PgpGeneralException(mContext.getString(R.string.error_noSignatureKey));
+ }
+
+ signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, signatureKeyId);
+ signingKey = PgpKeyHelper.getSigningKey(mContext, signatureKeyId);
+ if (signingKey == null) {
+ armorOut.close();
+ throw new PgpGeneralException(mContext.getString(R.string.error_signatureFailed));
+ }
+
+ if (signaturePassphrase == null) {
+ armorOut.close();
+ throw new PgpGeneralException(mContext.getString(R.string.error_noSignaturePassPhrase));
+ }
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassphrase.toCharArray());
+ signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
+ if (signaturePrivateKey == null) {
+ armorOut.close();
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_couldNotExtractPrivateKey));
+ }
+ updateProgress(R.string.progress_preparingStreams, 0, 100);
+
+ updateProgress(R.string.progress_preparingSignature, 30, 100);
+
+ PGPSignatureGenerator signatureGenerator = null;
+ PGPV3SignatureGenerator signatureV3Generator = null;
+
+ // content signer based on signing key algorithm and choosen hash algorithm
+ JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
+ .getPublicKey().getAlgorithm(), signatureHashAlgorithm)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+
+ if (forceV3Signature) {
+ signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
+ signatureV3Generator.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
+ } else {
+ signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
+ signatureGenerator.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey);
+
+ PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
+ String userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signingKeyRing));
+ spGen.setSignerUserID(false, userId);
+ signatureGenerator.setHashedSubpackets(spGen.generate());
+ }
+
+ updateProgress(R.string.progress_signing, 40, 100);
+
+ armorOut.beginClearText(signatureHashAlgorithm);
+
+ InputStream inStream = mData.getInputStream();
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
+
+ final byte[] newline = "\r\n".getBytes("UTF-8");
+
+ if (forceV3Signature) {
+ processLine(reader.readLine(), armorOut, signatureV3Generator);
+ } else {
+ processLine(reader.readLine(), armorOut, signatureGenerator);
+ }
+
+ while (true) {
+ final String line = reader.readLine();
+
+ if (line == null) {
+ armorOut.write(newline);
+ break;
+ }
+
+ armorOut.write(newline);
+ if (forceV3Signature) {
+ signatureV3Generator.update(newline);
+ processLine(line, armorOut, signatureV3Generator);
+ } else {
+ signatureGenerator.update(newline);
+ processLine(line, armorOut, signatureGenerator);
+ }
+ }
+
+ armorOut.endClearText();
+
+ BCPGOutputStream bOut = new BCPGOutputStream(armorOut);
+ if (forceV3Signature) {
+ signatureV3Generator.generate().encode(bOut);
+ } else {
+ signatureGenerator.generate().encode(bOut);
+ }
+ armorOut.close();
+
+ updateProgress(R.string.progress_done, 100, 100);
+ }
+
+ public void generateSignature(boolean armored, boolean binary, long signatureKeyId,
+ String signaturePassPhrase, int hashAlgorithm, boolean forceV3Signature)
+ throws PgpGeneralException, PGPException, IOException, NoSuchAlgorithmException,
+ SignatureException {
+
+ OutputStream out = null;
+
+ // Ascii Armor (Base64)
+ ArmoredOutputStream armorOut = null;
+ if (armored) {
+ armorOut = new ArmoredOutputStream(mOutStream);
+ armorOut.setHeader("Version", PgpHelper.getFullVersion(mContext));
+ out = armorOut;
+ } else {
+ out = mOutStream;
+ }
+
+ PGPSecretKey signingKey = null;
+ PGPSecretKeyRing signingKeyRing = null;
+ PGPPrivateKey signaturePrivateKey = null;
+
+ if (signatureKeyId == 0) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_noSignatureKey));
+ }
+
+ signingKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, signatureKeyId);
+ signingKey = PgpKeyHelper.getSigningKey(mContext, signatureKeyId);
+ if (signingKey == null) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_signatureFailed));
+ }
+
+ if (signaturePassPhrase == null) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_noSignaturePassPhrase));
+ }
+
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassPhrase.toCharArray());
+ signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
+ if (signaturePrivateKey == null) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_couldNotExtractPrivateKey));
+ }
+ updateProgress(R.string.progress_preparingStreams, 0, 100);
+
+ updateProgress(R.string.progress_preparingSignature, 30, 100);
+
+ PGPSignatureGenerator signatureGenerator = null;
+ PGPV3SignatureGenerator signatureV3Generator = null;
+
+ int type = PGPSignature.CANONICAL_TEXT_DOCUMENT;
+ if (binary) {
+ type = PGPSignature.BINARY_DOCUMENT;
+ }
+
+ // content signer based on signing key algorithm and choosen hash algorithm
+ JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(signingKey
+ .getPublicKey().getAlgorithm(), hashAlgorithm)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+
+ if (forceV3Signature) {
+ signatureV3Generator = new PGPV3SignatureGenerator(contentSignerBuilder);
+ signatureV3Generator.init(type, signaturePrivateKey);
+ } else {
+ signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
+ signatureGenerator.init(type, signaturePrivateKey);
+
+ PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
+ String userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signingKeyRing));
+ spGen.setSignerUserID(false, userId);
+ signatureGenerator.setHashedSubpackets(spGen.generate());
+ }
+
+ updateProgress(R.string.progress_signing, 40, 100);
+
+ InputStream inStream = mData.getInputStream();
+ if (binary) {
+ byte[] buffer = new byte[1 << 16];
+ int n = 0;
+ while ((n = inStream.read(buffer)) > 0) {
+ if (forceV3Signature) {
+ signatureV3Generator.update(buffer, 0, n);
+ } else {
+ signatureGenerator.update(buffer, 0, n);
+ }
+ }
+ } else {
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
+ final byte[] newline = "\r\n".getBytes("UTF-8");
+
+ while (true) {
+ final String line = reader.readLine();
+
+ if (line == null) {
+ break;
+ }
+
+ if (forceV3Signature) {
+ processLine(line, null, signatureV3Generator);
+ signatureV3Generator.update(newline);
+ } else {
+ processLine(line, null, signatureGenerator);
+ signatureGenerator.update(newline);
+ }
+ }
+ }
+
+ BCPGOutputStream bOut = new BCPGOutputStream(out);
+ if (forceV3Signature) {
+ signatureV3Generator.generate().encode(bOut);
+ } else {
+ signatureGenerator.generate().encode(bOut);
+ }
+ out.close();
+ mOutStream.close();
+
+ if (mProgress != null)
+ mProgress.setProgress(R.string.progress_done, 100, 100);
+ }
+
+ public static boolean hasSymmetricEncryption(Context context, InputStream inputStream)
+ throws PgpGeneralException, IOException {
+ InputStream in = PGPUtil.getDecoderStream(inputStream);
+ PGPObjectFactory pgpF = new PGPObjectFactory(in);
+ PGPEncryptedDataList enc;
+ Object o = pgpF.nextObject();
+
+ // the first object might be a PGP marker packet.
+ if (o instanceof PGPEncryptedDataList) {
+ enc = (PGPEncryptedDataList) o;
+ } else {
+ enc = (PGPEncryptedDataList) pgpF.nextObject();
+ }
+
+ if (enc == null) {
+ throw new PgpGeneralException(context.getString(R.string.error_invalidData));
+ }
+
+ Iterator<?> it = enc.getEncryptedDataObjects();
+ while (it.hasNext()) {
+ Object obj = it.next();
+ if (obj instanceof PGPPBEEncryptedData) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public Bundle decryptAndVerify(String passphrase, boolean assumeSymmetric) throws IOException,
+ PgpGeneralException, PGPException, SignatureException {
+ if (passphrase == null) {
+ passphrase = "";
+ }
+
+ Bundle returnData = new Bundle();
+ InputStream in = PGPUtil.getDecoderStream(mData.getInputStream());
+ PGPObjectFactory pgpF = new PGPObjectFactory(in);
+ PGPEncryptedDataList enc;
+ Object o = pgpF.nextObject();
+ long signatureKeyId = 0;
+
+ int currentProgress = 0;
+ updateProgress(R.string.progress_readingData, currentProgress, 100);
+
+ if (o instanceof PGPEncryptedDataList) {
+ enc = (PGPEncryptedDataList) o;
+ } else {
+ enc = (PGPEncryptedDataList) pgpF.nextObject();
+ }
+
+ if (enc == null) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_invalidData));
+ }
+
+ InputStream clear = null;
+ PGPEncryptedData encryptedData = null;
+
+ currentProgress += 5;
+
+ // TODO: currently we always only look at the first known key or symmetric encryption,
+ // there might be more...
+ if (assumeSymmetric) {
+ PGPPBEEncryptedData pbe = null;
+ Iterator<?> it = enc.getEncryptedDataObjects();
+ // find secret key
+ while (it.hasNext()) {
+ Object obj = it.next();
+ if (obj instanceof PGPPBEEncryptedData) {
+ pbe = (PGPPBEEncryptedData) obj;
+ break;
+ }
+ }
+
+ if (pbe == null) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_noSymmetricEncryptionPacket));
+ }
+
+ updateProgress(R.string.progress_preparingStreams, currentProgress, 100);
+
+ PGPDigestCalculatorProvider digestCalcProvider = new JcaPGPDigestCalculatorProviderBuilder()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build();
+ PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
+ digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ passphrase.toCharArray());
+
+ clear = pbe.getDataStream(decryptorFactory);
+
+ encryptedData = pbe;
+ currentProgress += 5;
+ } else {
+ updateProgress(R.string.progress_findingKey, currentProgress, 100);
+
+ PGPPublicKeyEncryptedData pbe = null;
+ PGPSecretKey secretKey = null;
+ Iterator<?> it = enc.getEncryptedDataObjects();
+ // find secret key
+ while (it.hasNext()) {
+ Object obj = it.next();
+ if (obj instanceof PGPPublicKeyEncryptedData) {
+ PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj;
+ secretKey = ProviderHelper.getPGPSecretKeyByKeyId(mContext, encData.getKeyID());
+ if (secretKey != null) {
+ pbe = encData;
+ break;
+ }
+ }
+ }
+
+ if (secretKey == null) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_noSecretKeyFound));
+ }
+
+ currentProgress += 5;
+ updateProgress(R.string.progress_extractingKey, currentProgress, 100);
+ PGPPrivateKey privateKey = null;
+ try {
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ passphrase.toCharArray());
+ privateKey = secretKey.extractPrivateKey(keyDecryptor);
+ } catch (PGPException e) {
+ throw new PGPException(mContext.getString(R.string.error_wrongPassPhrase));
+ }
+ if (privateKey == null) {
+ throw new PgpGeneralException(
+ mContext.getString(R.string.error_couldNotExtractPrivateKey));
+ }
+ currentProgress += 5;
+ updateProgress(R.string.progress_preparingStreams, currentProgress, 100);
+
+ PublicKeyDataDecryptorFactory decryptorFactory = new JcePublicKeyDataDecryptorFactoryBuilder()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(privateKey);
+
+ clear = pbe.getDataStream(decryptorFactory);
+
+ encryptedData = pbe;
+ currentProgress += 5;
+ }
+
+ PGPObjectFactory plainFact = new PGPObjectFactory(clear);
+ Object dataChunk = plainFact.nextObject();
+ PGPOnePassSignature signature = null;
+ PGPPublicKey signatureKey = null;
+ int signatureIndex = -1;
+
+ if (dataChunk instanceof PGPCompressedData) {
+ updateProgress(R.string.progress_decompressingData, currentProgress, 100);
+
+ PGPObjectFactory fact = new PGPObjectFactory(
+ ((PGPCompressedData) dataChunk).getDataStream());
+ dataChunk = fact.nextObject();
+ plainFact = fact;
+ currentProgress += 10;
+ }
+
+ if (dataChunk instanceof PGPOnePassSignatureList) {
+ updateProgress(R.string.progress_processingSignature, currentProgress, 100);
+
+ returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE, true);
+ PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk;
+ for (int i = 0; i < sigList.size(); ++i) {
+ signature = sigList.get(i);
+ signatureKey = ProviderHelper
+ .getPGPPublicKeyByKeyId(mContext, signature.getKeyID());
+ if (signatureKeyId == 0) {
+ signatureKeyId = signature.getKeyID();
+ }
+ if (signatureKey == null) {
+ signature = null;
+ } else {
+ signatureIndex = i;
+ signatureKeyId = signature.getKeyID();
+ String userId = null;
+ PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(
+ mContext, signatureKeyId);
+ if (signKeyRing != null) {
+ userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
+ }
+ returnData.putString(KeychainIntentService.RESULT_SIGNATURE_USER_ID, userId);
+ break;
+ }
+ }
+
+ returnData.putLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, signatureKeyId);
+
+ if (signature != null) {
+ JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+
+ signature.init(contentVerifierBuilderProvider, signatureKey);
+ } else {
+ returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN, true);
+ }
+
+ dataChunk = plainFact.nextObject();
+ currentProgress += 10;
+ }
+
+ if (dataChunk instanceof PGPSignatureList) {
+ dataChunk = plainFact.nextObject();
+ }
+
+ if (dataChunk instanceof PGPLiteralData) {
+ updateProgress(R.string.progress_decrypting, currentProgress, 100);
+
+ PGPLiteralData literalData = (PGPLiteralData) dataChunk;
+ OutputStream out = mOutStream;
+
+ byte[] buffer = new byte[1 << 16];
+ InputStream dataIn = literalData.getInputStream();
+
+ int startProgress = currentProgress;
+ int endProgress = 100;
+ if (signature != null) {
+ endProgress = 90;
+ } else if (encryptedData.isIntegrityProtected()) {
+ endProgress = 95;
+ }
+ int n = 0;
+ int done = 0;
+ long startPos = mData.getStreamPosition();
+ while ((n = dataIn.read(buffer)) > 0) {
+ out.write(buffer, 0, n);
+ done += n;
+ if (signature != null) {
+ try {
+ signature.update(buffer, 0, n);
+ } catch (SignatureException e) {
+ returnData
+ .putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, false);
+ signature = null;
+ }
+ }
+ // unknown size, but try to at least have a moving, slowing down progress bar
+ currentProgress = startProgress + (endProgress - startProgress) * done
+ / (done + 100000);
+ if (mData.getSize() - startPos == 0) {
+ currentProgress = endProgress;
+ } else {
+ currentProgress = (int) (startProgress + (endProgress - startProgress)
+ * (mData.getStreamPosition() - startPos) / (mData.getSize() - startPos));
+ }
+ updateProgress(currentProgress, 100);
+ }
+
+ if (signature != null) {
+ updateProgress(R.string.progress_verifyingSignature, 90, 100);
+
+ PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
+ PGPSignature messageSignature = signatureList.get(signatureIndex);
+ if (signature.verify(messageSignature)) {
+ returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, true);
+ } else {
+ returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, false);
+ }
+ }
+ }
+
+ // TODO: add integrity somewhere
+ if (encryptedData.isIntegrityProtected()) {
+ updateProgress(R.string.progress_verifyingIntegrity, 95, 100);
+
+ if (encryptedData.verify()) {
+ // passed
+ } else {
+ // failed
+ }
+ } else {
+ // no integrity check
+ }
+
+ updateProgress(R.string.progress_done, 100, 100);
+ return returnData;
+ }
+
+ public Bundle verifyText(boolean lookupUnknownKey) throws IOException, PgpGeneralException,
+ PGPException, SignatureException {
+ Bundle returnData = new Bundle();
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ArmoredInputStream aIn = new ArmoredInputStream(mData.getInputStream());
+
+ updateProgress(R.string.progress_done, 0, 100);
+
+ // mostly taken from ClearSignedFileProcessor
+ ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
+ int lookAhead = readInputLine(lineOut, aIn);
+ byte[] lineSep = getLineSeparator();
+
+ byte[] line = lineOut.toByteArray();
+ out.write(line, 0, getLengthWithoutSeparator(line));
+ out.write(lineSep);
+
+ while (lookAhead != -1 && aIn.isClearText()) {
+ lookAhead = readInputLine(lineOut, lookAhead, aIn);
+ line = lineOut.toByteArray();
+ out.write(line, 0, getLengthWithoutSeparator(line));
+ out.write(lineSep);
+ }
+
+ out.close();
+
+ byte[] clearText = out.toByteArray();
+ mOutStream.write(clearText);
+
+ returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE, true);
+
+ updateProgress(R.string.progress_processingSignature, 60, 100);
+ PGPObjectFactory pgpFact = new PGPObjectFactory(aIn);
+
+ PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
+ if (sigList == null) {
+ throw new PgpGeneralException(mContext.getString(R.string.error_corruptData));
+ }
+ PGPSignature signature = null;
+ long signatureKeyId = 0;
+ PGPPublicKey signatureKey = null;
+ for (int i = 0; i < sigList.size(); ++i) {
+ signature = sigList.get(i);
+ signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(mContext, signature.getKeyID());
+ if (signatureKeyId == 0) {
+ signatureKeyId = signature.getKeyID();
+ }
+ // if key is not known and we want to lookup unknown ones...
+ if (signatureKey == null && lookupUnknownKey) {
+
+ returnData = new Bundle();
+ returnData.putLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, signatureKeyId);
+ returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_LOOKUP_KEY, true);
+
+ // return directly now, decrypt will be done again after importing unknown key
+ return returnData;
+ }
+
+ if (signatureKey == null) {
+ signature = null;
+ } else {
+ signatureKeyId = signature.getKeyID();
+ String userId = null;
+ PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(mContext,
+ signatureKeyId);
+ if (signKeyRing != null) {
+ userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing));
+ }
+ returnData.putString(KeychainIntentService.RESULT_SIGNATURE_USER_ID, userId);
+ break;
+ }
+ }
+
+ returnData.putLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID, signatureKeyId);
+
+ if (signature == null) {
+ returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN, true);
+ if (mProgress != null)
+ mProgress.setProgress(R.string.progress_done, 100, 100);
+ return returnData;
+ }
+
+ JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+
+ signature.init(contentVerifierBuilderProvider, signatureKey);
+
+ InputStream sigIn = new BufferedInputStream(new ByteArrayInputStream(clearText));
+
+ lookAhead = readInputLine(lineOut, sigIn);
+
+ processLine(signature, lineOut.toByteArray());
+
+ if (lookAhead != -1) {
+ do {
+ lookAhead = readInputLine(lineOut, lookAhead, sigIn);
+
+ signature.update((byte) '\r');
+ signature.update((byte) '\n');
+
+ processLine(signature, lineOut.toByteArray());
+ } while (lookAhead != -1);
+ }
+
+ returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, signature.verify());
+
+ updateProgress(R.string.progress_done, 100, 100);
+ return returnData;
+ }
+
+ private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
+ final PGPSignatureGenerator pSignatureGenerator) throws IOException, SignatureException {
+
+ if (pLine == null) {
+ return;
+ }
+
+ final char[] chars = pLine.toCharArray();
+ int len = chars.length;
+
+ while (len > 0) {
+ if (!Character.isWhitespace(chars[len - 1])) {
+ break;
+ }
+ len--;
+ }
+
+ final byte[] data = pLine.substring(0, len).getBytes("UTF-8");
+
+ if (pArmoredOutput != null) {
+ pArmoredOutput.write(data);
+ }
+ pSignatureGenerator.update(data);
+ }
+
+ private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
+ final PGPV3SignatureGenerator pSignatureGenerator) throws IOException,
+ SignatureException {
+
+ if (pLine == null) {
+ return;
+ }
+
+ final char[] chars = pLine.toCharArray();
+ int len = chars.length;
+
+ while (len > 0) {
+ if (!Character.isWhitespace(chars[len - 1])) {
+ break;
+ }
+ len--;
+ }
+
+ final byte[] data = pLine.substring(0, len).getBytes("UTF-8");
+
+ if (pArmoredOutput != null) {
+ pArmoredOutput.write(data);
+ }
+ pSignatureGenerator.update(data);
+ }
+
+ // taken from ClearSignedFileProcessor in BC
+ private static void processLine(PGPSignature sig, byte[] line) throws SignatureException,
+ IOException {
+ int length = getLengthWithoutWhiteSpace(line);
+ if (length > 0) {
+ sig.update(line, 0, length);
+ }
+ }
+
+ private static int readInputLine(ByteArrayOutputStream bOut, InputStream fIn)
+ throws IOException {
+ bOut.reset();
+
+ int lookAhead = -1;
+ int ch;
+
+ while ((ch = fIn.read()) >= 0) {
+ bOut.write(ch);
+ if (ch == '\r' || ch == '\n') {
+ lookAhead = readPassedEOL(bOut, ch, fIn);
+ break;
+ }
+ }
+
+ return lookAhead;
+ }
+
+ private static int readInputLine(ByteArrayOutputStream bOut, int lookAhead, InputStream fIn)
+ throws IOException {
+ bOut.reset();
+
+ int ch = lookAhead;
+
+ do {
+ bOut.write(ch);
+ if (ch == '\r' || ch == '\n') {
+ lookAhead = readPassedEOL(bOut, ch, fIn);
+ break;
+ }
+ } while ((ch = fIn.read()) >= 0);
+
+ if (ch < 0) {
+ lookAhead = -1;
+ }
+
+ return lookAhead;
+ }
+
+ private static int readPassedEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn)
+ throws IOException {
+ int lookAhead = fIn.read();
+
+ if (lastCh == '\r' && lookAhead == '\n') {
+ bOut.write(lookAhead);
+ lookAhead = fIn.read();
+ }
+
+ return lookAhead;
+ }
+
+ private static int getLengthWithoutSeparator(byte[] line) {
+ int end = line.length - 1;
+
+ while (end >= 0 && isLineEnding(line[end])) {
+ end--;
+ }
+
+ return end + 1;
+ }
+
+ private static boolean isLineEnding(byte b) {
+ return b == '\r' || b == '\n';
+ }
+
+ private static int getLengthWithoutWhiteSpace(byte[] line) {
+ int end = line.length - 1;
+
+ while (end >= 0 && isWhiteSpace(line[end])) {
+ end--;
+ }
+
+ return end + 1;
+ }
+
+ private static boolean isWhiteSpace(byte b) {
+ return b == '\r' || b == '\n' || b == '\t' || b == ' ';
+ }
+
+ private static byte[] getLineSeparator() {
+ String nl = System.getProperty("line.separator");
+ byte[] nlBytes = new byte[nl.length()];
+
+ for (int i = 0; i != nlBytes.length; i++) {
+ nlBytes[i] = (byte) nl.charAt(i);
+ }
+
+ return nlBytes;
+ }
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpToX509.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpToX509.java
index 546a32473..e18eb0d6d 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpToX509.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpToX509.java
@@ -251,7 +251,7 @@ public class PgpToX509 {
}
X509Certificate selfSignedCert = createSelfSignedCert(
- pgpPubKey.getKey(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME), pgpPrivKey.getKey(),
+ pgpPubKey.getKey(Constants.BOUNCY_CASTLE_PROVIDER_NAME), pgpPrivKey.getKey(),
x509name, creationTime, validTo, subjAltNameURI);
return selfSignedCert;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/exception/NoAsymmetricEncryptionException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/exception/NoAsymmetricEncryptionException.java
new file mode 100644
index 000000000..92542fa35
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/exception/NoAsymmetricEncryptionException.java
@@ -0,0 +1,9 @@
+package org.sufficientlysecure.keychain.pgp.exception;
+
+public class NoAsymmetricEncryptionException extends Exception {
+ static final long serialVersionUID = 0xf812773343L;
+
+ public NoAsymmetricEncryptionException() {
+ super();
+ }
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralException.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralException.java
new file mode 100644
index 000000000..36c663727
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/exception/PgpGeneralException.java
@@ -0,0 +1,9 @@
+package org.sufficientlysecure.keychain.pgp.exception;
+
+public class PgpGeneralException extends Exception {
+ static final long serialVersionUID = 0xf812773342L;
+
+ public PgpGeneralException(String message) {
+ super(message);
+ }
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 27410d6e0..7ef61c15b 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -31,7 +31,7 @@ import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
@@ -320,11 +320,11 @@ public class ProviderHelper {
values.put(Keys.IS_MASTER_KEY, key.isMasterKey());
values.put(Keys.ALGORITHM, key.getAlgorithm());
values.put(Keys.KEY_SIZE, key.getBitStrength());
- values.put(Keys.CAN_SIGN, PgpHelper.isSigningKey(key));
- values.put(Keys.CAN_ENCRYPT, PgpHelper.isEncryptionKey(key));
+ values.put(Keys.CAN_SIGN, PgpKeyHelper.isSigningKey(key));
+ values.put(Keys.CAN_ENCRYPT, PgpKeyHelper.isEncryptionKey(key));
values.put(Keys.IS_REVOKED, key.isRevoked());
- values.put(Keys.CREATION, PgpHelper.getCreationDate(key).getTime() / 1000);
- Date expiryDate = PgpHelper.getExpiryDate(key);
+ values.put(Keys.CREATION, PgpKeyHelper.getCreationDate(key).getTime() / 1000);
+ Date expiryDate = PgpKeyHelper.getExpiryDate(key);
if (expiryDate != null) {
values.put(Keys.EXPIRY, expiryDate.getTime() / 1000);
}
@@ -375,7 +375,7 @@ public class ProviderHelper {
boolean has_private = true;
if (key.isMasterKey()) {
- if (PgpHelper.isSecretKeyPrivateEmpty(key)) {
+ if (PgpKeyHelper.isSecretKeyPrivateEmpty(key)) {
has_private = false;
}
}
@@ -384,12 +384,12 @@ public class ProviderHelper {
values.put(Keys.IS_MASTER_KEY, key.isMasterKey());
values.put(Keys.ALGORITHM, key.getPublicKey().getAlgorithm());
values.put(Keys.KEY_SIZE, key.getPublicKey().getBitStrength());
- values.put(Keys.CAN_CERTIFY, (PgpHelper.isCertificationKey(key) && has_private));
- values.put(Keys.CAN_SIGN, (PgpHelper.isSigningKey(key) && has_private));
- values.put(Keys.CAN_ENCRYPT, PgpHelper.isEncryptionKey(key));
+ values.put(Keys.CAN_CERTIFY, (PgpKeyHelper.isCertificationKey(key) && has_private));
+ values.put(Keys.CAN_SIGN, (PgpKeyHelper.isSigningKey(key) && has_private));
+ values.put(Keys.CAN_ENCRYPT, PgpKeyHelper.isEncryptionKey(key));
values.put(Keys.IS_REVOKED, key.getPublicKey().isRevoked());
- values.put(Keys.CREATION, PgpHelper.getCreationDate(key).getTime() / 1000);
- Date expiryDate = PgpHelper.getExpiryDate(key);
+ values.put(Keys.CREATION, PgpKeyHelper.getCreationDate(key).getTime() / 1000);
+ Date expiryDate = PgpKeyHelper.getExpiryDate(key);
if (expiryDate != null) {
values.put(Keys.EXPIRY, expiryDate.getTime() / 1000);
}
@@ -617,7 +617,7 @@ public class ProviderHelper {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ArmoredOutputStream aos = new ArmoredOutputStream(bos);
- aos.setHeader("Version", PgpMain.getFullVersion(context));
+ aos.setHeader("Version", PgpHelper.getFullVersion(context));
if (keyRing instanceof PGPSecretKeyRing) {
aos.write(((PGPSecretKeyRing) keyRing).getEncoded());
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index d7ddedce3..6b459b969 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -38,8 +38,11 @@ import org.sufficientlysecure.keychain.helper.FileHelper;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
-import org.sufficientlysecure.keychain.pgp.PgpMain.PgpGeneralException;
+import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpImportExport;
+import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
+import org.sufficientlysecure.keychain.pgp.PgpOperation;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.HkpKeyServer;
@@ -288,16 +291,15 @@ public class KeychainIntentService extends IntentService implements ProgressDial
// InputStream
InputStream in = getContentResolver().openInputStream(providerUri);
- inLength = PgpMain.getLengthOfStream(in);
+ inLength = PgpHelper.getLengthOfStream(in);
inputData = new InputData(in, inLength);
// OutputStream
try {
while (true) {
- streamFilename = PgpMain.generateRandomFilename(32);
+ streamFilename = PgpHelper.generateRandomFilename(32);
if (streamFilename == null) {
- throw new PgpMain.PgpGeneralException(
- "couldn't generate random file name");
+ throw new PgpGeneralException("couldn't generate random file name");
}
openFileInput(streamFilename).close();
}
@@ -309,31 +311,30 @@ public class KeychainIntentService extends IntentService implements ProgressDial
break;
default:
- throw new PgpMain.PgpGeneralException("No target choosen!");
+ throw new PgpGeneralException("No target choosen!");
}
/* Operation */
+ PgpOperation operation = new PgpOperation(this, this, inputData, outStream);
if (generateSignature) {
Log.d(Constants.TAG, "generating signature...");
- PgpMain.generateSignature(this, this, inputData, outStream, useAsciiArmor,
- false, secretKeyId, PassphraseCacheService.getCachedPassphrase(this,
- secretKeyId), Preferences.getPreferences(this)
- .getDefaultHashAlgorithm(), Preferences.getPreferences(this)
- .getForceV3Signatures());
- } else if (signOnly) {
- Log.d(Constants.TAG, "sign only...");
- PgpMain.signText(this, this, inputData, outStream, secretKeyId,
+ operation.generateSignature(useAsciiArmor, false, secretKeyId,
PassphraseCacheService.getCachedPassphrase(this, secretKeyId),
Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences
.getPreferences(this).getForceV3Signatures());
+ } else if (signOnly) {
+ Log.d(Constants.TAG, "sign only...");
+ operation.signText(secretKeyId, PassphraseCacheService.getCachedPassphrase(
+ this, secretKeyId), Preferences.getPreferences(this)
+ .getDefaultHashAlgorithm(), Preferences.getPreferences(this)
+ .getForceV3Signatures());
} else {
Log.d(Constants.TAG, "encrypt...");
- PgpMain.encryptAndSign(this, this, inputData, outStream, useAsciiArmor,
- compressionId, encryptionKeyIds, encryptionPassphrase, Preferences
- .getPreferences(this).getDefaultEncryptionAlgorithm(),
- secretKeyId,
- Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences
+ operation.encryptAndSign(useAsciiArmor, compressionId, encryptionKeyIds,
+ encryptionPassphrase, Preferences.getPreferences(this)
+ .getDefaultEncryptionAlgorithm(), secretKeyId, Preferences
+ .getPreferences(this).getDefaultHashAlgorithm(), Preferences
.getPreferences(this).getForceV3Signatures(),
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));
}
@@ -437,16 +438,15 @@ public class KeychainIntentService extends IntentService implements ProgressDial
// InputStream
InputStream in = getContentResolver().openInputStream(providerUri);
- inLength = PgpMain.getLengthOfStream(in);
+ inLength = PgpHelper.getLengthOfStream(in);
inputData = new InputData(in, inLength);
// OutputStream
try {
while (true) {
- streamFilename = PgpMain.generateRandomFilename(32);
+ streamFilename = PgpHelper.generateRandomFilename(32);
if (streamFilename == null) {
- throw new PgpMain.PgpGeneralException(
- "couldn't generate random file name");
+ throw new PgpGeneralException("couldn't generate random file name");
}
openFileInput(streamFilename).close();
}
@@ -458,7 +458,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial
break;
default:
- throw new PgpMain.PgpGeneralException("No target choosen!");
+ throw new PgpGeneralException("No target choosen!");
}
@@ -468,11 +468,11 @@ public class KeychainIntentService extends IntentService implements ProgressDial
// verifyText and decrypt returning additional resultData values for the
// verification of signatures
+ PgpOperation operation = new PgpOperation(this, this, inputData, outStream);
if (signedOnly) {
- resultData = PgpMain.verifyText(this, this, inputData, outStream,
- lookupUnknownKey);
+ resultData = operation.verifyText(lookupUnknownKey);
} else {
- resultData = PgpMain.decryptAndVerify(this, this, inputData, outStream,
+ resultData = operation.decryptAndVerify(
PassphraseCacheService.getCachedPassphrase(this, secretKeyId),
assumeSymmetricEncryption);
}
@@ -530,14 +530,15 @@ public class KeychainIntentService extends IntentService implements ProgressDial
ArrayList<Integer> keysUsages = data.getIntegerArrayList(SAVE_KEYRING_KEYS_USAGES);
long masterKeyId = data.getLong(SAVE_KEYRING_MASTER_KEY_ID);
+ PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
/* Operation */
if (!canSign) {
- PgpMain.changeSecretKeyPassphrase(this,
+ keyOperations.changeSecretKeyPassphrase(
ProviderHelper.getPGPSecretKeyRingByKeyId(this, masterKeyId),
- oldPassPhrase, newPassPhrase, this);
+ oldPassPhrase, newPassPhrase);
} else {
- PgpMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId,
- oldPassPhrase, newPassPhrase, this);
+ keyOperations.buildSecretKey(userIds, keys, keysUsages, masterKeyId,
+ oldPassPhrase, newPassPhrase);
}
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassPhrase);
@@ -559,7 +560,8 @@ public class KeychainIntentService extends IntentService implements ProgressDial
}
/* Operation */
- PGPSecretKeyRing newKeyRing = PgpMain.createKey(this, algorithm, keysize,
+ PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
+ PGPSecretKeyRing newKeyRing = keyOperations.createKey(algorithm, keysize,
passphrase, masterKey);
/* Output */
@@ -580,10 +582,12 @@ public class KeychainIntentService extends IntentService implements ProgressDial
String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
/* Operation */
- PGPSecretKeyRing masterKeyRing = PgpMain.createKey(this, Id.choice.algorithm.rsa,
+ PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
+
+ PGPSecretKeyRing masterKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa,
4096, passphrase, null);
- PGPSecretKeyRing subKeyRing = PgpMain.createKey(this, Id.choice.algorithm.rsa,
+ PGPSecretKeyRing subKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa,
4096, passphrase, masterKeyRing.getSecretKey());
/* Output */
@@ -606,13 +610,13 @@ public class KeychainIntentService extends IntentService implements ProgressDial
/* Operation */
try {
- PgpMain.deleteFileSecurely(this, this, new File(deleteFile));
+ PgpHelper.deleteFileSecurely(this, this, new File(deleteFile));
} catch (FileNotFoundException e) {
- throw new PgpMain.PgpGeneralException(getString(R.string.error_fileNotFound,
- deleteFile));
+ throw new PgpGeneralException(
+ getString(R.string.error_fileNotFound, deleteFile));
} catch (IOException e) {
- throw new PgpMain.PgpGeneralException(getString(
- R.string.error_fileDeleteFailed, deleteFile));
+ throw new PgpGeneralException(getString(R.string.error_fileDeleteFailed,
+ deleteFile));
}
/* Output */
@@ -661,7 +665,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial
}
Bundle resultData = new Bundle();
- resultData = PgpMain.importKeyRings(this, inputData, this);
+
+ PgpImportExport pgpImportExport = new PgpImportExport(this, this);
+ resultData = pgpImportExport.importKeyRings(inputData);
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
} catch (Exception e) {
@@ -708,8 +714,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial
}
Bundle resultData = new Bundle();
- resultData = PgpMain.exportKeyRings(this, keyRingMasterKeyIds, keyType, outStream,
- this);
+
+ PgpImportExport pgpImportExport = new PgpImportExport(this, this);
+ resultData = pgpImportExport
+ .exportKeyRings(keyRingMasterKeyIds, keyType, outStream);
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
} catch (Exception e) {
@@ -728,7 +736,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial
PGPPublicKeyRing keyring = ProviderHelper.getPGPPublicKeyRingByRowId(this,
keyRingRowId);
if (keyring != null) {
- boolean uploaded = PgpMain.uploadKeyRingToServer(server,
+ PgpImportExport pgpImportExport = new PgpImportExport(this, null);
+
+ boolean uploaded = pgpImportExport.uploadKeyRingToServer(server,
(PGPPublicKeyRing) keyring);
if (!uploaded) {
throw new PgpGeneralException("Unable to export key to selected server");
@@ -778,11 +788,13 @@ public class KeychainIntentService extends IntentService implements ProgressDial
String signaturePassPhrase = PassphraseCacheService.getCachedPassphrase(this,
masterKeyId);
- PGPPublicKeyRing signedPubKeyRing = PgpMain.signKey(this, masterKeyId, pubKeyId,
+ PgpKeyOperation keyOperation = new PgpKeyOperation(this, this);
+ PGPPublicKeyRing signedPubKeyRing = keyOperation.signKey(masterKeyId, pubKeyId,
signaturePassPhrase);
// store the signed key in our local cache
- int retval = PgpMain.storeKeyRingInCache(this, signedPubKeyRing);
+ PgpImportExport pgpImportExport = new PgpImportExport(this, null);
+ int retval = pgpImportExport.storeKeyRingInCache(signedPubKeyRing);
if (retval != Id.return_value.ok && retval != Id.return_value.updated) {
throw new PgpGeneralException("Failed to store signed key in local cache");
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index 466d087a2..f447b6d4f 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -29,7 +29,7 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import android.app.AlarmManager;
@@ -173,7 +173,7 @@ public class PassphraseCacheService extends Service {
if (keyRing == null) {
return null;
}
- PGPSecretKey masterKey = PgpHelper.getMasterKey(keyRing);
+ PGPSecretKey masterKey = PgpKeyHelper.getMasterKey(keyRing);
if (masterKey == null) {
return null;
}
@@ -210,7 +210,7 @@ public class PassphraseCacheService extends Service {
public static boolean hasPassphrase(Context context, long secretKeyId) {
// check if the key has no passphrase
try {
- PGPSecretKey secretKey = PgpHelper.getMasterKey(ProviderHelper
+ PGPSecretKey secretKey = PgpKeyHelper.getMasterKey(ProviderHelper
.getPGPSecretKeyRingByKeyId(context, secretKeyId));
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
"SC").build("".toCharArray());
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
index 8eb34b6e8..0f919fc67 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
@@ -26,7 +26,7 @@ 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.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.SelectSecretKeyActivity;
import org.sufficientlysecure.keychain.util.KeyValueSpinnerAdapter;
@@ -259,9 +259,9 @@ public class AppSettingsFragment extends Fragment {
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(
getActivity(), secretKeyId);
if (keyRing != null) {
- PGPSecretKey key = PgpHelper.getMasterKey(keyRing);
+ PGPSecretKey key = PgpKeyHelper.getMasterKey(keyRing);
if (key != null) {
- String userId = PgpHelper.getMainUserIdSafe(getActivity(), key);
+ String userId = PgpKeyHelper.getMainUserIdSafe(getActivity(), key);
String chunks[] = userId.split(" <", 2);
uid = chunks[0];
if (chunks.length > 1) {
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java
index 94e4004c6..4530179cb 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/ExtendedApiService.java
@@ -29,8 +29,7 @@ import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openssl.PEMWriter;
import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.PgpToX509;
import org.sufficientlysecure.keychain.util.Log;
@@ -53,13 +52,13 @@ public class ExtendedApiService extends RemoteService {
try {
long keyId = appSettings.getKeyId();
- PGPSecretKey pgpSecretKey = PgpHelper.getSigningKey(this, keyId);
+ PGPSecretKey pgpSecretKey = PgpKeyHelper.getSigningKey(this, keyId);
PasswordCallback pgpSecKeyPasswordCallBack = new PasswordCallback("pgp passphrase?",
false);
pgpPwdCallbackHandler.handle(new Callback[] { pgpSecKeyPasswordCallBack });
PGPPrivateKey pgpPrivKey = pgpSecretKey.extractPrivateKey(
- pgpSecKeyPasswordCallBack.getPassword(), PgpMain.BOUNCY_CASTLE_PROVIDER_NAME);
+ pgpSecKeyPasswordCallBack.getPassword(), Constants.BOUNCY_CASTLE_PROVIDER_NAME);
pgpSecKeyPasswordCallBack.clearPassword();
X509Certificate selfSignedCert = PgpToX509.createSelfSignedCert(pgpSecretKey,
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java
index 200675288..480b88ca5 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java
@@ -32,7 +32,10 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
+import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpOperation;
+import org.sufficientlysecure.keychain.pgp.exception.NoAsymmetricEncryptionException;
+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;
@@ -230,6 +233,7 @@ public class OpenPgpService extends RemoteService {
return;
}
+ PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream);
if (sign) {
String passphrase = getCachedPassphrase(appSettings.getKeyId());
if (passphrase == null) {
@@ -238,13 +242,11 @@ public class OpenPgpService extends RemoteService {
return;
}
- PgpMain.encryptAndSign(getContext(), null, inputData, outputStream, asciiArmor,
- appSettings.getCompression(), keyIds, null,
+ operation.encryptAndSign(asciiArmor, appSettings.getCompression(), keyIds, null,
appSettings.getEncryptionAlgorithm(), appSettings.getKeyId(),
appSettings.getHashAlgorithm(), true, passphrase);
} else {
- PgpMain.encryptAndSign(getContext(), null, inputData, outputStream, asciiArmor,
- appSettings.getCompression(), keyIds, null,
+ operation.encryptAndSign(asciiArmor, appSettings.getCompression(), keyIds, null,
appSettings.getEncryptionAlgorithm(), Id.key.none,
appSettings.getHashAlgorithm(), true, null);
}
@@ -286,9 +288,9 @@ public class OpenPgpService extends RemoteService {
return;
}
- PgpMain.signText(this, null, inputData, outputStream, appSettings.getKeyId(),
- passphrase, appSettings.getHashAlgorithm(), Preferences.getPreferences(this)
- .getForceV3Signatures());
+ PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream);
+ operation.signText(appSettings.getKeyId(), passphrase, appSettings.getHashAlgorithm(),
+ Preferences.getPreferences(this).getForceV3Signatures());
outputStream.close();
@@ -315,7 +317,7 @@ public class OpenPgpService extends RemoteService {
String message = new String(inputBytes);
Log.d(Constants.TAG, "in: " + message);
boolean signedOnly = false;
- Matcher matcher = PgpMain.PGP_MESSAGE.matcher(message);
+ Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(message);
if (matcher.matches()) {
Log.d(Constants.TAG, "PGP_MESSAGE matched");
message = matcher.group(1);
@@ -325,7 +327,7 @@ public class OpenPgpService extends RemoteService {
// overwrite inputBytes
inputBytes = message.getBytes();
} else {
- matcher = PgpMain.PGP_SIGNED_MESSAGE.matcher(message);
+ matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(message);
if (matcher.matches()) {
signedOnly = true;
Log.d(Constants.TAG, "PGP_SIGNED_MESSAGE matched");
@@ -368,19 +370,18 @@ public class OpenPgpService extends RemoteService {
// than 0.
inputStream2.mark(200);
}
- secretKeyId = PgpMain.getDecryptionKeyId(this, inputStream2);
+ secretKeyId = PgpHelper.getDecryptionKeyId(this, inputStream2);
if (secretKeyId == Id.key.none) {
- throw new PgpMain.PgpGeneralException(
- getString(R.string.error_noSecretKeyFound));
+ throw new PgpGeneralException(getString(R.string.error_noSecretKeyFound));
}
assumeSymmetricEncryption = false;
- } catch (PgpMain.NoAsymmetricEncryptionException e) {
+ } catch (NoAsymmetricEncryptionException e) {
if (inputStream2.markSupported()) {
inputStream2.reset();
}
secretKeyId = Id.key.symmetric;
- if (!PgpMain.hasSymmetricEncryption(this, inputStream2)) {
- throw new PgpMain.PgpGeneralException(
+ if (!PgpOperation.hasSymmetricEncryption(this, inputStream2)) {
+ throw new PgpGeneralException(
getString(R.string.error_noKnownEncryptionFound));
}
assumeSymmetricEncryption = true;
@@ -404,13 +405,13 @@ public class OpenPgpService extends RemoteService {
OutputStream outputStream = new ByteArrayOutputStream();
Bundle outputBundle;
+ PgpOperation operation = new PgpOperation(getContext(), null, inputData, outputStream);
if (signedOnly) {
// TODO: download missing keys from keyserver?
- outputBundle = PgpMain.verifyText(this, null, inputData, outputStream, false);
+ outputBundle = operation.verifyText(false);
} else {
// TODO: assume symmetric: callback to enter symmetric pass
- outputBundle = PgpMain.decryptAndVerify(this, null, inputData, outputStream,
- passphrase, assumeSymmetricEncryption);
+ outputBundle = operation.decryptAndVerify(passphrase, assumeSymmetricEncryption);
}
outputStream.close();
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
index cf64fb71d..5bf0684b1 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java
@@ -24,7 +24,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
@@ -316,7 +316,7 @@ public class RemoteServiceActivity extends SherlockFragmentActivity {
messenger, secretKeyId);
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
- } catch (PgpMain.PgpGeneralException e) {
+ } catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
// send message to handler to start encryption directly
returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java
index ad5b15744..136a53000 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java
@@ -33,7 +33,10 @@ import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.helper.FileHelper;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.pgp.PgpOperation;
+import org.sufficientlysecure.keychain.pgp.exception.NoAsymmetricEncryptionException;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
@@ -252,9 +255,9 @@ public class DecryptActivity extends SherlockFragmentActivity {
String data = "";
if (clipboardText != null) {
- Matcher matcher = PgpMain.PGP_MESSAGE.matcher(clipboardText);
+ Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(clipboardText);
if (!matcher.matches()) {
- matcher = PgpMain.PGP_SIGNED_MESSAGE.matcher(clipboardText);
+ matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(clipboardText);
}
if (matcher.matches()) {
data = matcher.group(1);
@@ -357,7 +360,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
*/
if (ACTION_DECRYPT.equals(action) && textData != null) {
Log.d(Constants.TAG, "textData null, matching text ...");
- Matcher matcher = PgpMain.PGP_MESSAGE.matcher(textData);
+ Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(textData);
if (matcher.matches()) {
Log.d(Constants.TAG, "PGP_MESSAGE matched");
textData = matcher.group(1);
@@ -365,7 +368,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
textData = textData.replaceAll("\\xa0", " ");
mMessage.setText(textData);
} else {
- matcher = PgpMain.PGP_SIGNED_MESSAGE.matcher(textData);
+ matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(textData);
if (matcher.matches()) {
Log.d(Constants.TAG, "PGP_SIGNED_MESSAGE matched");
textData = matcher.group(1);
@@ -478,7 +481,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
if (mDecryptTarget == Id.target.message) {
String messageData = mMessage.getText().toString();
- Matcher matcher = PgpMain.PGP_SIGNED_MESSAGE.matcher(messageData);
+ Matcher matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(messageData);
if (matcher.matches()) {
mSignedOnly = true;
decryptStart();
@@ -532,7 +535,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
messenger, mSecretKeyId);
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
- } catch (PgpMain.PgpGeneralException e) {
+ } catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
// send message to handler to start encryption directly
returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
@@ -578,20 +581,18 @@ public class DecryptActivity extends SherlockFragmentActivity {
inStream.mark(200); // should probably set this to the max size of two pgpF
// objects, if it even needs to be anything other than 0.
}
- mSecretKeyId = PgpMain.getDecryptionKeyId(this, inStream);
+ mSecretKeyId = PgpHelper.getDecryptionKeyId(this, inStream);
if (mSecretKeyId == Id.key.none) {
- throw new PgpMain.PgpGeneralException(
- getString(R.string.error_noSecretKeyFound));
+ throw new PgpGeneralException(getString(R.string.error_noSecretKeyFound));
}
mAssumeSymmetricEncryption = false;
- } catch (PgpMain.NoAsymmetricEncryptionException e) {
+ } catch (NoAsymmetricEncryptionException e) {
if (inStream.markSupported()) {
inStream.reset();
}
mSecretKeyId = Id.key.symmetric;
- if (!PgpMain.hasSymmetricEncryption(this, inStream)) {
- throw new PgpMain.PgpGeneralException(
- getString(R.string.error_noKnownEncryptionFound));
+ if (!PgpOperation.hasSymmetricEncryption(this, inStream)) {
+ throw new PgpGeneralException(getString(R.string.error_noKnownEncryptionFound));
}
mAssumeSymmetricEncryption = true;
}
@@ -771,8 +772,8 @@ public class DecryptActivity extends SherlockFragmentActivity {
.getString(KeychainIntentService.RESULT_SIGNATURE_USER_ID);
mSignatureKeyId = returnData
.getLong(KeychainIntentService.RESULT_SIGNATURE_KEY_ID);
- mUserIdRest
- .setText("id: " + PgpHelper.getSmallFingerPrint(mSignatureKeyId));
+ mUserIdRest.setText("id: "
+ + PgpKeyHelper.getSmallFingerPrint(mSignatureKeyId));
if (userId == null) {
userId = getResources().getString(R.string.unknownUserId);
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 0c1536d8d..0c7b90e16 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -28,12 +28,13 @@ import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
-import org.sufficientlysecure.keychain.pgp.PgpMain.PgpGeneralException;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
+import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
import org.sufficientlysecure.keychain.ui.widget.KeyEditor;
import org.sufficientlysecure.keychain.ui.widget.SectionView;
@@ -288,6 +289,38 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
}
+ private void showPassphraseDialog(final long masterKeyId, final boolean masterCanSign) {
+ // Message is received after passphrase is cached
+ final boolean mCanSign = masterCanSign;
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
+ String passPhrase = PassphraseCacheService.getCachedPassphrase(
+ EditKeyActivity.this, masterKeyId);
+ mCurrentPassPhrase = passPhrase;
+ finallyEdit(masterKeyId, masterCanSign);
+ } else {
+ finish();
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+
+ try {
+ PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
+ EditKeyActivity.this, messenger, masterKeyId);
+
+ passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
+ } catch (PgpGeneralException e) {
+ Log.d(Constants.TAG, "No passphrase for this secret key!");
+ // send message to handler to start encryption directly
+ returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
+ }
+ }
+
/**
* Handle intent action to edit existing key
*
@@ -299,7 +332,32 @@ public class EditKeyActivity extends SherlockFragmentActivity {
mActionBar.setTitle(R.string.title_editKey);
- mCurrentPassPhrase = PgpMain.getEditPassPhrase();
+ if (extras != null) {
+ if (extras.containsKey(EXTRA_MASTER_CAN_SIGN)) {
+ masterCanSign = extras.getBoolean(EXTRA_MASTER_CAN_SIGN);
+ }
+ if (extras.containsKey(EXTRA_MASTER_KEY_ID)) {
+ long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
+
+ // build layout in edit()
+ mBuildLayout = false;
+
+ String passPhrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
+ if (passPhrase == null) {
+ showPassphraseDialog(masterKeyId, masterCanSign);
+ } else {
+ // PgpMain.setEditPassPhrase(passPhrase);
+ mCurrentPassPhrase = passPhrase;
+
+ finallyEdit(masterKeyId, masterCanSign);
+ }
+
+ }
+ }
+ }
+
+ private void finallyEdit(final long masterKeyId, final boolean masterCanSign) {
+ // TODO: ???
if (mCurrentPassPhrase == null) {
mCurrentPassPhrase = "";
}
@@ -310,37 +368,28 @@ public class EditKeyActivity extends SherlockFragmentActivity {
mChangePassPhrase.setVisibility(View.GONE);
}
- if (extras != null) {
- if (extras.containsKey(EXTRA_MASTER_CAN_SIGN)) {
- masterCanSign = extras.getBoolean(EXTRA_MASTER_CAN_SIGN);
+ if (masterKeyId != 0) {
+ PGPSecretKey masterKey = null;
+ mKeyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this, masterKeyId);
+ if (mKeyRing != null) {
+ masterKey = PgpKeyHelper.getMasterKey(mKeyRing);
+ for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(mKeyRing.getSecretKeys())) {
+ mKeys.add(key);
+ mKeysUsages.add(-1); // get usage when view is created
+ }
+ } else {
+ Log.e(Constants.TAG, "Keyring not found with masterKeyId: " + masterKeyId);
+ Toast.makeText(this, R.string.error_noSecretKeyFound, Toast.LENGTH_LONG).show();
}
- if (extras.containsKey(EXTRA_MASTER_KEY_ID)) {
- long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
-
- if (masterKeyId != 0) {
- PGPSecretKey masterKey = null;
- mKeyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this, masterKeyId);
- if (mKeyRing != null) {
- masterKey = PgpHelper.getMasterKey(mKeyRing);
- for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(
- mKeyRing.getSecretKeys())) {
- mKeys.add(key);
- mKeysUsages.add(-1); // get usage when view is created
- }
- } else {
- Log.e(Constants.TAG, "Keyring not found with masterKeyId: " + masterKeyId);
- Toast.makeText(this, R.string.error_noSecretKeyFound, Toast.LENGTH_LONG)
- .show();
- }
- if (masterKey != null) {
- for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) {
- Log.d(Constants.TAG, "Added userId " + userId);
- mUserIds.add(userId);
- }
- }
+ if (masterKey != null) {
+ for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) {
+ Log.d(Constants.TAG, "Added userId " + userId);
+ mUserIds.add(userId);
}
}
}
+
+ buildLayout();
}
/**
@@ -424,7 +473,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
private void saveClicked() {
try {
if (!isPassphraseSet()) {
- throw new PgpMain.PgpGeneralException(this.getString(R.string.setAPassPhrase));
+ throw new PgpGeneralException(this.getString(R.string.setAPassPhrase));
}
// Send all information needed to service to edit key in other thread
@@ -480,7 +529,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
// start service with intent
startService(intent);
- } catch (PgpMain.PgpGeneralException e) {
+ } catch (PgpGeneralException e) {
Toast.makeText(this, getString(R.string.errorMessage, e.getMessage()),
Toast.LENGTH_SHORT).show();
}
@@ -497,8 +546,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
* @param userIdsView
* @return
*/
- private ArrayList<String> getUserIds(SectionView userIdsView)
- throws PgpMain.PgpGeneralException {
+ private ArrayList<String> getUserIds(SectionView userIdsView) throws PgpGeneralException {
ArrayList<String> userIds = new ArrayList<String>();
ViewGroup userIdEditors = userIdsView.getEditors();
@@ -510,13 +558,12 @@ public class EditKeyActivity extends SherlockFragmentActivity {
try {
userId = editor.getValue();
} catch (UserIdEditor.NoNameException e) {
- throw new PgpMain.PgpGeneralException(
- this.getString(R.string.error_userIdNeedsAName));
+ throw new PgpGeneralException(this.getString(R.string.error_userIdNeedsAName));
} catch (UserIdEditor.NoEmailException e) {
- throw new PgpMain.PgpGeneralException(
+ throw new PgpGeneralException(
this.getString(R.string.error_userIdNeedsAnEmailAddress));
} catch (UserIdEditor.InvalidEmailException e) {
- throw new PgpMain.PgpGeneralException(e.getMessage());
+ throw new PgpGeneralException(e.getMessage());
}
if (userId.equals("")) {
@@ -532,12 +579,11 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
if (userIds.size() == 0) {
- throw new PgpMain.PgpGeneralException(getString(R.string.error_keyNeedsAUserId));
+ throw new PgpGeneralException(getString(R.string.error_keyNeedsAUserId));
}
if (!gotMainUserId) {
- throw new PgpMain.PgpGeneralException(
- getString(R.string.error_mainUserIdMustNotBeEmpty));
+ throw new PgpGeneralException(getString(R.string.error_mainUserIdMustNotBeEmpty));
}
return userIds;
@@ -549,14 +595,13 @@ public class EditKeyActivity extends SherlockFragmentActivity {
* @param keysView
* @return
*/
- private ArrayList<PGPSecretKey> getKeys(SectionView keysView)
- throws PgpMain.PgpGeneralException {
+ private ArrayList<PGPSecretKey> getKeys(SectionView keysView) throws PgpGeneralException {
ArrayList<PGPSecretKey> keys = new ArrayList<PGPSecretKey>();
ViewGroup keyEditors = keysView.getEditors();
if (keyEditors.getChildCount() == 0) {
- throw new PgpMain.PgpGeneralException(getString(R.string.error_keyNeedsMasterKey));
+ throw new PgpGeneralException(getString(R.string.error_keyNeedsMasterKey));
}
for (int i = 0; i < keyEditors.getChildCount(); ++i) {
@@ -573,14 +618,13 @@ public class EditKeyActivity extends SherlockFragmentActivity {
* @param keysView
* @return
*/
- private ArrayList<Integer> getKeysUsages(SectionView keysView)
- throws PgpMain.PgpGeneralException {
+ private ArrayList<Integer> getKeysUsages(SectionView keysView) throws PgpGeneralException {
ArrayList<Integer> getKeysUsages = new ArrayList<Integer>();
ViewGroup keyEditors = keysView.getEditors();
if (keyEditors.getChildCount() == 0) {
- throw new PgpMain.PgpGeneralException(getString(R.string.error_keyNeedsMasterKey));
+ throw new PgpGeneralException(getString(R.string.error_keyNeedsMasterKey));
}
for (int i = 0; i < keyEditors.getChildCount(); ++i) {
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index 3e4b2bcfb..b9a58a210 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -31,8 +31,8 @@ import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.helper.FileHelper;
import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
@@ -302,9 +302,9 @@ public class EncryptActivity extends SherlockFragmentActivity {
preselectedSignatureKeyId);
PGPSecretKey masterKey = null;
if (keyRing != null) {
- masterKey = PgpHelper.getMasterKey(keyRing);
+ masterKey = PgpKeyHelper.getMasterKey(keyRing);
if (masterKey != null) {
- Vector<PGPSecretKey> signKeys = PgpHelper.getUsableSigningKeys(keyRing);
+ Vector<PGPSecretKey> signKeys = PgpKeyHelper.getUsableSigningKeys(keyRing);
if (signKeys.size() > 0) {
mSecretKeyId = masterKey.getKeyID();
}
@@ -321,11 +321,11 @@ public class EncryptActivity extends SherlockFragmentActivity {
if (keyRing == null) {
continue;
}
- masterKey = PgpHelper.getMasterKey(keyRing);
+ masterKey = PgpKeyHelper.getMasterKey(keyRing);
if (masterKey == null) {
continue;
}
- Vector<PGPPublicKey> encryptKeys = PgpHelper.getUsableEncryptKeys(keyRing);
+ Vector<PGPPublicKey> encryptKeys = PgpKeyHelper.getUsableEncryptKeys(keyRing);
if (encryptKeys.size() == 0) {
continue;
}
@@ -570,7 +570,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
EncryptActivity.this, messenger, mSecretKeyId);
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
- } catch (PgpMain.PgpGeneralException e) {
+ } catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
// send message to handler to start encryption directly
returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
@@ -914,9 +914,9 @@ public class EncryptActivity extends SherlockFragmentActivity {
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this,
mSecretKeyId);
if (keyRing != null) {
- PGPSecretKey key = PgpHelper.getMasterKey(keyRing);
+ PGPSecretKey key = PgpKeyHelper.getMasterKey(keyRing);
if (key != null) {
- String userId = PgpHelper.getMainUserIdSafe(this, key);
+ String userId = PgpKeyHelper.getMainUserIdSafe(this, key);
String chunks[] = userId.split(" <", 2);
uid = chunks[0];
if (chunks.length > 1) {
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
index 1b7d80b36..2e2c3cfcd 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
@@ -19,7 +19,7 @@ package org.sufficientlysecure.keychain.ui;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
@@ -97,7 +97,7 @@ public class KeyListPublicFragment extends KeyListFragment implements
PGPPublicKeyRing updateKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(
mKeyListActivity, keyRingRowId);
if (updateKeyRing != null) {
- updateKeyId = PgpHelper.getMasterKey(updateKeyRing).getKeyID();
+ updateKeyId = PgpKeyHelper.getMasterKey(updateKeyRing).getKeyID();
}
if (updateKeyId == 0) {
// this shouldn't happen
@@ -126,7 +126,7 @@ public class KeyListPublicFragment extends KeyListFragment implements
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(
mKeyListActivity, keyRingRowId);
if (signKeyRing != null) {
- keyId = PgpHelper.getMasterKey(signKeyRing).getKeyID();
+ keyId = PgpKeyHelper.getMasterKey(signKeyRing).getKeyID();
}
if (keyId == 0) {
// this shouldn't happen
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
index 84b3d6689..68e3be5df 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
@@ -19,20 +19,13 @@ package org.sufficientlysecure.keychain.ui;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
-import org.sufficientlysecure.keychain.service.PassphraseCacheService;
-import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
-import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.R;
-import com.actionbarsherlock.view.Menu;
-import com.actionbarsherlock.view.MenuItem;
-
import android.content.Intent;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
+
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuItem;
public class KeyListSecretActivity extends KeyListActivity {
@@ -77,48 +70,7 @@ public class KeyListSecretActivity extends KeyListActivity {
}
}
- public void checkPassPhraseAndEdit(long masterKeyId, boolean masterCanSign) {
- String passPhrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
- if (passPhrase == null) {
- showPassphraseDialog(masterKeyId, masterCanSign);
- } else {
- PgpMain.setEditPassPhrase(passPhrase);
- editKey(masterKeyId, masterCanSign);
- }
- }
-
- private void showPassphraseDialog(final long masterKeyId, boolean masterCanSign) {
- // Message is received after passphrase is cached
- final boolean mCanSign = masterCanSign;
- Handler returnHandler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
- String passPhrase = PassphraseCacheService.getCachedPassphrase(
- KeyListSecretActivity.this, masterKeyId);
- PgpMain.setEditPassPhrase(passPhrase);
- editKey(masterKeyId, mCanSign);
- }
- }
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(returnHandler);
-
- try {
- PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
- KeyListSecretActivity.this, messenger, masterKeyId);
-
- passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
- } catch (PgpMain.PgpGeneralException e) {
- Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
- // send message to handler to start encryption directly
- returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
- }
- }
-
private void createKey() {
- PgpMain.setEditPassPhrase("");
Intent intent = new Intent(this, EditKeyActivity.class);
intent.setAction(EditKeyActivity.ACTION_CREATE_KEY);
intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true);
@@ -127,13 +79,12 @@ public class KeyListSecretActivity extends KeyListActivity {
}
private void createKeyExpert() {
- PgpMain.setEditPassPhrase("");
Intent intent = new Intent(this, EditKeyActivity.class);
intent.setAction(EditKeyActivity.ACTION_CREATE_KEY);
startActivityForResult(intent, 0);
}
- private void editKey(long masterKeyId, boolean masterCanSign) {
+ void editKey(long masterKeyId, boolean masterCanSign) {
Intent intent = new Intent(this, EditKeyActivity.class);
intent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
intent.putExtra(EditKeyActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
index 2a6ce2808..f8d02b7b3 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
@@ -91,7 +91,7 @@ public class KeyListSecretFragment extends KeyListFragment implements
switch (item.getItemId()) {
case Id.menu.edit:
- mKeyListSecretActivity.checkPassPhraseAndEdit(masterKeyId, masterCanSign);
+ mKeyListSecretActivity.editKey(masterKeyId, masterCanSign);
return true;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java
index 458603f84..22f4b65fe 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java
@@ -23,7 +23,7 @@ import java.util.List;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.util.Log;
@@ -140,7 +140,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
if (ACTION_LOOK_UP_KEY_ID.equals(action) || ACTION_LOOK_UP_KEY_ID_AND_RETURN.equals(action)) {
long keyId = intent.getLongExtra(EXTRA_KEY_ID, 0);
if (keyId != 0) {
- String query = "0x" + PgpHelper.keyToHex(keyId);
+ String query = "0x" + PgpKeyHelper.keyToHex(keyId);
mQuery.setText(query);
search(query);
}
@@ -308,7 +308,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
mainUserId.setText(userId);
}
- keyId.setText(PgpHelper.getSmallFingerPrint(keyInfo.keyId));
+ keyId.setText(PgpKeyHelper.getSmallFingerPrint(keyInfo.keyId));
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
index 7e7af7feb..83dcce14b 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
@@ -22,18 +22,15 @@ import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSignature;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.R;
-
-import com.actionbarsherlock.app.ActionBar;
-import com.actionbarsherlock.app.SherlockFragmentActivity;
import android.app.ProgressDialog;
import android.content.Intent;
@@ -51,6 +48,9 @@ import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Spinner;
import android.widget.Toast;
+import com.actionbarsherlock.app.ActionBar;
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+
/**
* gpg --sign-key
*
@@ -144,7 +144,7 @@ public class SignKeyActivity extends SherlockFragmentActivity {
messenger, secretKeyId);
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
- } catch (PgpMain.PgpGeneralException e) {
+ } catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
// send message to handler to start encryption directly
returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
index a4a88fcdf..87a08a68f 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
@@ -21,7 +21,7 @@ import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.R;
@@ -79,11 +79,11 @@ public class DeleteKeyDialogFragment extends DialogFragment {
if (keyType == Id.type.public_key) {
PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByRowId(activity,
deleteKeyRingRowId);
- userId = PgpHelper.getMainUserIdSafe(activity, PgpHelper.getMasterKey(keyRing));
+ userId = PgpKeyHelper.getMainUserIdSafe(activity, PgpKeyHelper.getMasterKey(keyRing));
} else {
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByRowId(activity,
deleteKeyRingRowId);
- userId = PgpHelper.getMainUserIdSafe(activity, PgpHelper.getMasterKey(keyRing));
+ userId = PgpKeyHelper.getMainUserIdSafe(activity, PgpKeyHelper.getMasterKey(keyRing));
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/LookupUnknownKeyDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/LookupUnknownKeyDialogFragment.java
index eebda1799..b50ec5f0d 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/LookupUnknownKeyDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/LookupUnknownKeyDialogFragment.java
@@ -19,7 +19,7 @@ package org.sufficientlysecure.keychain.ui.dialog;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.ui.KeyServerQueryActivity;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.R;
@@ -79,7 +79,7 @@ public class LookupUnknownKeyDialogFragment extends DialogFragment {
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.title_unknownSignatureKey);
alert.setMessage(getString(R.string.lookupUnknownKey,
- PgpHelper.getSmallFingerPrint(unknownKeyId)));
+ PgpKeyHelper.getSmallFingerPrint(unknownKeyId)));
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
index c3a3dee8e..61a9a4366 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
@@ -24,13 +24,12 @@ import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
-import org.sufficientlysecure.keychain.pgp.PgpMain.PgpGeneralException;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.R;
import android.app.Activity;
import android.app.AlertDialog;
@@ -80,7 +79,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
// check if secret key has a passphrase
if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) {
if (!PassphraseCacheService.hasPassphrase(context, secretKeyId)) {
- throw new PgpMain.PgpGeneralException("No passphrase! No passphrase dialog needed!");
+ throw new PgpGeneralException("No passphrase! No passphrase dialog needed!");
}
}
@@ -119,7 +118,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
alert.setMessage(R.string.passPhraseForSymmetricEncryption);
} else {
// TODO: by master key id???
- secretKey = PgpHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByKeyId(activity,
+ secretKey = PgpKeyHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByKeyId(activity,
secretKeyId));
// secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
@@ -135,7 +134,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
canKB = false;
return alert.create();
}
- String userId = PgpHelper.getMainUserIdSafe(activity, secretKey);
+ String userId = PgpKeyHelper.getMainUserIdSafe(activity, secretKey);
Log.d(Constants.TAG, "User id: '" + userId + "'");
alert.setMessage(getString(R.string.passPhraseFor, userId));
@@ -163,7 +162,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
if (clickSecretKey != null) { // check again for loop
try {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
- .setProvider(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
passPhrase.toCharArray());
PGPPrivateKey testKey = clickSecretKey
.extractPrivateKey(keyDecryptor);
@@ -176,7 +175,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
sendMessageToHandler(MESSAGE_CANCEL);
return;
} else {
- clickSecretKey = PgpHelper.getKeyNum(ProviderHelper
+ clickSecretKey = PgpKeyHelper.getKeyNum(ProviderHelper
.getPGPSecretKeyRingByKeyId(activity, secretKeyId),
curKeyIndex);
curKeyIndex++; // does post-increment work like C?
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ImportKeysListLoader.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ImportKeysListLoader.java
index 42c5ddef7..45f23d443 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ImportKeysListLoader.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/ImportKeysListLoader.java
@@ -32,7 +32,7 @@ import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPUtil;
import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
@@ -142,13 +142,13 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<Map<String, Strin
}
private void addToData(PGPKeyRing keyring) {
- String userId = PgpHelper.getMainUserId(keyring.getPublicKey());
+ String userId = PgpKeyHelper.getMainUserId(keyring.getPublicKey());
if (keyring instanceof PGPSecretKeyRing) {
userId = mContext.getString(R.string.secretKeyring) + " " + userId;
}
- String fingerprint = PgpHelper.convertFingerprintToHex(keyring.getPublicKey()
+ String fingerprint = PgpKeyHelper.convertFingerprintToHex(keyring.getPublicKey()
.getFingerprint());
Map<String, String> attrs = new HashMap<String, String>();
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
index 729123e13..27e5a7cc6 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
@@ -19,7 +19,7 @@ package org.sufficientlysecure.keychain.ui.widget;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.util.Choice;
import org.sufficientlysecure.keychain.R;
@@ -151,9 +151,9 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
mDeleteButton.setVisibility(View.INVISIBLE);
}
- mAlgorithm.setText(PgpHelper.getAlgorithmInfo(key));
- String keyId1Str = PgpHelper.getSmallFingerPrint(key.getKeyID());
- String keyId2Str = PgpHelper.getSmallFingerPrint(key.getKeyID() >> 32);
+ mAlgorithm.setText(PgpKeyHelper.getAlgorithmInfo(key));
+ String keyId1Str = PgpKeyHelper.getSmallFingerPrint(key.getKeyID());
+ String keyId2Str = PgpKeyHelper.getSmallFingerPrint(key.getKeyID() >> 32);
mKeyId.setText(keyId1Str + " " + keyId2Str);
Vector<Choice> choices = new Vector<Choice>();
@@ -179,8 +179,8 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
// Set value in choice dropdown to key
int selectId = 0;
- if (PgpHelper.isEncryptionKey(key)) {
- if (PgpHelper.isSigningKey(key)) {
+ if (PgpKeyHelper.isEncryptionKey(key)) {
+ if (PgpKeyHelper.isSigningKey(key)) {
selectId = Id.choice.usage.sign_and_encrypt;
} else {
selectId = Id.choice.usage.encrypt_only;
@@ -203,14 +203,14 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
}
GregorianCalendar cal = new GregorianCalendar();
- cal.setTime(PgpHelper.getCreationDate(key));
+ cal.setTime(PgpKeyHelper.getCreationDate(key));
mCreationDate.setText(DateFormat.getDateInstance().format(cal.getTime()));
cal = new GregorianCalendar();
- Date date = PgpHelper.getExpiryDate(key);
+ Date date = PgpKeyHelper.getExpiryDate(key);
if (date == null) {
setExpiryDate(null);
} else {
- cal.setTime(PgpHelper.getExpiryDate(key));
+ cal.setTime(PgpKeyHelper.getExpiryDate(key));
setExpiryDate(cal);
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java
index e41db4f2f..989036a7f 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyListAdapter.java
@@ -19,7 +19,7 @@ package org.sufficientlysecure.keychain.ui.widget;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.OtherHelper;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.util.Log;
@@ -117,7 +117,7 @@ public class KeyListAdapter extends CursorTreeAdapter {
keyLayout.setVisibility(View.GONE);
userIdLayout.setVisibility(View.VISIBLE);
- String fingerprint = PgpHelper.getFingerPrint(context,
+ String fingerprint = PgpKeyHelper.getFingerPrint(context,
cursor.getLong(cursor.getColumnIndex(Keys.KEY_ID)));
fingerprint = fingerprint.replace(" ", "\n");
@@ -132,9 +132,9 @@ public class KeyListAdapter extends CursorTreeAdapter {
keyLayout.setVisibility(View.VISIBLE);
userIdLayout.setVisibility(View.GONE);
- String keyIdStr = PgpHelper.getSmallFingerPrint(cursor.getLong(cursor
+ String keyIdStr = PgpKeyHelper.getSmallFingerPrint(cursor.getLong(cursor
.getColumnIndex(Keys.KEY_ID)));
- String algorithmStr = PgpHelper.getAlgorithmInfo(
+ String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
cursor.getInt(cursor.getColumnIndex(Keys.ALGORITHM)),
cursor.getInt(cursor.getColumnIndex(Keys.KEY_SIZE)));
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java
index b6d2949d3..0b2b612a5 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SelectKeyCursorAdapter.java
@@ -19,7 +19,7 @@ package org.sufficientlysecure.keychain.ui.widget;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.helper.OtherHelper;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.R;
@@ -87,7 +87,7 @@ public class SelectKeyCursorAdapter extends CursorAdapter {
}
long masterKeyId = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID));
- keyId.setText(PgpHelper.getSmallFingerPrint(masterKeyId));
+ keyId.setText(PgpKeyHelper.getSmallFingerPrint(masterKeyId));
if (mainUserIdRest.getText().length() == 0) {
mainUserIdRest.setVisibility(View.GONE);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/HkpKeyServer.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/HkpKeyServer.java
index c414dfd86..ff69aa264 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/HkpKeyServer.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/HkpKeyServer.java
@@ -44,7 +44,7 @@ import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
-import org.sufficientlysecure.keychain.pgp.PgpMain;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import android.text.Html;
@@ -179,8 +179,8 @@ public class HkpKeyServer extends KeyServer {
KeyInfo info = new KeyInfo();
info.size = Integer.parseInt(matcher.group(1));
info.algorithm = matcher.group(2);
- info.keyId = PgpHelper.keyFromHex(matcher.group(3));
- info.fingerPrint = PgpHelper.getSmallFingerPrint(info.keyId);
+ info.keyId = PgpKeyHelper.keyFromHex(matcher.group(3));
+ info.fingerPrint = PgpKeyHelper.getSmallFingerPrint(info.keyId);
String chunks[] = matcher.group(4).split("-");
info.date = new GregorianCalendar(Integer.parseInt(chunks[0]),
Integer.parseInt(chunks[1]), Integer.parseInt(chunks[2])).getTime();
@@ -211,7 +211,7 @@ public class HkpKeyServer extends KeyServer {
HttpClient client = new DefaultHttpClient();
try {
HttpGet get = new HttpGet("http://" + mHost + ":" + mPort
- + "/pks/lookup?op=get&search=0x" + PgpHelper.keyToHex(keyId));
+ + "/pks/lookup?op=get&search=0x" + PgpKeyHelper.keyToHex(keyId));
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
@@ -221,7 +221,7 @@ public class HkpKeyServer extends KeyServer {
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
String data = readAll(is, EntityUtils.getContentCharSet(entity));
- Matcher matcher = PgpMain.PGP_PUBLIC_KEY.matcher(data);
+ Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(data);
if (matcher.find()) {
return matcher.group(1);
}