diff --git a/README.md b/README.md index fe072337d..e8d08a0f3 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,6 @@ Fork APG and do a merge request. I will merge your changes back into the main pr 1. New -> Android Project -> Create project from existing source, choose com_actionbarsherlock 2. New -> Android Project -> Create project from existing source, choose org_apg 3. Add com_actionbarsherlock as Android Lib (Properties of org_apg -> Android -> Library -> add) -4. Optional (As of Android Tools r17 the libraries are automatically added from the libs folder): Add Java libs (Properties of org_apg -> Java Build Path -> Libraries -> add all libraries from libs folder in org_apg) 5. Now APG+ can be build # Libraries @@ -35,7 +34,7 @@ Fork APG and do a merge request. I will merge your changes back into the main pr The Libraries are provided in the git repository. * ActionBarSherlock to provide an ActionBar for Android < 3.0 -* Spongy Castle as the main Crypto Lib +* Spongy Castle Crypto Lib (Android version of Bouncy Castle) * android-support-v4.jar: Compatibility Lib * barcodescanner-android-integration-supportv4.jar: Barcode Scanner Integration diff --git a/org_apg/libs/sc-bzip2-1.47.0.2.jar b/org_apg/libs/sc-bzip2-1.47.0.2.jar new file mode 100644 index 000000000..3bc42f30e Binary files /dev/null and b/org_apg/libs/sc-bzip2-1.47.0.2.jar differ diff --git a/org_apg/libs/scprov-jdk15on-1.47.0.1.jar b/org_apg/libs/sc-light-jdk15on-1.47.0.2.jar similarity index 55% rename from org_apg/libs/scprov-jdk15on-1.47.0.1.jar rename to org_apg/libs/sc-light-jdk15on-1.47.0.2.jar index 4fca4fed3..7cdbf856e 100644 Binary files a/org_apg/libs/scprov-jdk15on-1.47.0.1.jar and b/org_apg/libs/sc-light-jdk15on-1.47.0.2.jar differ diff --git a/org_apg/libs/scpg-jdk15on-1.47.0.1.jar b/org_apg/libs/scpg-jdk15on-1.47.0.2.jar similarity index 89% rename from org_apg/libs/scpg-jdk15on-1.47.0.1.jar rename to org_apg/libs/scpg-jdk15on-1.47.0.2.jar index dc7f635c8..f290334d8 100644 Binary files a/org_apg/libs/scpg-jdk15on-1.47.0.1.jar and b/org_apg/libs/scpg-jdk15on-1.47.0.2.jar differ diff --git a/org_apg/libs/scprov-jdk15on-1.47.0.2.jar b/org_apg/libs/scprov-jdk15on-1.47.0.2.jar new file mode 100644 index 000000000..221a36b29 Binary files /dev/null and b/org_apg/libs/scprov-jdk15on-1.47.0.2.jar differ diff --git a/org_apg/src/org/thialfihar/android/apg/deprecated/ApgService2.java b/org_apg/src/org/thialfihar/android/apg/deprecated/ApgService2.java index 955d9c8ff..b13110f50 100644 --- a/org_apg/src/org/thialfihar/android/apg/deprecated/ApgService2.java +++ b/org_apg/src/org/thialfihar/android/apg/deprecated/ApgService2.java @@ -32,6 +32,7 @@ import org.thialfihar.android.apg.deprecated.IApgService2.Stub; import org.thialfihar.android.apg.Id.database; import org.thialfihar.android.apg.R.string; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.Preferences; import org.thialfihar.android.apg.passphrase.PassphraseCacheService; import org.thialfihar.android.apg.provider.KeyRings; @@ -204,7 +205,7 @@ public class ApgService2 extends PassphraseCacheService { typeWhere = KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?"; typeVal = new String[] { "" + pParams.get("key_type") }; } - return qb.query(PGPHelper.getDatabase().db(), (String[]) pParams.get("columns"), typeWhere, + return qb.query(PGPMain.getDatabase().db(), (String[]) pParams.get("columns"), typeWhere, typeVal, null, null, orderBy); } @@ -427,7 +428,7 @@ public class ApgService2 extends PassphraseCacheService { } private boolean prepareArgs(String pCall, Bundle pArgs, Bundle pReturn) { - PGPHelper.initialize(getBaseContext()); + PGPMain.initialize(getBaseContext()); /* add default return values for all functions */ addDefaultReturns(pReturn); @@ -493,7 +494,7 @@ public class ApgService2 extends PassphraseCacheService { if (LOCAL_LOGV) Log.v(TAG, "About to encrypt"); try { - PGPHelper.encrypt(getBaseContext(), // context + PGPMain.encrypt(getBaseContext(), // context in, // input stream out, // output stream pArgs.getBoolean(arg.ARMORED_OUTPUT.name()), // ARMORED_OUTPUT @@ -625,7 +626,7 @@ public class ApgService2 extends PassphraseCacheService { if (LOCAL_LOGV) Log.v(TAG, "About to decrypt"); try { - PGPHelper.decrypt(getBaseContext(), in, out, passphrase, null, // progress + PGPMain.decrypt(getBaseContext(), in, out, passphrase, null, // progress pArgs.getString(arg.SYMMETRIC_PASSPHRASE.name()) != null // symmetric ); } catch (Exception e) { diff --git a/org_apg/src/org/thialfihar/android/apg/deprecated/GeneralActivity.java b/org_apg/src/org/thialfihar/android/apg/deprecated/GeneralActivity.java deleted file mode 100644 index 7a3d99232..000000000 --- a/org_apg/src/org/thialfihar/android/apg/deprecated/GeneralActivity.java +++ /dev/null @@ -1,196 +0,0 @@ -///* -// * Licensed under the Apache License, Version 2.0 (the "License"); -// * you may not use this file except in compliance with the License. -// * You may obtain a copy of the License at -// * -// * http://www.apache.org/licenses/LICENSE-2.0 -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the License is distributed on an "AS IS" BASIS, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the License for the specific language governing permissions and -// * limitations under the License. -// */ -// -//package org.thialfihar.android.apg.deprecated; -// -//import java.io.ByteArrayInputStream; -//import java.io.FileNotFoundException; -//import java.io.IOException; -//import java.io.InputStream; -//import java.util.Vector; -// -//import org.thialfihar.android.apg.R; -//import org.thialfihar.android.apg.Id; -//import org.thialfihar.android.apg.helper.PGPHelper; -//import org.thialfihar.android.apg.ui.BaseActivity; -//import org.thialfihar.android.apg.ui.DecryptActivity; -//import org.thialfihar.android.apg.ui.EncryptActivity; -//import org.thialfihar.android.apg.ui.PublicKeyListActivity; -//import org.thialfihar.android.apg.ui.SecretKeyListActivity; -//import org.thialfihar.android.apg.util.Choice; -// -//import android.content.Intent; -//import android.net.Uri; -//import android.os.Bundle; -//import android.view.View; -//import android.view.View.OnClickListener; -//import android.widget.AdapterView; -//import android.widget.AdapterView.OnItemClickListener; -//import android.widget.ArrayAdapter; -//import android.widget.Button; -//import android.widget.ListView; -//import android.widget.Toast; -// -//public class GeneralActivity extends BaseActivity { -// private Intent mIntent; -// private ArrayAdapter mAdapter; -// private ListView mList; -// private Button mCancelButton; -// private String mDataString; -// private Uri mDataUri; -// -// @Override -// protected void onCreate(Bundle savedInstanceState) { -// super.onCreate(savedInstanceState); -// -// setContentView(R.layout.general); -// -// mIntent = getIntent(); -// -// InputStream inStream = null; -// { -// String data = mIntent.getStringExtra(Intent.EXTRA_TEXT); -// if (data != null) { -// mDataString = data; -// inStream = new ByteArrayInputStream(data.getBytes()); -// } -// } -// -// if (inStream == null) { -// Uri data = mIntent.getData(); -// if (data != null) { -// mDataUri = data; -// try { -// inStream = getContentResolver().openInputStream(data); -// } catch (FileNotFoundException e) { -// // didn't work -// Toast.makeText(this, "failed to open stream", Toast.LENGTH_SHORT).show(); -// } -// } -// } -// -// if (inStream == null) { -// Toast.makeText(this, "no data found", Toast.LENGTH_SHORT).show(); -// finish(); -// return; -// } -// -// int contentType = Id.content.unknown; -// try { -// contentType = PGPHelper.getStreamContent(this, inStream); -// inStream.close(); -// } catch (IOException e) { -// // just means that there's no PGP data in there -// } -// -// mList = (ListView) findViewById(R.id.options); -// Vector choices = new Vector(); -// -// if (contentType == Id.content.keys) { -// choices.add(new Choice(Id.choice.action.import_public, -// getString(R.string.action_importPublic))); -// choices.add(new Choice(Id.choice.action.import_secret, -// getString(R.string.action_importSecret))); -// } -// -// if (contentType == Id.content.encrypted_data) { -// choices.add(new Choice(Id.choice.action.decrypt, getString(R.string.action_decrypt))); -// } -// -// if (contentType == Id.content.unknown) { -// choices.add(new Choice(Id.choice.action.encrypt, getString(R.string.action_encrypt))); -// } -// -// mAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, choices); -// mList.setAdapter(mAdapter); -// -// mList.setOnItemClickListener(new OnItemClickListener() { -// public void onItemClick(AdapterView arg0, View arg1, int arg2, long arg3) { -// clicked(mAdapter.getItem(arg2).getId()); -// } -// }); -// -// mCancelButton = (Button) findViewById(R.id.btn_cancel); -// mCancelButton.setOnClickListener(new OnClickListener() { -// public void onClick(View v) { -// GeneralActivity.this.finish(); -// } -// }); -// -// if (choices.size() == 1) { -// clicked(choices.get(0).getId()); -// } -// } -// -// private void clicked(int id) { -// Intent intent = new Intent(); -// switch (id) { -// case Id.choice.action.encrypt: { -// intent.setClass(this, EncryptActivity.class); -// if (mDataString != null) { -// intent.setAction(EncryptActivity.ENCRYPT); -// intent.putExtra(PGPHelper.EXTRA_TEXT, mDataString); -// } else if (mDataUri != null) { -// intent.setAction(EncryptActivity.ENCRYPT_FILE); -// intent.setDataAndType(mDataUri, mIntent.getType()); -// } -// -// break; -// } -// -// case Id.choice.action.decrypt: { -// intent.setClass(this, DecryptActivity.class); -// if (mDataString != null) { -// intent.setAction(DecryptActivity.DECRYPT); -// intent.putExtra(PGPHelper.EXTRA_TEXT, mDataString); -// } else if (mDataUri != null) { -// intent.setAction(DecryptActivity.DECRYPT_FILE); -// intent.setDataAndType(mDataUri, mIntent.getType()); -// } -// -// break; -// } -// -// case Id.choice.action.import_public: { -// intent.setClass(this, PublicKeyListActivity.class); -// intent.setAction(PublicKeyListActivity.IMPORT); -// if (mDataString != null) { -// intent.putExtra(PGPHelper.EXTRA_TEXT, mDataString); -// } else if (mDataUri != null) { -// intent.setDataAndType(mDataUri, mIntent.getType()); -// } -// break; -// } -// -// case Id.choice.action.import_secret: { -// intent.setClass(this, SecretKeyListActivity.class); -// intent.setAction(SecretKeyListActivity.IMPORT); -// if (mDataString != null) { -// intent.putExtra(PGPHelper.EXTRA_TEXT, mDataString); -// } else if (mDataUri != null) { -// intent.setDataAndType(mDataUri, mIntent.getType()); -// } -// break; -// } -// -// default: { -// // shouldn't happen -// return; -// } -// } -// -// startActivity(intent); -// finish(); -// } -//} diff --git a/org_apg/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java b/org_apg/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java index a406bf6e8..f1bd530a8 100644 --- a/org_apg/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java +++ b/org_apg/src/org/thialfihar/android/apg/helper/PGPConversionHelper.java @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.Vector; import org.spongycastle.openpgp.PGPObjectFactory; +import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.Constants; @@ -54,7 +55,7 @@ public class PGPConversionHelper { } /** - * Convert from byte[] to ArrayList + * Convert from byte[] to PGPSecretKeyRing * * @param keysBytes * @return @@ -72,6 +73,26 @@ public class PGPConversionHelper { return keyRing; } + + /** + * Convert from byte[] to PGPPublicKeyRing + * + * @param keysBytes + * @return + */ + public static PGPPublicKeyRing BytesToPGPPublicKeyRing(byte[] keysBytes) { + PGPObjectFactory factory = new PGPObjectFactory(keysBytes); + PGPPublicKeyRing keyRing = null; + try { + if ((keyRing = (PGPPublicKeyRing) factory.nextObject()) == null) { + Log.e(Constants.TAG, "No keys given!"); + } + } catch (IOException e) { + e.printStackTrace(); + } + + return keyRing; + } public static ArrayList BytesToPGPSecretKeyList(byte[] keysBytes) { PGPSecretKeyRing keyRing = BytesToPGPSecretKeyRing(keysBytes); diff --git a/org_apg/src/org/thialfihar/android/apg/helper/PGPHelper.java b/org_apg/src/org/thialfihar/android/apg/helper/PGPHelper.java index ffd8bbea6..0b6191f67 100644 --- a/org_apg/src/org/thialfihar/android/apg/helper/PGPHelper.java +++ b/org_apg/src/org/thialfihar/android/apg/helper/PGPHelper.java @@ -17,587 +17,29 @@ package org.thialfihar.android.apg.helper; -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 java.io.IOException; +import java.io.InputStream; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Vector; + 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.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.thialfihar.android.apg.Id.choice; -import org.thialfihar.android.apg.Id.content; -import org.thialfihar.android.apg.Id.database; -import org.thialfihar.android.apg.Id.key; -import org.thialfihar.android.apg.Id.return_value; -import org.thialfihar.android.apg.Id.type; -import org.thialfihar.android.apg.Id.choice.algorithm; -import org.thialfihar.android.apg.Id.choice.compression; -import org.thialfihar.android.apg.Id.choice.usage; -import org.thialfihar.android.apg.R.string; -import org.thialfihar.android.apg.passphrase.CachedPassPhrase; -import org.thialfihar.android.apg.provider.DataProvider; -import org.thialfihar.android.apg.provider.Database; -import org.thialfihar.android.apg.provider.KeyRings; -import org.thialfihar.android.apg.provider.Keys; -import org.thialfihar.android.apg.provider.UserIds; -import org.thialfihar.android.apg.service.ApgService; -import org.thialfihar.android.apg.ui.BaseActivity; -import org.thialfihar.android.apg.ui.widget.KeyEditor; -import org.thialfihar.android.apg.ui.widget.SectionView; -import org.thialfihar.android.apg.ui.widget.UserIdEditor; -import org.thialfihar.android.apg.util.HkpKeyServer; -import org.thialfihar.android.apg.util.InputData; -import org.thialfihar.android.apg.util.IterableIterator; -import org.thialfihar.android.apg.util.KeyServer; -import org.thialfihar.android.apg.util.PositionAwareInputStream; -import org.thialfihar.android.apg.util.Primes; -import org.thialfihar.android.apg.util.KeyServer.AddKeyException; -import org.thialfihar.android.apg.Constants; -import org.thialfihar.android.apg.Id; -import org.thialfihar.android.apg.ProgressDialogUpdater; import org.thialfihar.android.apg.R; +import org.thialfihar.android.apg.util.IterableIterator; -import android.app.Activity; import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager.NameNotFoundException; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.os.Bundle; -import android.os.Environment; -import android.os.Message; -import android.util.Log; -import android.view.ViewGroup; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -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.KeyPair; -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.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Vector; -import java.util.regex.Pattern; - -/** - * TODO: - * - * - Externalize the authority and content uri constants - * - * - Separate this file into different helpers - * - */ public class PGPHelper { - - static { - // register spongy castle provider - Security.addProvider(new BouncyCastleProvider()); - } - - public static final String AUTHORITY = DataProvider.AUTHORITY; - - public static final Uri CONTENT_URI_SECRET_KEY_RINGS = Uri.parse("content://" + AUTHORITY - + "/key_rings/secret/"); - public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID = Uri.parse("content://" - + AUTHORITY + "/key_rings/secret/key_id/"); - public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS = Uri.parse("content://" - + AUTHORITY + "/key_rings/secret/emails/"); - - public static final Uri CONTENT_URI_PUBLIC_KEY_RINGS = Uri.parse("content://" + AUTHORITY - + "/key_rings/public/"); - public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID = Uri.parse("content://" - + AUTHORITY + "/key_rings/public/key_id/"); - public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS = Uri.parse("content://" - + AUTHORITY + "/key_rings/public/emails/"); - - private static String VERSION = null; - - 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 HashMap mPassPhraseCache = new HashMap(); - private static String mEditPassPhrase = null; - - private static Database mDatabase = null; - - public static class GeneralException extends Exception { - static final long serialVersionUID = 0xf812773342L; - - public GeneralException(String message) { - super(message); - } - } - - public static class NoAsymmetricEncryptionException extends Exception { - static final long serialVersionUID = 0xf812773343L; - - public NoAsymmetricEncryptionException() { - super(); - } - } - - public static void initialize(Context context) { - if (mDatabase == null) { - mDatabase = new Database(context); - } - } - - public static Database getDatabase() { - return mDatabase; - } - - public static void setEditPassPhrase(String passPhrase) { - mEditPassPhrase = passPhrase; - } - - public static String getEditPassPhrase() { - return mEditPassPhrase; - } - - public static void setCachedPassPhrase(long keyId, String passPhrase) { - mPassPhraseCache.put(keyId, new CachedPassPhrase(new Date().getTime(), passPhrase)); - } - - public static String getCachedPassPhrase(long keyId) { - long realId = keyId; - if (realId != Id.key.symmetric) { - PGPSecretKeyRing keyRing = getSecretKeyRing(keyId); - if (keyRing == null) { - return null; - } - PGPSecretKey masterKey = getMasterKey(keyRing); - if (masterKey == null) { - return null; - } - realId = masterKey.getKeyID(); - } - CachedPassPhrase cpp = mPassPhraseCache.get(realId); - if (cpp == null) { - return null; - } - // set it again to reset the cache life cycle - setCachedPassPhrase(realId, cpp.passPhrase); - return cpp.passPhrase; - } - - public static int cleanUpCache(int ttl, int initialDelay) { - int delay = initialDelay; - long realTtl = ttl * 1000; - long now = new Date().getTime(); - Vector oldKeys = new Vector(); - for (Map.Entry pair : mPassPhraseCache.entrySet()) { - long lived = now - pair.getValue().timestamp; - if (lived >= realTtl) { - oldKeys.add(pair.getKey()); - } else { - // see, whether the remaining time for this cache entry improves our - // check delay - long nextCheck = realTtl - lived + 1000; - if (nextCheck < delay) { - delay = (int) nextCheck; - } - } - } - - for (long keyId : oldKeys) { - mPassPhraseCache.remove(keyId); - } - - return delay; - } - - /** - * 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 GeneralException - * @throws InvalidAlgorithmParameterException - */ - public static PGPSecretKeyRing createKey(Context context, int algorithmChoice, int keySize, - String passPhrase, PGPSecretKey masterSecretKey) throws NoSuchAlgorithmException, - PGPException, NoSuchProviderException, GeneralException, - InvalidAlgorithmParameterException { - - if (keySize < 512) { - throw new GeneralException(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", "SC"); - keyGen.initialize(keySize, new SecureRandom()); - algorithm = PGPPublicKey.DSA; - break; - } - - case Id.choice.algorithm.elgamal: { - if (masterSecretKey == null) { - throw new GeneralException( - context.getString(R.string.error_masterKeyMustNotBeElGamal)); - } - keyGen = KeyPairGenerator.getInstance("ELGAMAL", "SC"); - 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", "SC"); - keyGen.initialize(keySize, new SecureRandom()); - - algorithm = PGPPublicKey.RSA_GENERAL; - break; - } - - default: { - throw new GeneralException(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); - PGPContentSignerBuilder certificationSignerBuilder = new JcaPGPContentSignerBuilder(keyPair - .getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1); - - // Build key encrypter and decrypter based on passphrase - PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( - PGPEncryptedData.CAST5, sha1Calc).setProvider("SC").build(passPhrase.toCharArray()); - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider("SC").build(passPhrase.toCharArray()); - - PGPKeyRingGenerator ringGen = null; - if (masterSecretKey == null) { - - // build keyRing with only this one master key in it! - ringGen = new PGPKeyRingGenerator(PGPSignature.DEFAULT_CERTIFICATION, keyPair, "", - sha1Calc, null, null, certificationSignerBuilder, keyEncryptor); - } else { - PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); - PGPPrivateKey masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor); - PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey); - - // build keyRing with master key and new key as subkey (certified by masterkey) - ringGen = new PGPKeyRingGenerator(PGPSignature.DEFAULT_CERTIFICATION, masterKeyPair, - "", sha1Calc, null, null, certificationSignerBuilder, keyEncryptor); - - ringGen.addSubKey(keyPair); - } - - PGPSecretKeyRing secKeyRing = ringGen.generateSecretKeyRing(); - - return secKeyRing; - } - - public static void buildSecretKey(Context context, ArrayList userIds, - ArrayList keys, ArrayList keysUsages, long masterKeyId, - String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress) - throws PGPHelper.GeneralException, NoSuchProviderException, PGPException, - NoSuchAlgorithmException, SignatureException, IOException, Database.GeneralException { - - if (progress != null) - progress.setProgress(R.string.progress_buildingKey, 0, 100); - - if (oldPassPhrase == null || oldPassPhrase.equals("")) { - oldPassPhrase = ""; - } - - if (newPassPhrase == null || newPassPhrase.equals("")) { - newPassPhrase = ""; - } - - // Vector userIds = new Vector(); - // Vector keys = new Vector(); - - // ViewGroup userIdEditors = userIdsView.getEditors(); - // ViewGroup keyEditors = keysView.getEditors(); - // - // boolean gotMainUserId = false; - // for (int i = 0; i < userIdEditors.getChildCount(); ++i) { - // UserIdEditor editor = (UserIdEditor) userIdEditors.getChildAt(i); - // String userId = null; - // try { - // userId = editor.getValue(); - // } catch (UserIdEditor.NoNameException e) { - // throw new Apg.GeneralException(context.getString(R.string.error_userIdNeedsAName)); - // } catch (UserIdEditor.NoEmailException e) { - // throw new Apg.GeneralException( - // context.getString(R.string.error_userIdNeedsAnEmailAddress)); - // } catch (UserIdEditor.InvalidEmailException e) { - // throw new Apg.GeneralException("" + e); - // } - // - // if (userId.equals("")) { - // continue; - // } - // - // if (editor.isMainUserId()) { - // userIds.insertElementAt(userId, 0); - // gotMainUserId = true; - // } else { - // userIds.add(userId); - // } - // } - - // if (userIds.size() == 0) { - // throw new Apg.GeneralException(context.getString(R.string.error_keyNeedsAUserId)); - // } - // - // if (!gotMainUserId) { - // throw new Apg.GeneralException( - // context.getString(R.string.error_mainUserIdMustNotBeEmpty)); - // } - - // if (keyEditors.getChildCount() == 0) { - // throw new Apg.GeneralException(context.getString(R.string.error_keyNeedsMasterKey)); - // } - // - // for (int i = 0; i < keyEditors.getChildCount(); ++i) { - // KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i); - // keys.add(editor.getValue()); - // } - - if (progress != null) - progress.setProgress(R.string.progress_preparingMasterKey, 10, 100); - - // KeyEditor keyEditor = (KeyEditor) keyEditors.getChildAt(0); - // int usageId = keyEditor.getUsage(); - - 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); - PGPPublicKey tmpKey = masterKey.getPublicKey(); - PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(), - tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime()); - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider("SC").build(oldPassPhrase.toCharArray()); - PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor); - - if (progress != null) - progress.setProgress(R.string.progress_certifyingMasterKey, 20, 100); - for (int i = 0; i < userIds.size(); ++i) { - String userId = userIds.get(i); - - PGPSignatureGenerator sGen = new PGPSignatureGenerator(masterPublicKey.getAlgorithm(), - HashAlgorithmTags.SHA1, new BouncyCastleProvider()); - - sGen.initSign(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 - - 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 - // 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); - // } - - if (progress != null) { - progress.setProgress(R.string.progress_buildingMasterKeyRing, 30, 100); - } - - PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, - masterKeyPair, mainUserId, PGPEncryptedData.CAST5, newPassPhrase.toCharArray(), - hashedPacketsGen.generate(), unhashedPacketsGen.generate(), new SecureRandom(), - new BouncyCastleProvider().getName()); - - if (progress != null) - progress.setProgress(R.string.progress_addingSubKeys, 40, 100); - for (int i = 1; i < keys.size(); ++i) { - if (progress != null) - progress.setProgress(40 + 50 * (i - 1) / (keys.size() - 1), 100); - PGPSecretKey subKey = keys.get(i); - // keyEditor = (KeyEditor) keyEditors.getChildAt(i); - PGPPublicKey subPublicKey = subKey.getPublicKey(); - - PBESecretKeyDecryptor keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder() - .setProvider("SC").build(oldPassPhrase.toCharArray()); - PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor2); - PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey.getAlgorithm(), - subPublicKey.getKey(new BouncyCastleProvider()), subPrivateKey.getKey(), - subPublicKey.getCreationTime()); - - hashedPacketsGen = new PGPSignatureSubpacketGenerator(); - unhashedPacketsGen = new PGPSignatureSubpacketGenerator(); - - keyFlags = 0; - // usageId = keyEditor.getUsage(); - - 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 - // 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(); - - if (progress != null) - progress.setProgress(R.string.progress_savingKeyRing, 90, 100); - mDatabase.saveKeyRing(secretKeyRing); - mDatabase.saveKeyRing(publicKeyRing); - - if (progress != null) - progress.setProgress(R.string.progress_done, 100, 100); - } - public static PGPKeyRing decodeKeyRing(InputStream is) throws IOException { InputStream in = PGPUtil.getDecoderStream(is); PGPObjectFactory objectFactory = new PGPObjectFactory(in); @@ -610,184 +52,6 @@ public class PGPHelper { return null; } - public static int storeKeyRingInCache(PGPKeyRing keyring) { - int status = Integer.MIN_VALUE; // out of bounds value (Id.retrun_value.*) - try { - if (keyring instanceof PGPSecretKeyRing) { - PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring; - boolean save = true; - try { - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider("SC").build(new char[] {}); - PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey( - keyDecryptor); - if (testKey == null) { - // this is bad, something is very wrong... likely a --export-secret-subkeys - // export - save = false; - status = Id.return_value.bad; - } - } catch (PGPException e) { - // all good if this fails, we likely didn't use the right password - } - - if (save) { - status = mDatabase.saveKeyRing(secretKeyRing); - } - } else if (keyring instanceof PGPPublicKeyRing) { - PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring; - status = mDatabase.saveKeyRing(publicKeyRing); - } - } catch (IOException e) { - status = Id.return_value.error; - } catch (Database.GeneralException 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(Activity context, int type, InputData data, - ProgressDialogUpdater progress) throws GeneralException, FileNotFoundException, - PGPException, IOException { - Bundle returnData = new Bundle(); - - if (type == Id.type.secret_key) { - if (progress != null) - progress.setProgress(R.string.progress_importingSecretKeys, 0, 100); - } else { - if (progress != null) - progress.setProgress(R.string.progress_importingPublicKeys, 0, 100); - } - - if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - throw new GeneralException(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 { - PGPKeyRing keyring = decodeKeyRing(bufferedInput); - while (keyring != null) { - int status = Integer.MIN_VALUE; // out of bounds value - - // if this key is what we expect it to be, save it - if ((type == Id.type.secret_key && keyring instanceof PGPSecretKeyRing) - || (type == Id.type.public_key && keyring instanceof PGPPublicKeyRing)) { - status = storeKeyRingInCache(keyring); - } - - if (status == Id.return_value.error) { - throw new GeneralException(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; - } - - if (progress != null) { - progress.setProgress((int) (100 * progressIn.position() / data.getSize()), 100); - } - // TODO: needed? - // obj = objectFactory.nextObject(); - - keyring = decodeKeyRing(bufferedInput); - } - } catch (EOFException e) { - // nothing to do, we are done - } - - returnData.putInt("added", newKeys); - returnData.putInt("updated", oldKeys); - returnData.putInt("bad", badKeys); - - if (progress != null) - progress.setProgress(R.string.progress_done, 100, 100); - - return returnData; - } - - public static Bundle exportKeyRings(Activity context, Vector keyRingIds, - OutputStream outStream, ProgressDialogUpdater progress) throws GeneralException, - FileNotFoundException, PGPException, IOException { - Bundle returnData = new Bundle(); - - if (keyRingIds.size() == 1) { - if (progress != null) - progress.setProgress(R.string.progress_exportingKey, 0, 100); - } else { - if (progress != null) - progress.setProgress(R.string.progress_exportingKeys, 0, 100); - } - - if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - throw new GeneralException(context.getString(R.string.error_externalStorageNotReady)); - } - ArmoredOutputStream out = new ArmoredOutputStream(outStream); - - int numKeys = 0; - for (int i = 0; i < keyRingIds.size(); ++i) { - if (progress != null) - progress.setProgress(i * 100 / keyRingIds.size(), 100); - Object obj = mDatabase.getKeyRing(keyRingIds.get(i)); - PGPPublicKeyRing publicKeyRing; - PGPSecretKeyRing secretKeyRing; - - if (obj instanceof PGPSecretKeyRing) { - secretKeyRing = (PGPSecretKeyRing) obj; - secretKeyRing.encode(out); - } else if (obj instanceof PGPPublicKeyRing) { - publicKeyRing = (PGPPublicKeyRing) obj; - publicKeyRing.encode(out); - } else { - continue; - } - ++numKeys; - } - out.close(); - returnData.putInt("exported", numKeys); - - if (progress != null) - progress.setProgress(R.string.progress_done, 100, 100); - - return returnData; - } - public static Date getCreationDate(PGPPublicKey key) { return key.getCreationTime(); } @@ -922,7 +186,8 @@ public class PGPHelper { } public static PGPPublicKey getEncryptPublicKey(long masterKeyId) { - PGPPublicKeyRing keyRing = getPublicKeyRing(masterKeyId); + //TODO: externalize getSecretKeyRing from PGPWrapper into a DatabaseHelper + PGPPublicKeyRing keyRing = PGPMain.getPublicKeyRing(masterKeyId); if (keyRing == null) { return null; } @@ -934,7 +199,8 @@ public class PGPHelper { } public static PGPSecretKey getSigningKey(long masterKeyId) { - PGPSecretKeyRing keyRing = getSecretKeyRing(masterKeyId); + //TODO: externalize getSecretKeyRing from PGPWrapper into a DatabaseHelper + PGPSecretKeyRing keyRing = PGPMain.getSecretKeyRing(masterKeyId); if (keyRing == null) { return null; } @@ -1115,9 +381,9 @@ public class PGPHelper { } public static String getFingerPrint(long keyId) { - PGPPublicKey key = PGPHelper.getPublicKey(keyId); + PGPPublicKey key = PGPMain.getPublicKey(keyId); if (key == null) { - PGPSecretKey secretKey = PGPHelper.getSecretKey(keyId); + PGPSecretKey secretKey = PGPMain.getSecretKey(keyId); if (secretKey == null) { return ""; } @@ -1145,1162 +411,4 @@ public class PGPHelper { String s1 = data.substring(0, len - 8); return (Long.parseLong(s1, 16) << 32) | Long.parseLong(s2, 16); } - - public static void deleteKey(int keyRingId) { - mDatabase.deleteKeyRing(keyRingId); - } - - public static PGPKeyRing getKeyRing(int keyRingId) { - return (PGPKeyRing) mDatabase.getKeyRing(keyRingId); - } - - public static PGPSecretKeyRing getSecretKeyRing(long keyId) { - byte[] data = mDatabase.getKeyRingDataFromKeyId(Id.database.type_secret, keyId); - if (data == null) { - return null; - } - try { - return new PGPSecretKeyRing(data); - } catch (IOException e) { - // no good way to handle this, return null - // TODO: some info? - } catch (PGPException e) { - // no good way to handle this, return null - // TODO: some info? - } - return null; - } - - public static PGPPublicKeyRing getPublicKeyRing(long keyId) { - byte[] data = mDatabase.getKeyRingDataFromKeyId(Id.database.type_public, keyId); - if (data == null) { - return null; - } - try { - return new PGPPublicKeyRing(data); - } catch (IOException e) { - // no good way to handle this, return null - // TODO: some info? - } - return null; - } - - public static PGPSecretKey getSecretKey(long keyId) { - PGPSecretKeyRing keyRing = getSecretKeyRing(keyId); - if (keyRing == null) { - return null; - } - return keyRing.getSecretKey(keyId); - } - - public static PGPPublicKey getPublicKey(long keyId) { - PGPPublicKeyRing keyRing = getPublicKeyRing(keyId); - if (keyRing == null) { - return null; - } - - return keyRing.getPublicKey(keyId); - } - - public static Vector getKeyRingIds(int type) { - SQLiteDatabase db = mDatabase.db(); - Vector keyIds = new Vector(); - Cursor c = db.query(KeyRings.TABLE_NAME, new String[] { KeyRings._ID }, KeyRings.TYPE - + " = ?", new String[] { "" + type }, null, null, null); - if (c != null && c.moveToFirst()) { - do { - keyIds.add(c.getInt(0)); - } while (c.moveToNext()); - } - - if (c != null) { - c.close(); - } - - return keyIds; - } - - public static String getMainUserId(long keyId, int type) { - SQLiteDatabase db = mDatabase.db(); - Cursor c = db.query(Keys.TABLE_NAME + " INNER JOIN " + KeyRings.TABLE_NAME + " ON (" - + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "." - + Keys.KEY_RING_ID + ") " + " INNER JOIN " + Keys.TABLE_NAME + " AS masterKey ON (" - + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + "masterKey." - + Keys.KEY_RING_ID + " AND " + "masterKey." + Keys.IS_MASTER_KEY + " = '1') " - + " INNER JOIN " + UserIds.TABLE_NAME + " ON (" + UserIds.TABLE_NAME + "." - + UserIds.KEY_ID + " = " + "masterKey." + Keys._ID + " AND " + UserIds.TABLE_NAME - + "." + UserIds.RANK + " = '0')", new String[] { UserIds.USER_ID }, Keys.TABLE_NAME - + "." + Keys.KEY_ID + " = ? AND " + KeyRings.TABLE_NAME + "." + KeyRings.TYPE - + " = ?", new String[] { "" + keyId, "" + type, }, null, null, null); - String userId = ""; - if (c != null && c.moveToFirst()) { - do { - userId = c.getString(0); - } while (c.moveToNext()); - } - - if (c != null) { - c.close(); - } - - return userId; - } - - public static void encrypt(Context context, InputData data, OutputStream outStream, - boolean armored, long encryptionKeyIds[], long signatureKeyId, - String signaturePassPhrase, ProgressDialogUpdater progress, int symmetricAlgorithm, - int hashAlgorithm, int compression, boolean forceV3Signature, String passPhrase) - throws IOException, GeneralException, PGPException, NoSuchProviderException, - NoSuchAlgorithmException, SignatureException { - - if (encryptionKeyIds == null) { - encryptionKeyIds = new long[0]; - } - - ArmoredOutputStream armorOut = null; - OutputStream out = null; - OutputStream encryptOut = 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 (encryptionKeyIds.length == 0 && passPhrase == null) { - throw new GeneralException( - context.getString(R.string.error_noEncryptionKeysOrPassPhrase)); - } - - if (signatureKeyId != Id.key.none) { - signingKeyRing = getSecretKeyRing(signatureKeyId); - signingKey = getSigningKey(signatureKeyId); - if (signingKey == null) { - throw new GeneralException(context.getString(R.string.error_signatureFailed)); - } - - if (signaturePassPhrase == null) { - throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase)); - } - if (progress != null) - progress.setProgress(R.string.progress_extractingSignatureKey, 0, 100); - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( - "SC").build(signaturePassPhrase.toCharArray()); - signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); - if (signaturePrivateKey == null) { - throw new GeneralException( - context.getString(R.string.error_couldNotExtractPrivateKey)); - } - } - if (progress != null) - progress.setProgress(R.string.progress_preparingStreams, 5, 100); - - // encrypt and compress input file content - PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(symmetricAlgorithm, true, - new SecureRandom(), new BouncyCastleProvider()); - - if (encryptionKeyIds.length == 0) { - // symmetric encryption - Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption"); - cPk.addMethod(passPhrase.toCharArray()); - } - for (int i = 0; i < encryptionKeyIds.length; ++i) { - PGPPublicKey key = getEncryptPublicKey(encryptionKeyIds[i]); - if (key != null) { - cPk.addMethod(key); - } - } - encryptOut = cPk.open(out, new byte[1 << 16]); - - PGPSignatureGenerator signatureGenerator = null; - PGPV3SignatureGenerator signatureV3Generator = null; - - if (signatureKeyId != Id.key.none) { - if (progress != null) - progress.setProgress(R.string.progress_preparingSignature, 10, 100); - if (forceV3Signature) { - signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey() - .getAlgorithm(), hashAlgorithm, new BouncyCastleProvider()); - signatureV3Generator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey); - } else { - signatureGenerator = new PGPSignatureGenerator(signingKey.getPublicKey() - .getAlgorithm(), hashAlgorithm, new BouncyCastleProvider()); - signatureGenerator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey); - - String userId = getMainUserId(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 (forceV3Signature) { - 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]); - if (progress != null) - progress.setProgress(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 (forceV3Signature) { - signatureV3Generator.update(buffer, 0, n); - } else { - signatureGenerator.update(buffer, 0, n); - } - } - done += n; - if (data.getSize() != 0) { - if (progress != null) - progress.setProgress((int) (20 + (95 - 20) * done / data.getSize()), 100); - } - } - - literalGen.close(); - - if (signatureKeyId != Id.key.none) { - if (progress != null) - progress.setProgress(R.string.progress_generatingSignature, 95, 100); - if (forceV3Signature) { - signatureV3Generator.generate().encode(pOut); - } else { - signatureGenerator.generate().encode(pOut); - } - } - if (compressGen != null) { - compressGen.close(); - } - encryptOut.close(); - if (armored) { - armorOut.close(); - } - - if (progress != null) - progress.setProgress(R.string.progress_done, 100, 100); - } - - public static void signText(Context context, InputData data, OutputStream outStream, - long signatureKeyId, String signaturePassPhrase, int hashAlgorithm, - boolean forceV3Signature, ProgressDialogUpdater progress) throws GeneralException, - 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) { - throw new GeneralException(context.getString(R.string.error_noSignatureKey)); - } - - signingKeyRing = getSecretKeyRing(signatureKeyId); - signingKey = getSigningKey(signatureKeyId); - if (signingKey == null) { - throw new GeneralException(context.getString(R.string.error_signatureFailed)); - } - - if (signaturePassPhrase == null) { - throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase)); - } - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider("SC").build(signaturePassPhrase.toCharArray()); - signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); - if (signaturePrivateKey == null) { - throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey)); - } - if (progress != null) - progress.setProgress(R.string.progress_preparingStreams, 0, 100); - - if (progress != null) - progress.setProgress(R.string.progress_preparingSignature, 30, 100); - - PGPSignatureGenerator signatureGenerator = null; - PGPV3SignatureGenerator signatureV3Generator = null; - - if (forceV3Signature) { - signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey() - .getAlgorithm(), hashAlgorithm, new BouncyCastleProvider()); - signatureV3Generator - .initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey); - } else { - signatureGenerator = new PGPSignatureGenerator( - signingKey.getPublicKey().getAlgorithm(), hashAlgorithm, - new BouncyCastleProvider()); - signatureGenerator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey); - - PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); - String userId = getMainUserId(getMasterKey(signingKeyRing)); - spGen.setSignerUserID(false, userId); - signatureGenerator.setHashedSubpackets(spGen.generate()); - } - - if (progress != null) - progress.setProgress(R.string.progress_signing, 40, 100); - - armorOut.beginClearText(hashAlgorithm); - - 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(); - - if (progress != null) - progress.setProgress(R.string.progress_done, 100, 100); - } - - public static void generateSignature(Context context, InputData data, OutputStream outStream, - boolean armored, boolean binary, long signatureKeyId, String signaturePassPhrase, - int hashAlgorithm, boolean forceV3Signature, ProgressDialogUpdater progress) - throws GeneralException, PGPException, IOException, NoSuchAlgorithmException, - SignatureException { - - ArmoredOutputStream armorOut = null; - OutputStream out = 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 GeneralException(context.getString(R.string.error_noSignatureKey)); - } - - signingKeyRing = getSecretKeyRing(signatureKeyId); - signingKey = getSigningKey(signatureKeyId); - if (signingKey == null) { - throw new GeneralException(context.getString(R.string.error_signatureFailed)); - } - - if (signaturePassPhrase == null) { - throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase)); - } - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider("SC").build(signaturePassPhrase.toCharArray()); - signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); - if (signaturePrivateKey == null) { - throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey)); - } - if (progress != null) - progress.setProgress(R.string.progress_preparingStreams, 0, 100); - - if (progress != null) - progress.setProgress(R.string.progress_preparingSignature, 30, 100); - - PGPSignatureGenerator signatureGenerator = null; - PGPV3SignatureGenerator signatureV3Generator = null; - - int type = PGPSignature.CANONICAL_TEXT_DOCUMENT; - if (binary) { - type = PGPSignature.BINARY_DOCUMENT; - } - - if (forceV3Signature) { - signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey() - .getAlgorithm(), hashAlgorithm, new BouncyCastleProvider()); - signatureV3Generator.initSign(type, signaturePrivateKey); - } else { - signatureGenerator = new PGPSignatureGenerator( - signingKey.getPublicKey().getAlgorithm(), hashAlgorithm, - new BouncyCastleProvider()); - signatureGenerator.initSign(type, signaturePrivateKey); - - PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); - String userId = getMainUserId(getMasterKey(signingKeyRing)); - spGen.setSignerUserID(false, userId); - signatureGenerator.setHashedSubpackets(spGen.generate()); - } - - if (progress != null) - progress.setProgress(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 long getDecryptionKeyId(Context context, InputStream inputStream) - throws GeneralException, 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 GeneralException(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 = getSecretKey(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 GeneralException, 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 GeneralException(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 decrypt(Context context, InputData data, OutputStream outStream, - String passPhrase, ProgressDialogUpdater progress, boolean assumeSymmetric) - throws IOException, GeneralException, 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 GeneralException(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 GeneralException( - context.getString(R.string.error_noSymmetricEncryptionPacket)); - } - - if (progress != null) - progress.setProgress(R.string.progress_preparingStreams, currentProgress, 100); - clear = pbe.getDataStream(passPhrase.toCharArray(), new BouncyCastleProvider()); - 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 = getSecretKey(encData.getKeyID()); - if (secretKey != null) { - pbe = encData; - break; - } - } - } - - if (secretKey == null) { - throw new GeneralException(context.getString(R.string.error_noSecretKeyFound)); - } - - currentProgress += 5; - if (progress != null) - progress.setProgress(R.string.progress_extractingKey, currentProgress, 100); - PGPPrivateKey privateKey = null; - try { - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider("SC").build(passPhrase.toCharArray()); - privateKey = secretKey.extractPrivateKey(keyDecryptor); - } catch (PGPException e) { - throw new PGPException(context.getString(R.string.error_wrongPassPhrase)); - } - if (privateKey == null) { - throw new GeneralException( - context.getString(R.string.error_couldNotExtractPrivateKey)); - } - currentProgress += 5; - if (progress != null) - progress.setProgress(R.string.progress_preparingStreams, currentProgress, 100); - clear = pbe.getDataStream(privateKey, new BouncyCastleProvider()); - 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(ApgService.EXTRA_SIGNATURE, true); - PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk; - for (int i = 0; i < sigList.size(); ++i) { - signature = sigList.get(i); - signatureKey = getPublicKey(signature.getKeyID()); - if (signatureKeyId == 0) { - signatureKeyId = signature.getKeyID(); - } - if (signatureKey == null) { - signature = null; - } else { - signatureIndex = i; - signatureKeyId = signature.getKeyID(); - String userId = null; - PGPPublicKeyRing sigKeyRing = getPublicKeyRing(signatureKeyId); - if (sigKeyRing != null) { - userId = getMainUserId(getMasterKey(sigKeyRing)); - } - returnData.putString(ApgService.EXTRA_SIGNATURE_USER_ID, userId); - break; - } - } - - returnData.putLong(ApgService.EXTRA_SIGNATURE_KEY_ID, signatureKeyId); - - if (signature != null) { - signature.initVerify(signatureKey, new BouncyCastleProvider()); - } else { - returnData.putBoolean(ApgService.EXTRA_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(ApgService.EXTRA_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)); - } - if (progress != null) - progress.setProgress(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(ApgService.EXTRA_SIGNATURE_SUCCESS, true); - } else { - returnData.putBoolean(ApgService.EXTRA_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 - } - - if (progress != null) - progress.setProgress(R.string.progress_done, 100, 100); - return returnData; - } - - public static Bundle verifyText(Context context, InputData data, OutputStream outStream, - ProgressDialogUpdater progress) throws IOException, GeneralException, PGPException, - SignatureException { - Bundle returnData = new Bundle(); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ArmoredInputStream aIn = new ArmoredInputStream(data.getInputStream()); - - if (progress != null) - progress.setProgress(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(ApgService.EXTRA_SIGNATURE, true); - - if (progress != null) - progress.setProgress(R.string.progress_processingSignature, 60, 100); - PGPObjectFactory pgpFact = new PGPObjectFactory(aIn); - - PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); - if (sigList == null) { - throw new GeneralException(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 = getPublicKey(signature.getKeyID()); - if (signatureKeyId == 0) { - signatureKeyId = signature.getKeyID(); - } - if (signatureKey == null) { - // TODO: reimplement! - // Bundle pauseData = new Bundle(); - // pauseData.putInt(Constants.extras.STATUS, Id.message.unknown_signature_key); - // pauseData.putLong(Constants.extras.KEY_ID, signatureKeyId); - // Message msg = new Message(); - // msg.setData(pauseData); - // context.sendMessage(msg); - // // pause here - // context.getRunningThread().pause(); - // // see whether the key was found in the meantime - // signatureKey = getPublicKey(signature.getKeyID()); - } - - if (signatureKey == null) { - signature = null; - } else { - signatureKeyId = signature.getKeyID(); - String userId = null; - PGPPublicKeyRing sigKeyRing = getPublicKeyRing(signatureKeyId); - if (sigKeyRing != null) { - userId = getMainUserId(getMasterKey(sigKeyRing)); - } - returnData.putString(ApgService.EXTRA_SIGNATURE_USER_ID, userId); - break; - } - } - - returnData.putLong(ApgService.EXTRA_SIGNATURE_KEY_ID, signatureKeyId); - - if (signature == null) { - returnData.putBoolean(ApgService.EXTRA_SIGNATURE_UNKNOWN, true); - if (progress != null) - progress.setProgress(R.string.progress_done, 100, 100); - return returnData; - } - - signature.initVerify(signatureKey, new BouncyCastleProvider()); - - 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(ApgService.EXTRA_SIGNATURE_SUCCESS, signature.verify()); - - if (progress != null) - progress.setProgress(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) { - if (VERSION != null) { - return VERSION; - } - try { - PackageInfo pi = context.getPackageManager().getPackageInfo(Constants.PACKAGE_NAME, 0); - VERSION = pi.versionName; - return VERSION; - } catch (NameNotFoundException e) { - // impossible! - return "0.0.0"; - } - } - - public static String getFullVersion(Context context) { - return "APG v" + getVersion(context); - } - - public static String generateRandomString(int length) { - SecureRandom random = new SecureRandom(); - /* - * try { random = SecureRandom.getInstance("SHA1PRNG", new BouncyCastleProvider()); } catch - * (NoSuchAlgorithmException e) { // TODO: need to handle this case somehow return null; } - */ - 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; - } - - 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; - } - - public static void deleteFileSecurely(Context context, File file, ProgressDialogUpdater progress) - 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/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java b/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java new file mode 100644 index 000000000..780fc47f2 --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java @@ -0,0 +1,1971 @@ +/* + * Copyright (C) 2012 Dominik Schürmann + * Copyright (C) 2010 Thialfihar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thialfihar.android.apg.helper; + +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.PGPUtil; +import org.spongycastle.openpgp.PGPV3SignatureGenerator; +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.PublicKeyKeyEncryptionMethodGenerator; +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.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.thialfihar.android.apg.passphrase.CachedPassPhrase; +import org.thialfihar.android.apg.provider.DataProvider; +import org.thialfihar.android.apg.provider.Database; +import org.thialfihar.android.apg.provider.KeyRings; +import org.thialfihar.android.apg.provider.Keys; +import org.thialfihar.android.apg.provider.UserIds; +import org.thialfihar.android.apg.service.ApgService; +import org.thialfihar.android.apg.util.HkpKeyServer; +import org.thialfihar.android.apg.util.InputData; +import org.thialfihar.android.apg.util.PositionAwareInputStream; +import org.thialfihar.android.apg.util.Primes; +import org.thialfihar.android.apg.util.KeyServer.AddKeyException; +import org.thialfihar.android.apg.Constants; +import org.thialfihar.android.apg.Id; +import org.thialfihar.android.apg.ProgressDialogUpdater; +import org.thialfihar.android.apg.R; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.util.Log; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +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.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Vector; +import java.util.regex.Pattern; + +/** + * TODO: + * + * - Externalize the authority and content uri constants + * + * - Separate this file into different helpers + * + */ +public class PGPMain { + + static { + // register spongy castle provider + Security.addProvider(new BouncyCastleProvider()); + } + + // Not BC due to the use of Spongy Castle for Android + public static final String BOUNCY_CASTLE_PROVIDER_NAME = "SC"; + + public static final String AUTHORITY = DataProvider.AUTHORITY; + + public static final Uri CONTENT_URI_SECRET_KEY_RINGS = Uri.parse("content://" + AUTHORITY + + "/key_rings/secret/"); + public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID = Uri.parse("content://" + + AUTHORITY + "/key_rings/secret/key_id/"); + public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS = Uri.parse("content://" + + AUTHORITY + "/key_rings/secret/emails/"); + + public static final Uri CONTENT_URI_PUBLIC_KEY_RINGS = Uri.parse("content://" + AUTHORITY + + "/key_rings/public/"); + public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID = Uri.parse("content://" + + AUTHORITY + "/key_rings/public/key_id/"); + public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS = Uri.parse("content://" + + AUTHORITY + "/key_rings/public/emails/"); + + private static String VERSION = null; + + 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 HashMap mPassPhraseCache = new HashMap(); + private static String mEditPassPhrase = null; + + private static Database mDatabase = null; + + public static class GeneralException extends Exception { + static final long serialVersionUID = 0xf812773342L; + + public GeneralException(String message) { + super(message); + } + } + + public static class NoAsymmetricEncryptionException extends Exception { + static final long serialVersionUID = 0xf812773343L; + + public NoAsymmetricEncryptionException() { + super(); + } + } + + public static void initialize(Context context) { + if (mDatabase == null) { + mDatabase = new Database(context); + } + } + + public static Database getDatabase() { + return mDatabase; + } + + public static void setEditPassPhrase(String passPhrase) { + mEditPassPhrase = passPhrase; + } + + public static String getEditPassPhrase() { + return mEditPassPhrase; + } + + public static void setCachedPassPhrase(long keyId, String passPhrase) { + mPassPhraseCache.put(keyId, new CachedPassPhrase(new Date().getTime(), passPhrase)); + } + + public static String getCachedPassPhrase(long keyId) { + long realId = keyId; + if (realId != Id.key.symmetric) { + PGPSecretKeyRing keyRing = getSecretKeyRing(keyId); + if (keyRing == null) { + return null; + } + PGPSecretKey masterKey = PGPHelper.getMasterKey(keyRing); + if (masterKey == null) { + return null; + } + realId = masterKey.getKeyID(); + } + CachedPassPhrase cpp = mPassPhraseCache.get(realId); + if (cpp == null) { + return null; + } + // set it again to reset the cache life cycle + setCachedPassPhrase(realId, cpp.passPhrase); + return cpp.passPhrase; + } + + public static int cleanUpCache(int ttl, int initialDelay) { + int delay = initialDelay; + long realTtl = ttl * 1000; + long now = new Date().getTime(); + Vector oldKeys = new Vector(); + for (Map.Entry pair : mPassPhraseCache.entrySet()) { + long lived = now - pair.getValue().timestamp; + if (lived >= realTtl) { + oldKeys.add(pair.getKey()); + } else { + // see, whether the remaining time for this cache entry improves our + // check delay + long nextCheck = realTtl - lived + 1000; + if (nextCheck < delay) { + delay = (int) nextCheck; + } + } + } + + for (long keyId : oldKeys) { + mPassPhraseCache.remove(keyId); + } + + return delay; + } + + /** + * 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 GeneralException + * @throws InvalidAlgorithmParameterException + */ + public static PGPSecretKeyRing createKey(Context context, int algorithmChoice, int keySize, + String passPhrase, PGPSecretKey masterSecretKey) throws NoSuchAlgorithmException, + PGPException, NoSuchProviderException, GeneralException, + InvalidAlgorithmParameterException { + + if (keySize < 512) { + throw new GeneralException(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 GeneralException( + 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 GeneralException(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); + PGPContentSignerBuilder certificationSignerBuilder = new JcaPGPContentSignerBuilder(keyPair + .getPublicKey().getAlgorithm(), 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; + if (masterSecretKey == null) { + + // build keyRing with only this one master key in it! + ringGen = new PGPKeyRingGenerator(PGPSignature.DEFAULT_CERTIFICATION, keyPair, "", + sha1Calc, null, null, certificationSignerBuilder, keyEncryptor); + } else { + PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); + PGPPrivateKey masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor); + PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey); + + // build keyRing with master key and new key as subkey (certified by masterkey) + ringGen = new PGPKeyRingGenerator(PGPSignature.DEFAULT_CERTIFICATION, masterKeyPair, + "", sha1Calc, null, null, certificationSignerBuilder, keyEncryptor); + + ringGen.addSubKey(keyPair); + } + + PGPSecretKeyRing secKeyRing = ringGen.generateSecretKeyRing(); + + return secKeyRing; + } + + public static void buildSecretKey(Context context, ArrayList userIds, + ArrayList keys, ArrayList keysUsages, long masterKeyId, + String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress) + throws PGPMain.GeneralException, NoSuchProviderException, PGPException, + NoSuchAlgorithmException, SignatureException, IOException, Database.GeneralException { + + if (progress != null) + progress.setProgress(R.string.progress_buildingKey, 0, 100); + + if (oldPassPhrase == null || oldPassPhrase.equals("")) { + oldPassPhrase = ""; + } + + if (newPassPhrase == null || newPassPhrase.equals("")) { + newPassPhrase = ""; + } + + // TODO: What is with this code? + // Vector userIds = new Vector(); + // Vector keys = new Vector(); + + // ViewGroup userIdEditors = userIdsView.getEditors(); + // ViewGroup keyEditors = keysView.getEditors(); + // + // boolean gotMainUserId = false; + // for (int i = 0; i < userIdEditors.getChildCount(); ++i) { + // UserIdEditor editor = (UserIdEditor) userIdEditors.getChildAt(i); + // String userId = null; + // try { + // userId = editor.getValue(); + // } catch (UserIdEditor.NoNameException e) { + // throw new Apg.GeneralException(context.getString(R.string.error_userIdNeedsAName)); + // } catch (UserIdEditor.NoEmailException e) { + // throw new Apg.GeneralException( + // context.getString(R.string.error_userIdNeedsAnEmailAddress)); + // } catch (UserIdEditor.InvalidEmailException e) { + // throw new Apg.GeneralException("" + e); + // } + // + // if (userId.equals("")) { + // continue; + // } + // + // if (editor.isMainUserId()) { + // userIds.insertElementAt(userId, 0); + // gotMainUserId = true; + // } else { + // userIds.add(userId); + // } + // } + + // if (userIds.size() == 0) { + // throw new Apg.GeneralException(context.getString(R.string.error_keyNeedsAUserId)); + // } + // + // if (!gotMainUserId) { + // throw new Apg.GeneralException( + // context.getString(R.string.error_mainUserIdMustNotBeEmpty)); + // } + + // if (keyEditors.getChildCount() == 0) { + // throw new Apg.GeneralException(context.getString(R.string.error_keyNeedsMasterKey)); + // } + // + // for (int i = 0; i < keyEditors.getChildCount(); ++i) { + // KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i); + // keys.add(editor.getValue()); + // } + + if (progress != null) + progress.setProgress(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); + PGPPublicKey masterPublicKey = masterKey.getPublicKey(); + + // TODO: why was this done?: + // PGPPublicKey tmpKey = masterKey.getPublicKey(); + // PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(), + // tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime()); + + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( + BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray()); + PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor); + + if (progress != null) + progress.setProgress(R.string.progress_certifyingMasterKey, 20, 100); + for (int i = 0; i < userIds.size(); ++i) { + String userId = userIds.get(i); + + 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 + + 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 + // 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); + // } + + if (progress != null) { + progress.setProgress(R.string.progress_buildingMasterKeyRing, 30, 100); + } + + // deprecated method: + // PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, + // masterKeyPair, mainUserId, PGPEncryptedData.CAST5, newPassPhrase.toCharArray(), + // hashedPacketsGen.generate(), unhashedPacketsGen.generate(), new SecureRandom(), + // new BouncyCastleProvider().getName()); + + // 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); + + if (progress != null) + progress.setProgress(R.string.progress_addingSubKeys, 40, 100); + for (int i = 1; i < keys.size(); ++i) { + if (progress != null) + progress.setProgress(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); + + // deprecated method: + // PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey.getAlgorithm(), + // subPublicKey.getKey(new BouncyCastleProvider()), subPrivateKey.getKey(), + // subPublicKey.getCreationTime()); + + // TODO: now used without algorithm and creation time?! + 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 + // 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(); + + if (progress != null) + progress.setProgress(R.string.progress_savingKeyRing, 90, 100); + mDatabase.saveKeyRing(secretKeyRing); + mDatabase.saveKeyRing(publicKeyRing); + + if (progress != null) + progress.setProgress(R.string.progress_done, 100, 100); + } + + public static int storeKeyRingInCache(PGPKeyRing keyring) { + int status = Integer.MIN_VALUE; // out of bounds value (Id.retrun_value.*) + try { + if (keyring instanceof PGPSecretKeyRing) { + PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring; + boolean save = true; + try { + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() + .setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(new char[] {}); + PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey( + keyDecryptor); + if (testKey == null) { + // this is bad, something is very wrong... likely a --export-secret-subkeys + // export + save = false; + status = Id.return_value.bad; + } + } catch (PGPException e) { + // all good if this fails, we likely didn't use the right password + } + + if (save) { + status = mDatabase.saveKeyRing(secretKeyRing); + } + } else if (keyring instanceof PGPPublicKeyRing) { + PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring; + status = mDatabase.saveKeyRing(publicKeyRing); + } + } catch (IOException e) { + status = Id.return_value.error; + } catch (Database.GeneralException 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(Activity context, int type, InputData data, + ProgressDialogUpdater progress) throws GeneralException, FileNotFoundException, + PGPException, IOException { + Bundle returnData = new Bundle(); + + if (type == Id.type.secret_key) { + if (progress != null) + progress.setProgress(R.string.progress_importingSecretKeys, 0, 100); + } else { + if (progress != null) + progress.setProgress(R.string.progress_importingPublicKeys, 0, 100); + } + + if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + throw new GeneralException(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 { + PGPKeyRing keyring = PGPHelper.decodeKeyRing(bufferedInput); + while (keyring != null) { + int status = Integer.MIN_VALUE; // out of bounds value + + // if this key is what we expect it to be, save it + if ((type == Id.type.secret_key && keyring instanceof PGPSecretKeyRing) + || (type == Id.type.public_key && keyring instanceof PGPPublicKeyRing)) { + status = storeKeyRingInCache(keyring); + } + + if (status == Id.return_value.error) { + throw new GeneralException(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; + } + + if (progress != null) { + progress.setProgress((int) (100 * progressIn.position() / data.getSize()), 100); + } + // TODO: needed? + // obj = objectFactory.nextObject(); + + keyring = PGPHelper.decodeKeyRing(bufferedInput); + } + } catch (EOFException e) { + // nothing to do, we are done + } + + returnData.putInt("added", newKeys); + returnData.putInt("updated", oldKeys); + returnData.putInt("bad", badKeys); + + if (progress != null) + progress.setProgress(R.string.progress_done, 100, 100); + + return returnData; + } + + public static Bundle exportKeyRings(Activity context, Vector keyRingIds, + OutputStream outStream, ProgressDialogUpdater progress) throws GeneralException, + FileNotFoundException, PGPException, IOException { + Bundle returnData = new Bundle(); + + if (keyRingIds.size() == 1) { + if (progress != null) + progress.setProgress(R.string.progress_exportingKey, 0, 100); + } else { + if (progress != null) + progress.setProgress(R.string.progress_exportingKeys, 0, 100); + } + + if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + throw new GeneralException(context.getString(R.string.error_externalStorageNotReady)); + } + ArmoredOutputStream out = new ArmoredOutputStream(outStream); + + int numKeys = 0; + for (int i = 0; i < keyRingIds.size(); ++i) { + if (progress != null) + progress.setProgress(i * 100 / keyRingIds.size(), 100); + Object obj = mDatabase.getKeyRing(keyRingIds.get(i)); + PGPPublicKeyRing publicKeyRing; + PGPSecretKeyRing secretKeyRing; + + if (obj instanceof PGPSecretKeyRing) { + secretKeyRing = (PGPSecretKeyRing) obj; + secretKeyRing.encode(out); + } else if (obj instanceof PGPPublicKeyRing) { + publicKeyRing = (PGPPublicKeyRing) obj; + publicKeyRing.encode(out); + } else { + continue; + } + ++numKeys; + } + out.close(); + returnData.putInt("exported", numKeys); + + if (progress != null) + progress.setProgress(R.string.progress_done, 100, 100); + + return returnData; + } + + public static void deleteKey(int keyRingId) { + mDatabase.deleteKeyRing(keyRingId); + } + + public static PGPKeyRing getKeyRing(int keyRingId) { + return (PGPKeyRing) mDatabase.getKeyRing(keyRingId); + } + + public static PGPSecretKeyRing getSecretKeyRing(long keyId) { + byte[] data = mDatabase.getKeyRingDataFromKeyId(Id.database.type_secret, keyId); + if (data == null) { + return null; + } + return PGPConversionHelper.BytesToPGPSecretKeyRing(data); + + // deprecated method: + // try { + // return new PGPSecretKeyRing(data); + // } catch (IOException e) { + // // no good way to handle this, return null + // // TODO: some info? + // } catch (PGPException e) { + // // no good way to handle this, return null + // // TODO: some info? + // } + // return null; + } + + public static PGPPublicKeyRing getPublicKeyRing(long keyId) { + byte[] data = mDatabase.getKeyRingDataFromKeyId(Id.database.type_public, keyId); + if (data == null) { + return null; + } + return PGPConversionHelper.BytesToPGPPublicKeyRing(data); + + // deprecated method: + // try { + // return new PGPPublicKeyRing(data); + // } catch (IOException e) { + // // no good way to handle this, return null + // // TODO: some info? + // } + // return null; + } + + public static PGPSecretKey getSecretKey(long keyId) { + PGPSecretKeyRing keyRing = getSecretKeyRing(keyId); + if (keyRing == null) { + return null; + } + return keyRing.getSecretKey(keyId); + } + + public static PGPPublicKey getPublicKey(long keyId) { + PGPPublicKeyRing keyRing = getPublicKeyRing(keyId); + if (keyRing == null) { + return null; + } + + return keyRing.getPublicKey(keyId); + } + + public static Vector getKeyRingIds(int type) { + SQLiteDatabase db = mDatabase.db(); + Vector keyIds = new Vector(); + Cursor c = db.query(KeyRings.TABLE_NAME, new String[] { KeyRings._ID }, KeyRings.TYPE + + " = ?", new String[] { "" + type }, null, null, null); + if (c != null && c.moveToFirst()) { + do { + keyIds.add(c.getInt(0)); + } while (c.moveToNext()); + } + + if (c != null) { + c.close(); + } + + return keyIds; + } + + public static String getMainUserId(long keyId, int type) { + SQLiteDatabase db = mDatabase.db(); + Cursor c = db.query(Keys.TABLE_NAME + " INNER JOIN " + KeyRings.TABLE_NAME + " ON (" + + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "." + + Keys.KEY_RING_ID + ") " + " INNER JOIN " + Keys.TABLE_NAME + " AS masterKey ON (" + + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + "masterKey." + + Keys.KEY_RING_ID + " AND " + "masterKey." + Keys.IS_MASTER_KEY + " = '1') " + + " INNER JOIN " + UserIds.TABLE_NAME + " ON (" + UserIds.TABLE_NAME + "." + + UserIds.KEY_ID + " = " + "masterKey." + Keys._ID + " AND " + UserIds.TABLE_NAME + + "." + UserIds.RANK + " = '0')", new String[] { UserIds.USER_ID }, Keys.TABLE_NAME + + "." + Keys.KEY_ID + " = ? AND " + KeyRings.TABLE_NAME + "." + KeyRings.TYPE + + " = ?", new String[] { "" + keyId, "" + type, }, null, null, null); + String userId = ""; + if (c != null && c.moveToFirst()) { + do { + userId = c.getString(0); + } while (c.moveToNext()); + } + + if (c != null) { + c.close(); + } + + return userId; + } + + public static void encrypt(Context context, InputData data, OutputStream outStream, + boolean armored, long encryptionKeyIds[], long signatureKeyId, + String signaturePassPhrase, ProgressDialogUpdater progress, int symmetricAlgorithm, + int hashAlgorithm, int compression, boolean forceV3Signature, String passPhrase) + throws IOException, GeneralException, PGPException, NoSuchProviderException, + NoSuchAlgorithmException, SignatureException { + + if (encryptionKeyIds == null) { + encryptionKeyIds = new long[0]; + } + + ArmoredOutputStream armorOut = null; + OutputStream out = null; + OutputStream encryptOut = 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 (encryptionKeyIds.length == 0 && passPhrase == null) { + throw new GeneralException( + context.getString(R.string.error_noEncryptionKeysOrPassPhrase)); + } + + if (signatureKeyId != Id.key.none) { + signingKeyRing = getSecretKeyRing(signatureKeyId); + signingKey = PGPHelper.getSigningKey(signatureKeyId); + if (signingKey == null) { + throw new GeneralException(context.getString(R.string.error_signatureFailed)); + } + + if (signaturePassPhrase == null) { + throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase)); + } + if (progress != null) + progress.setProgress(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 GeneralException( + context.getString(R.string.error_couldNotExtractPrivateKey)); + } + } + if (progress != null) + progress.setProgress(R.string.progress_preparingStreams, 5, 100); + + // encrypt and compress input file content + JcePGPDataEncryptorBuilder encryptorBuilder = new JcePGPDataEncryptorBuilder( + symmetricAlgorithm).setProvider(BOUNCY_CASTLE_PROVIDER_NAME) + .setWithIntegrityPacket(true); + + PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(encryptorBuilder); + + // deprecated method: + // PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(symmetricAlgorithm, true, + // new SecureRandom(), new BouncyCastleProvider()); + + if (encryptionKeyIds.length == 0) { + // symmetric encryption + Log.d(Constants.TAG, "encryptionKeyIds length is 0 -> symmetric encryption"); + + JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator = new JcePBEKeyEncryptionMethodGenerator( + passPhrase.toCharArray()); + cPk.addMethod(symmetricEncryptionGenerator); + + // deprecated method: + // cPk.addMethod(passPhrase.toCharArray()); + } + for (int i = 0; i < encryptionKeyIds.length; ++i) { + PGPPublicKey key = PGPHelper.getEncryptPublicKey(encryptionKeyIds[i]); + if (key != null) { + + JcePublicKeyKeyEncryptionMethodGenerator pubKeyEncryptionGenerator = new JcePublicKeyKeyEncryptionMethodGenerator( + key); + cPk.addMethod(pubKeyEncryptionGenerator); + + // deprecated method: + // cPk.addMethod(key); + } + } + encryptOut = cPk.open(out, new byte[1 << 16]); + + PGPSignatureGenerator signatureGenerator = null; + PGPV3SignatureGenerator signatureV3Generator = null; + + if (signatureKeyId != Id.key.none) { + if (progress != null) + progress.setProgress(R.string.progress_preparingSignature, 10, 100); + if (forceV3Signature) { + signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey() + .getAlgorithm(), hashAlgorithm, new BouncyCastleProvider()); + signatureV3Generator.initSign(PGPSignature.BINARY_DOCUMENT, signaturePrivateKey); + } else { + signatureGenerator = new PGPSignatureGenerator(signingKey.getPublicKey() + .getAlgorithm(), hashAlgorithm, new BouncyCastleProvider()); + signatureGenerator.initSign(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 (forceV3Signature) { + 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]); + if (progress != null) + progress.setProgress(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 (forceV3Signature) { + signatureV3Generator.update(buffer, 0, n); + } else { + signatureGenerator.update(buffer, 0, n); + } + } + done += n; + if (data.getSize() != 0) { + if (progress != null) + progress.setProgress((int) (20 + (95 - 20) * done / data.getSize()), 100); + } + } + + literalGen.close(); + + if (signatureKeyId != Id.key.none) { + if (progress != null) + progress.setProgress(R.string.progress_generatingSignature, 95, 100); + if (forceV3Signature) { + signatureV3Generator.generate().encode(pOut); + } else { + signatureGenerator.generate().encode(pOut); + } + } + if (compressGen != null) { + compressGen.close(); + } + encryptOut.close(); + if (armored) { + armorOut.close(); + } + + if (progress != null) + progress.setProgress(R.string.progress_done, 100, 100); + } + + public static void signText(Context context, InputData data, OutputStream outStream, + long signatureKeyId, String signaturePassPhrase, int hashAlgorithm, + boolean forceV3Signature, ProgressDialogUpdater progress) throws GeneralException, + 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) { + throw new GeneralException(context.getString(R.string.error_noSignatureKey)); + } + + signingKeyRing = getSecretKeyRing(signatureKeyId); + signingKey = PGPHelper.getSigningKey(signatureKeyId); + if (signingKey == null) { + throw new GeneralException(context.getString(R.string.error_signatureFailed)); + } + + if (signaturePassPhrase == null) { + throw new GeneralException(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 GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey)); + } + if (progress != null) + progress.setProgress(R.string.progress_preparingStreams, 0, 100); + + if (progress != null) + progress.setProgress(R.string.progress_preparingSignature, 30, 100); + + PGPSignatureGenerator signatureGenerator = null; + PGPV3SignatureGenerator signatureV3Generator = null; + + if (forceV3Signature) { + signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey() + .getAlgorithm(), hashAlgorithm, new BouncyCastleProvider()); + signatureV3Generator + .initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey); + } else { + signatureGenerator = new PGPSignatureGenerator( + signingKey.getPublicKey().getAlgorithm(), hashAlgorithm, + new BouncyCastleProvider()); + signatureGenerator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, signaturePrivateKey); + + PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); + String userId = PGPHelper.getMainUserId(PGPHelper.getMasterKey(signingKeyRing)); + spGen.setSignerUserID(false, userId); + signatureGenerator.setHashedSubpackets(spGen.generate()); + } + + if (progress != null) + progress.setProgress(R.string.progress_signing, 40, 100); + + armorOut.beginClearText(hashAlgorithm); + + 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(); + + if (progress != null) + progress.setProgress(R.string.progress_done, 100, 100); + } + + public static void generateSignature(Context context, InputData data, OutputStream outStream, + boolean armored, boolean binary, long signatureKeyId, String signaturePassPhrase, + int hashAlgorithm, boolean forceV3Signature, ProgressDialogUpdater progress) + throws GeneralException, PGPException, IOException, NoSuchAlgorithmException, + SignatureException { + + ArmoredOutputStream armorOut = null; + OutputStream out = 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 GeneralException(context.getString(R.string.error_noSignatureKey)); + } + + signingKeyRing = getSecretKeyRing(signatureKeyId); + signingKey = PGPHelper.getSigningKey(signatureKeyId); + if (signingKey == null) { + throw new GeneralException(context.getString(R.string.error_signatureFailed)); + } + + if (signaturePassPhrase == null) { + throw new GeneralException(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 GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey)); + } + if (progress != null) + progress.setProgress(R.string.progress_preparingStreams, 0, 100); + + if (progress != null) + progress.setProgress(R.string.progress_preparingSignature, 30, 100); + + PGPSignatureGenerator signatureGenerator = null; + PGPV3SignatureGenerator signatureV3Generator = null; + + int type = PGPSignature.CANONICAL_TEXT_DOCUMENT; + if (binary) { + type = PGPSignature.BINARY_DOCUMENT; + } + + if (forceV3Signature) { + signatureV3Generator = new PGPV3SignatureGenerator(signingKey.getPublicKey() + .getAlgorithm(), hashAlgorithm, new BouncyCastleProvider()); + signatureV3Generator.initSign(type, signaturePrivateKey); + } else { + signatureGenerator = new PGPSignatureGenerator( + signingKey.getPublicKey().getAlgorithm(), hashAlgorithm, + new BouncyCastleProvider()); + signatureGenerator.initSign(type, signaturePrivateKey); + + PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); + String userId = PGPHelper.getMainUserId(PGPHelper.getMasterKey(signingKeyRing)); + spGen.setSignerUserID(false, userId); + signatureGenerator.setHashedSubpackets(spGen.generate()); + } + + if (progress != null) + progress.setProgress(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 long getDecryptionKeyId(Context context, InputStream inputStream) + throws GeneralException, 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 GeneralException(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 = getSecretKey(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 GeneralException, 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 GeneralException(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 decrypt(Context context, InputData data, OutputStream outStream, + String passPhrase, ProgressDialogUpdater progress, boolean assumeSymmetric) + throws IOException, GeneralException, 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 GeneralException(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 GeneralException( + context.getString(R.string.error_noSymmetricEncryptionPacket)); + } + + if (progress != null) + progress.setProgress(R.string.progress_preparingStreams, currentProgress, 100); + clear = pbe.getDataStream(passPhrase.toCharArray(), new BouncyCastleProvider()); + 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 = getSecretKey(encData.getKeyID()); + if (secretKey != null) { + pbe = encData; + break; + } + } + } + + if (secretKey == null) { + throw new GeneralException(context.getString(R.string.error_noSecretKeyFound)); + } + + currentProgress += 5; + if (progress != null) + progress.setProgress(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 GeneralException( + context.getString(R.string.error_couldNotExtractPrivateKey)); + } + currentProgress += 5; + if (progress != null) + progress.setProgress(R.string.progress_preparingStreams, currentProgress, 100); + clear = pbe.getDataStream(privateKey, new BouncyCastleProvider()); + 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(ApgService.EXTRA_SIGNATURE, true); + PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk; + for (int i = 0; i < sigList.size(); ++i) { + signature = sigList.get(i); + signatureKey = getPublicKey(signature.getKeyID()); + if (signatureKeyId == 0) { + signatureKeyId = signature.getKeyID(); + } + if (signatureKey == null) { + signature = null; + } else { + signatureIndex = i; + signatureKeyId = signature.getKeyID(); + String userId = null; + PGPPublicKeyRing sigKeyRing = getPublicKeyRing(signatureKeyId); + if (sigKeyRing != null) { + userId = PGPHelper.getMainUserId(PGPHelper.getMasterKey(sigKeyRing)); + } + returnData.putString(ApgService.EXTRA_SIGNATURE_USER_ID, userId); + break; + } + } + + returnData.putLong(ApgService.EXTRA_SIGNATURE_KEY_ID, signatureKeyId); + + if (signature != null) { + signature.initVerify(signatureKey, new BouncyCastleProvider()); + } else { + returnData.putBoolean(ApgService.EXTRA_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(ApgService.EXTRA_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)); + } + if (progress != null) + progress.setProgress(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(ApgService.EXTRA_SIGNATURE_SUCCESS, true); + } else { + returnData.putBoolean(ApgService.EXTRA_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 + } + + if (progress != null) + progress.setProgress(R.string.progress_done, 100, 100); + return returnData; + } + + public static Bundle verifyText(Context context, InputData data, OutputStream outStream, + ProgressDialogUpdater progress) throws IOException, GeneralException, PGPException, + SignatureException { + Bundle returnData = new Bundle(); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ArmoredInputStream aIn = new ArmoredInputStream(data.getInputStream()); + + if (progress != null) + progress.setProgress(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(ApgService.EXTRA_SIGNATURE, true); + + if (progress != null) + progress.setProgress(R.string.progress_processingSignature, 60, 100); + PGPObjectFactory pgpFact = new PGPObjectFactory(aIn); + + PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); + if (sigList == null) { + throw new GeneralException(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 = getPublicKey(signature.getKeyID()); + if (signatureKeyId == 0) { + signatureKeyId = signature.getKeyID(); + } + if (signatureKey == null) { + // TODO: reimplement! + // Bundle pauseData = new Bundle(); + // pauseData.putInt(Constants.extras.STATUS, Id.message.unknown_signature_key); + // pauseData.putLong(Constants.extras.KEY_ID, signatureKeyId); + // Message msg = new Message(); + // msg.setData(pauseData); + // context.sendMessage(msg); + // // pause here + // context.getRunningThread().pause(); + // // see whether the key was found in the meantime + // signatureKey = getPublicKey(signature.getKeyID()); + } + + if (signatureKey == null) { + signature = null; + } else { + signatureKeyId = signature.getKeyID(); + String userId = null; + PGPPublicKeyRing sigKeyRing = getPublicKeyRing(signatureKeyId); + if (sigKeyRing != null) { + userId = PGPHelper.getMainUserId(PGPHelper.getMasterKey(sigKeyRing)); + } + returnData.putString(ApgService.EXTRA_SIGNATURE_USER_ID, userId); + break; + } + } + + returnData.putLong(ApgService.EXTRA_SIGNATURE_KEY_ID, signatureKeyId); + + if (signature == null) { + returnData.putBoolean(ApgService.EXTRA_SIGNATURE_UNKNOWN, true); + if (progress != null) + progress.setProgress(R.string.progress_done, 100, 100); + return returnData; + } + + signature.initVerify(signatureKey, new BouncyCastleProvider()); + + 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(ApgService.EXTRA_SIGNATURE_SUCCESS, signature.verify()); + + if (progress != null) + progress.setProgress(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) { + if (VERSION != null) { + return VERSION; + } + try { + PackageInfo pi = context.getPackageManager().getPackageInfo(Constants.PACKAGE_NAME, 0); + VERSION = pi.versionName; + return VERSION; + } catch (NameNotFoundException e) { + // impossible! + return "0.0.0"; + } + } + + public static String getFullVersion(Context context) { + return "APG v" + getVersion(context); + } + + public static String generateRandomString(int length) { + SecureRandom random = new SecureRandom(); + /* + * try { random = SecureRandom.getInstance("SHA1PRNG", new BouncyCastleProvider()); } catch + * (NoSuchAlgorithmException e) { // TODO: need to handle this case somehow return null; } + */ + 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; + } + + 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; + } + + public static void deleteFileSecurely(Context context, File file, ProgressDialogUpdater progress) + 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/org_apg/src/org/thialfihar/android/apg/passphrase/AskForPassphrase.java b/org_apg/src/org/thialfihar/android/apg/passphrase/AskForPassphrase.java index 5711a16a8..4e7bdd70f 100644 --- a/org_apg/src/org/thialfihar/android/apg/passphrase/AskForPassphrase.java +++ b/org_apg/src/org/thialfihar/android/apg/passphrase/AskForPassphrase.java @@ -23,6 +23,7 @@ import org.spongycastle.openpgp.PGPSecretKey; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import android.app.Activity; import android.app.AlertDialog; @@ -55,7 +56,7 @@ public class AskForPassphrase { secretKey = null; alert.setMessage(context.getString(R.string.passPhraseForSymmetricEncryption)); } else { - secretKey = PGPHelper.getMasterKey(PGPHelper.getSecretKeyRing(secretKeyId)); + secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId)); if (secretKey == null) { alert.setTitle(R.string.title_keyNotFound); alert.setMessage(context.getString(R.string.keyNotFound, secretKeyId)); @@ -111,7 +112,7 @@ public class AskForPassphrase { } // cache again - PGPHelper.setCachedPassPhrase(keyId, passPhrase); + PGPMain.setCachedPassPhrase(keyId, passPhrase); // return by callback cb.passPhraseCallback(keyId, passPhrase); } @@ -133,7 +134,7 @@ public class AskForPassphrase { Log.d("APG", "Key has no passphrase!"); // cache null - PGPHelper.setCachedPassPhrase(secretKey.getKeyID(), null); + PGPMain.setCachedPassPhrase(secretKey.getKeyID(), null); // return by callback cb.passPhraseCallback(secretKey.getKeyID(), null); diff --git a/org_apg/src/org/thialfihar/android/apg/passphrase/PassphraseCacheService.java b/org_apg/src/org/thialfihar/android/apg/passphrase/PassphraseCacheService.java index 9325268fa..c7758cb4f 100644 --- a/org_apg/src/org/thialfihar/android/apg/passphrase/PassphraseCacheService.java +++ b/org_apg/src/org/thialfihar/android/apg/passphrase/PassphraseCacheService.java @@ -14,7 +14,7 @@ package org.thialfihar.android.apg.passphrase; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.Preferences; import android.app.Service; @@ -47,7 +47,7 @@ public class PassphraseCacheService extends Service { delay = 60000; } - delay = PGPHelper.cleanUpCache(mPassPhraseCacheTtl, delay); + delay = PGPMain.cleanUpCache(mPassPhraseCacheTtl, delay); // don't check too often, even if we were close if (delay < 5000) { delay = 5000; diff --git a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java index 43b13ba77..7f5ee1272 100644 --- a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java +++ b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java @@ -33,9 +33,9 @@ import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.ProgressDialogUpdater; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.helper.FileHelper; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.Preferences; -import org.thialfihar.android.apg.helper.PGPHelper.GeneralException; +import org.thialfihar.android.apg.helper.PGPMain.GeneralException; import org.thialfihar.android.apg.helper.PGPConversionHelper; import org.thialfihar.android.apg.provider.DataProvider; import org.thialfihar.android.apg.util.InputData; @@ -197,9 +197,9 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { long masterKeyId = data.getLong(MASTER_KEY_ID); /* Operation */ - PGPHelper.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, + PGPMain.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase, newPassPhrase, this); - PGPHelper.setCachedPassPhrase(masterKeyId, newPassPhrase); + PGPMain.setCachedPassPhrase(masterKeyId, newPassPhrase); /* Output */ sendMessageToHandler(ApgHandler.MESSAGE_OKAY); @@ -223,7 +223,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { } /* Operation */ - PGPSecretKeyRing newKeyRing = PGPHelper.createKey(this, algorithm, keysize, + PGPSecretKeyRing newKeyRing = PGPMain.createKey(this, algorithm, keysize, passphrase, masterKey); /* Output */ @@ -244,10 +244,10 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { String passphrase = data.getString(SYMMETRIC_PASSPHRASE); /* Operation */ - PGPSecretKeyRing masterKeyRing = PGPHelper.createKey(this, Id.choice.algorithm.rsa, + PGPSecretKeyRing masterKeyRing = PGPMain.createKey(this, Id.choice.algorithm.rsa, 2048, passphrase, null); - PGPSecretKeyRing subKeyRing = PGPHelper.createKey(this, Id.choice.algorithm.rsa, + PGPSecretKeyRing subKeyRing = PGPMain.createKey(this, Id.choice.algorithm.rsa, 2048, passphrase, masterKeyRing.getSecretKey()); /* Output */ @@ -288,20 +288,20 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { if (generateSignature) { Log.d(Constants.TAG, "generate signature..."); - PGPHelper.generateSignature(this, inputData, outStream, useAsciiArmour, false, - secretKeyId, PGPHelper.getCachedPassPhrase(secretKeyId), Preferences + PGPMain.generateSignature(this, inputData, outStream, useAsciiArmour, false, + secretKeyId, PGPMain.getCachedPassPhrase(secretKeyId), Preferences .getPreferences(this).getDefaultHashAlgorithm(), Preferences .getPreferences(this).getForceV3Signatures(), this); } else if (signOnly) { Log.d(Constants.TAG, "sign only..."); - PGPHelper.signText(this, inputData, outStream, secretKeyId, PGPHelper + PGPMain.signText(this, inputData, outStream, secretKeyId, PGPMain .getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this) .getDefaultHashAlgorithm(), Preferences.getPreferences(this) .getForceV3Signatures(), this); } else { Log.d(Constants.TAG, "encrypt..."); - PGPHelper.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds, - signatureKeyId, PGPHelper.getCachedPassPhrase(signatureKeyId), this, + PGPMain.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds, + signatureKeyId, PGPMain.getCachedPassPhrase(signatureKeyId), this, Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(), Preferences.getPreferences(this).getDefaultHashAlgorithm(), compressionId, Preferences.getPreferences(this).getForceV3Signatures(), @@ -373,20 +373,20 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { if (generateSignature) { Log.d(Constants.TAG, "generate signature..."); - PGPHelper.generateSignature(this, inputData, outStream, useAsciiArmour, true, - secretKeyId, PGPHelper.getCachedPassPhrase(secretKeyId), Preferences + PGPMain.generateSignature(this, inputData, outStream, useAsciiArmour, true, + secretKeyId, PGPMain.getCachedPassPhrase(secretKeyId), Preferences .getPreferences(this).getDefaultHashAlgorithm(), Preferences .getPreferences(this).getForceV3Signatures(), this); } else if (signOnly) { Log.d(Constants.TAG, "sign only..."); - PGPHelper.signText(this, inputData, outStream, secretKeyId, PGPHelper + PGPMain.signText(this, inputData, outStream, secretKeyId, PGPMain .getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this) .getDefaultHashAlgorithm(), Preferences.getPreferences(this) .getForceV3Signatures(), this); } else { Log.d(Constants.TAG, "encrypt..."); - PGPHelper.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds, - signatureKeyId, PGPHelper.getCachedPassPhrase(signatureKeyId), this, + PGPMain.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds, + signatureKeyId, PGPMain.getCachedPassPhrase(signatureKeyId), this, Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(), Preferences.getPreferences(this).getDefaultHashAlgorithm(), compressionId, Preferences.getPreferences(this).getForceV3Signatures(), @@ -420,16 +420,16 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { /* Operation */ // InputStream InputStream in = getContentResolver().openInputStream(providerUri); - long inLength = PGPHelper.getLengthOfStream(in); + long inLength = PGPMain.getLengthOfStream(in); InputData inputData = new InputData(in, inLength); // OutputStream String streamFilename = null; try { while (true) { - streamFilename = PGPHelper.generateRandomString(32); + streamFilename = PGPMain.generateRandomString(32); if (streamFilename == null) { - throw new PGPHelper.GeneralException( + throw new PGPMain.GeneralException( "couldn't generate random file name"); } openFileInput(streamFilename).close(); @@ -440,18 +440,18 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { FileOutputStream outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE); if (generateSignature) { - PGPHelper.generateSignature(this, inputData, outStream, useAsciiArmour, true, - secretKeyId, PGPHelper.getCachedPassPhrase(secretKeyId), Preferences + PGPMain.generateSignature(this, inputData, outStream, useAsciiArmour, true, + secretKeyId, PGPMain.getCachedPassPhrase(secretKeyId), Preferences .getPreferences(this).getDefaultHashAlgorithm(), Preferences .getPreferences(this).getForceV3Signatures(), this); } else if (signOnly) { - PGPHelper.signText(this, inputData, outStream, secretKeyId, PGPHelper + PGPMain.signText(this, inputData, outStream, secretKeyId, PGPMain .getCachedPassPhrase(secretKeyId), Preferences.getPreferences(this) .getDefaultHashAlgorithm(), Preferences.getPreferences(this) .getForceV3Signatures(), this); } else { - PGPHelper.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds, - signatureKeyId, PGPHelper.getCachedPassPhrase(signatureKeyId), this, + PGPMain.encrypt(this, inputData, outStream, useAsciiArmour, encryptionKeyIds, + signatureKeyId, PGPMain.getCachedPassPhrase(signatureKeyId), this, Preferences.getPreferences(this).getDefaultEncryptionAlgorithm(), Preferences.getPreferences(this).getDefaultHashAlgorithm(), compressionId, Preferences.getPreferences(this).getForceV3Signatures(), @@ -480,12 +480,12 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { /* Operation */ try { - PGPHelper.deleteFileSecurely(this, new File(deleteFile), this); + PGPMain.deleteFileSecurely(this, new File(deleteFile), this); } catch (FileNotFoundException e) { - throw new PGPHelper.GeneralException(getString(R.string.error_fileNotFound, + throw new PGPMain.GeneralException(getString(R.string.error_fileNotFound, deleteFile)); } catch (IOException e) { - throw new PGPHelper.GeneralException(getString(R.string.error_fileDeleteFailed, + throw new PGPMain.GeneralException(getString(R.string.error_fileDeleteFailed, deleteFile)); } @@ -518,10 +518,10 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // verifyText and decrypt returning additional resultData values for the // verification of signatures if (signedOnly) { - resultData = PGPHelper.verifyText(this, inputData, outStream, this); + resultData = PGPMain.verifyText(this, inputData, outStream, this); } else { - resultData = PGPHelper.decrypt(this, inputData, outStream, - PGPHelper.getCachedPassPhrase(secretKeyId), this, + resultData = PGPMain.decrypt(this, inputData, outStream, + PGPMain.getCachedPassPhrase(secretKeyId), this, assumeSymmetricEncryption); } @@ -577,10 +577,10 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // verifyText and decrypt returning additional output values for the // verification of signatures if (signedOnly) { - resultData = PGPHelper.verifyText(this, inputData, outStream, this); + resultData = PGPMain.verifyText(this, inputData, outStream, this); } else { - resultData = PGPHelper.decrypt(this, inputData, outStream, - PGPHelper.getCachedPassPhrase(secretKeyId), this, + resultData = PGPMain.decrypt(this, inputData, outStream, + PGPMain.getCachedPassPhrase(secretKeyId), this, assumeSymmetricEncryption); } @@ -604,16 +604,16 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { /* Operation */ // InputStream InputStream in = getContentResolver().openInputStream(providerUri); - long inLength = PGPHelper.getLengthOfStream(in); + long inLength = PGPMain.getLengthOfStream(in); InputData inputData = new InputData(in, inLength); // OutputStream String streamFilename = null; try { while (true) { - streamFilename = PGPHelper.generateRandomString(32); + streamFilename = PGPMain.generateRandomString(32); if (streamFilename == null) { - throw new PGPHelper.GeneralException( + throw new PGPMain.GeneralException( "couldn't generate random file name"); } openFileInput(streamFilename).close(); @@ -628,10 +628,10 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // verifyText and decrypt returning additional output values for the // verification of signatures if (signedOnly) { - resultData = PGPHelper.verifyText(this, inputData, outStream, this); + resultData = PGPMain.verifyText(this, inputData, outStream, this); } else { - resultData = PGPHelper.decrypt(this, inputData, outStream, - PGPHelper.getCachedPassPhrase(secretKeyId), this, + resultData = PGPMain.decrypt(this, inputData, outStream, + PGPMain.getCachedPassPhrase(secretKeyId), this, assumeSymmetricEncryption); } diff --git a/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java index 81d53a29d..542f65d3c 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java @@ -25,7 +25,7 @@ import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.ProgressDialogUpdater; import org.thialfihar.android.apg.deprecated.PausableThread; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.Preferences; import org.thialfihar.android.apg.passphrase.AskForPassphrase; import org.thialfihar.android.apg.passphrase.PassphraseCacheService; @@ -79,7 +79,7 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable, // not needed later: mPreferences = Preferences.getPreferences(this); - PGPHelper.initialize(this); + PGPMain.initialize(this); if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { File dir = new File(Constants.path.APP_DIR); @@ -378,7 +378,7 @@ public class BaseActivity extends SherlockFragmentActivity implements Runnable, public void passPhraseCallback(long keyId, String passPhrase) { // TODO: Not needed anymore, now implemented in AskForSecretKeyPass - PGPHelper.setCachedPassPhrase(keyId, passPhrase); + PGPMain.setCachedPassPhrase(keyId, passPhrase); } public void sendMessage(Message msg) { diff --git a/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java index 71835840e..b65aabd71 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java @@ -21,6 +21,7 @@ import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.FileHelper; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.service.ApgHandler; import org.thialfihar.android.apg.service.ApgService; import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment; @@ -299,7 +300,7 @@ public class DecryptActivity extends SherlockFragmentActivity { } if (textData != null) { Log.d(Constants.TAG, "textData null, matching text ..."); - Matcher matcher = PGPHelper.PGP_MESSAGE.matcher(textData); + Matcher matcher = PGPMain.PGP_MESSAGE.matcher(textData); if (matcher.matches()) { Log.d(Constants.TAG, "PGP_MESSAGE matched"); textData = matcher.group(1); @@ -307,7 +308,7 @@ public class DecryptActivity extends SherlockFragmentActivity { textData = textData.replaceAll("\\xa0", " "); mMessage.setText(textData); } else { - matcher = PGPHelper.PGP_SIGNED_MESSAGE.matcher(textData); + matcher = PGPMain.PGP_SIGNED_MESSAGE.matcher(textData); if (matcher.matches()) { Log.d(Constants.TAG, "PGP_SIGNED_MESSAGE matched"); textData = matcher.group(1); @@ -350,14 +351,14 @@ public class DecryptActivity extends SherlockFragmentActivity { mData = extras.getByteArray(EXTRA_DATA); String data = extras.getString(EXTRA_TEXT); if (data != null) { - Matcher matcher = PGPHelper.PGP_MESSAGE.matcher(data); + Matcher matcher = PGPMain.PGP_MESSAGE.matcher(data); if (matcher.matches()) { data = matcher.group(1); // replace non breakable spaces data = data.replaceAll("\\xa0", " "); mMessage.setText(data); } else { - matcher = PGPHelper.PGP_SIGNED_MESSAGE.matcher(data); + matcher = PGPMain.PGP_SIGNED_MESSAGE.matcher(data); if (matcher.matches()) { data = matcher.group(1); // replace non breakable spaces @@ -381,9 +382,9 @@ public class DecryptActivity extends SherlockFragmentActivity { String data = ""; if (clipboardText != null) { - Matcher matcher = PGPHelper.PGP_MESSAGE.matcher(clipboardText); + Matcher matcher = PGPMain.PGP_MESSAGE.matcher(clipboardText); if (!matcher.matches()) { - matcher = PGPHelper.PGP_SIGNED_MESSAGE.matcher(clipboardText); + matcher = PGPMain.PGP_SIGNED_MESSAGE.matcher(clipboardText); } if (matcher.matches()) { data = matcher.group(1); @@ -399,7 +400,7 @@ public class DecryptActivity extends SherlockFragmentActivity { if (mSignatureKeyId == 0) { return; } - PGPPublicKeyRing key = PGPHelper.getPublicKeyRing(mSignatureKeyId); + PGPPublicKeyRing key = PGPMain.getPublicKeyRing(mSignatureKeyId); if (key != null) { Intent intent = new Intent(DecryptActivity.this, KeyServerQueryActivity.class); intent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID); @@ -506,7 +507,7 @@ public class DecryptActivity extends SherlockFragmentActivity { if (mDecryptTarget == Id.target.message) { String messageData = mMessage.getText().toString(); - Matcher matcher = PGPHelper.PGP_SIGNED_MESSAGE.matcher(messageData); + Matcher matcher = PGPMain.PGP_SIGNED_MESSAGE.matcher(messageData); if (matcher.matches()) { mSignedOnly = true; decryptStart(); @@ -523,7 +524,7 @@ public class DecryptActivity extends SherlockFragmentActivity { // if we need a symmetric passphrase or a passphrase to use a sekret key ask for it if (getSecretKeyId() == Id.key.symmetric - || PGPHelper.getCachedPassPhrase(getSecretKeyId()) == null) { + || PGPMain.getCachedPassPhrase(getSecretKeyId()) == null) { // showDialog(Id.dialog.pass_phrase); showPassphraseDialog(); } else { @@ -563,7 +564,7 @@ public class DecryptActivity extends SherlockFragmentActivity { messenger, mSecretKeyId); passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PGPHelper.GeneralException e) { + } catch (PGPMain.GeneralException 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); @@ -609,15 +610,15 @@ public class DecryptActivity extends SherlockFragmentActivity { try { try { - setSecretKeyId(PGPHelper.getDecryptionKeyId(this, inStream)); + setSecretKeyId(PGPMain.getDecryptionKeyId(this, inStream)); if (getSecretKeyId() == Id.key.none) { - throw new PGPHelper.GeneralException(getString(R.string.error_noSecretKeyFound)); + throw new PGPMain.GeneralException(getString(R.string.error_noSecretKeyFound)); } mAssumeSymmetricEncryption = false; - } catch (PGPHelper.NoAsymmetricEncryptionException e) { + } catch (PGPMain.NoAsymmetricEncryptionException e) { setSecretKeyId(Id.key.symmetric); - if (!PGPHelper.hasSymmetricEncryption(this, inStream)) { - throw new PGPHelper.GeneralException( + if (!PGPMain.hasSymmetricEncryption(this, inStream)) { + throw new PGPMain.GeneralException( getString(R.string.error_noKnownEncryptionFound)); } mAssumeSymmetricEncryption = true; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java index f31d39381..855be57c5 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java @@ -22,6 +22,7 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.OtherHelper; import org.thialfihar.android.apg.helper.PGPConversionHelper; import org.thialfihar.android.apg.service.ApgHandler; @@ -256,7 +257,7 @@ public class EditKeyActivity extends SherlockFragmentActivity { } else if (ACTION_EDIT_KEY.equals(mIntent.getAction())) { mActionBar.setTitle(R.string.title_editKey); - mCurrentPassPhrase = PGPHelper.getEditPassPhrase(); + mCurrentPassPhrase = PGPMain.getEditPassPhrase(); if (mCurrentPassPhrase == null) { mCurrentPassPhrase = ""; } @@ -274,7 +275,7 @@ public class EditKeyActivity extends SherlockFragmentActivity { if (keyId != 0) { PGPSecretKey masterKey = null; - mKeyRing = PGPHelper.getSecretKeyRing(keyId); + mKeyRing = PGPMain.getSecretKeyRing(keyId); if (mKeyRing != null) { masterKey = PGPHelper.getMasterKey(mKeyRing); for (PGPSecretKey key : new IterableIterator( @@ -420,7 +421,7 @@ public class EditKeyActivity extends SherlockFragmentActivity { try { if (!isPassphraseSet()) { - throw new PGPHelper.GeneralException(this.getString(R.string.setAPassPhrase)); + throw new PGPMain.GeneralException(this.getString(R.string.setAPassPhrase)); } // Send all information needed to service to edit key in other thread @@ -464,7 +465,7 @@ public class EditKeyActivity extends SherlockFragmentActivity { // start service with intent startService(intent); - } catch (PGPHelper.GeneralException e) { + } catch (PGPMain.GeneralException e) { Toast.makeText(this, getString(R.string.errorMessage, e.getMessage()), Toast.LENGTH_SHORT).show(); } @@ -476,7 +477,7 @@ public class EditKeyActivity extends SherlockFragmentActivity { * @param userIdsView * @return */ - private Vector getUserIds(SectionView userIdsView) throws PGPHelper.GeneralException { + private Vector getUserIds(SectionView userIdsView) throws PGPMain.GeneralException { Vector userIds = new Vector(); ViewGroup userIdEditors = userIdsView.getEditors(); @@ -488,13 +489,13 @@ public class EditKeyActivity extends SherlockFragmentActivity { try { userId = editor.getValue(); } catch (UserIdEditor.NoNameException e) { - throw new PGPHelper.GeneralException( + throw new PGPMain.GeneralException( this.getString(R.string.error_userIdNeedsAName)); } catch (UserIdEditor.NoEmailException e) { - throw new PGPHelper.GeneralException( + throw new PGPMain.GeneralException( this.getString(R.string.error_userIdNeedsAnEmailAddress)); } catch (UserIdEditor.InvalidEmailException e) { - throw new PGPHelper.GeneralException(e.getMessage()); + throw new PGPMain.GeneralException(e.getMessage()); } if (userId.equals("")) { @@ -510,11 +511,11 @@ public class EditKeyActivity extends SherlockFragmentActivity { } if (userIds.size() == 0) { - throw new PGPHelper.GeneralException(getString(R.string.error_keyNeedsAUserId)); + throw new PGPMain.GeneralException(getString(R.string.error_keyNeedsAUserId)); } if (!gotMainUserId) { - throw new PGPHelper.GeneralException(getString(R.string.error_mainUserIdMustNotBeEmpty)); + throw new PGPMain.GeneralException(getString(R.string.error_mainUserIdMustNotBeEmpty)); } return userIds; @@ -526,13 +527,13 @@ public class EditKeyActivity extends SherlockFragmentActivity { * @param keysView * @return */ - private Vector getKeys(SectionView keysView) throws PGPHelper.GeneralException { + private Vector getKeys(SectionView keysView) throws PGPMain.GeneralException { Vector keys = new Vector(); ViewGroup keyEditors = keysView.getEditors(); if (keyEditors.getChildCount() == 0) { - throw new PGPHelper.GeneralException(getString(R.string.error_keyNeedsMasterKey)); + throw new PGPMain.GeneralException(getString(R.string.error_keyNeedsMasterKey)); } for (int i = 0; i < keyEditors.getChildCount(); ++i) { @@ -549,13 +550,13 @@ public class EditKeyActivity extends SherlockFragmentActivity { * @param keysView * @return */ - private Vector getKeysUsages(SectionView keysView) throws PGPHelper.GeneralException { + private Vector getKeysUsages(SectionView keysView) throws PGPMain.GeneralException { Vector getKeysUsages = new Vector(); ViewGroup keyEditors = keysView.getEditors(); if (keyEditors.getChildCount() == 0) { - throw new PGPHelper.GeneralException(getString(R.string.error_keyNeedsMasterKey)); + throw new PGPMain.GeneralException(getString(R.string.error_keyNeedsMasterKey)); } for (int i = 0; i < keyEditors.getChildCount(); ++i) { diff --git a/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java index c01a1efb6..b0013f588 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java @@ -25,6 +25,7 @@ import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.FileHelper; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.Preferences; import org.thialfihar.android.apg.service.ApgHandler; import org.thialfihar.android.apg.service.ApgService; @@ -390,7 +391,7 @@ public class EncryptActivity extends SherlockFragmentActivity { long signatureKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID); long encryptionKeyIds[] = extras.getLongArray(EXTRA_ENCRYPTION_KEY_IDS); if (signatureKeyId != 0) { - PGPSecretKeyRing keyRing = PGPHelper.getSecretKeyRing(signatureKeyId); + PGPSecretKeyRing keyRing = PGPMain.getSecretKeyRing(signatureKeyId); PGPSecretKey masterKey = null; if (keyRing != null) { masterKey = PGPHelper.getMasterKey(keyRing); @@ -406,7 +407,7 @@ public class EncryptActivity extends SherlockFragmentActivity { if (encryptionKeyIds != null) { Vector goodIds = new Vector(); for (int i = 0; i < encryptionKeyIds.length; ++i) { - PGPPublicKeyRing keyRing = PGPHelper.getPublicKeyRing(encryptionKeyIds[i]); + PGPPublicKeyRing keyRing = PGPMain.getPublicKeyRing(encryptionKeyIds[i]); PGPPublicKey masterKey = null; if (keyRing == null) { continue; @@ -669,7 +670,7 @@ public class EncryptActivity extends SherlockFragmentActivity { return; } - if (getSecretKeyId() != 0 && PGPHelper.getCachedPassPhrase(getSecretKeyId()) == null) { + if (getSecretKeyId() != 0 && PGPMain.getCachedPassPhrase(getSecretKeyId()) == null) { showPassphraseDialog(); return; @@ -710,7 +711,7 @@ public class EncryptActivity extends SherlockFragmentActivity { messenger, mSecretKeyId); passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PGPHelper.GeneralException e) { + } catch (PGPMain.GeneralException 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); @@ -935,7 +936,7 @@ public class EncryptActivity extends SherlockFragmentActivity { } else { String uid = getResources().getString(R.string.unknownUserId); String uidExtra = ""; - PGPSecretKeyRing keyRing = PGPHelper.getSecretKeyRing(getSecretKeyId()); + PGPSecretKeyRing keyRing = PGPMain.getSecretKeyRing(getSecretKeyId()); if (keyRing != null) { PGPSecretKey key = PGPHelper.getMasterKey(keyRing); if (key != null) { diff --git a/org_apg/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java index 9ab992d60..854427b02 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java @@ -24,6 +24,7 @@ import org.spongycastle.openpgp.PGPPublicKeyRing; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.util.HkpKeyServer; import org.thialfihar.android.apg.util.KeyServer.QueryException; import org.thialfihar.android.apg.R; @@ -83,7 +84,7 @@ public class ImportFromQRCodeActivity extends BaseActivity { .getPublicKey().getFingerprint()); if (expectedFingerprint.equals(actualFingerprint)) { // store the signed key in our local cache - int retval = PGPHelper.storeKeyRingInCache(publicKeyRing); + int retval = PGPMain.storeKeyRingInCache(publicKeyRing); if (retval != Id.return_value.ok && retval != Id.return_value.updated) { status.putString(EXTRA_ERROR, diff --git a/org_apg/src/org/thialfihar/android/apg/ui/KeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/KeyListActivity.java index 2ad64f91e..9c378cba1 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/KeyListActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/KeyListActivity.java @@ -22,6 +22,7 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.provider.KeyRings; import org.thialfihar.android.apg.provider.Keys; import org.thialfihar.android.apg.provider.UserIds; @@ -269,7 +270,7 @@ public class KeyListActivity extends BaseActivity { mSelectedItem = -1; // TODO: better way to do this? String userId = ""; - Object keyRing = PGPHelper.getKeyRing(keyRingId); + Object keyRing = PGPMain.getKeyRing(keyRingId); if (keyRing != null) { if (keyRing instanceof PGPPublicKeyRing) { userId = PGPHelper.getMainUserIdSafe(this, @@ -344,12 +345,12 @@ public class KeyListActivity extends BaseActivity { } if (mTask == Id.task.import_keys) { - data = PGPHelper.importKeyRings(this, mKeyType, new InputData(importInputStream, + data = PGPMain.importKeyRings(this, mKeyType, new InputData(importInputStream, size), this); } else { Vector keyRingIds = new Vector(); if (mSelectedItem == -1) { - keyRingIds = PGPHelper + keyRingIds = PGPMain .getKeyRingIds(mKeyType == Id.type.public_key ? Id.database.type_public : Id.database.type_secret); } else { @@ -357,7 +358,7 @@ public class KeyListActivity extends BaseActivity { keyRingIds.add(keyRingId); mSelectedItem = -1; } - data = PGPHelper.exportKeyRings(this, keyRingIds, exportOutputStream, this); + data = PGPMain.exportKeyRings(this, keyRingIds, exportOutputStream, this); } } catch (FileNotFoundException e) { error = getString(R.string.error_fileNotFound); @@ -365,7 +366,7 @@ public class KeyListActivity extends BaseActivity { error = "" + e; } catch (PGPException e) { error = "" + e; - } catch (PGPHelper.GeneralException e) { + } catch (PGPMain.GeneralException e) { error = "" + e; } @@ -386,7 +387,7 @@ public class KeyListActivity extends BaseActivity { } protected void deleteKey(int keyRingId) { - PGPHelper.deleteKey(keyRingId); + PGPMain.deleteKey(keyRingId); refreshList(); } @@ -527,7 +528,7 @@ public class KeyListActivity extends BaseActivity { mSearchString = searchString; mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mDatabase = PGPHelper.getDatabase().db(); + mDatabase = PGPMain.getDatabase().db(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + Keys.TABLE_NAME + "." diff --git a/org_apg/src/org/thialfihar/android/apg/ui/KeyServerExportActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/KeyServerExportActivity.java index cf14492b6..a15468bed 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/KeyServerExportActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/KeyServerExportActivity.java @@ -21,7 +21,7 @@ import org.spongycastle.openpgp.PGPPublicKeyRing; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.util.HkpKeyServer; import com.actionbarsherlock.view.MenuItem; @@ -110,9 +110,9 @@ public class KeyServerExportActivity extends BaseActivity { int keyRingId = getIntent().getIntExtra(EXTRA_KEY_ID, -1); - PGPKeyRing keyring = PGPHelper.getKeyRing(keyRingId); + PGPKeyRing keyring = PGPMain.getKeyRing(keyRingId); if (keyring != null && keyring instanceof PGPPublicKeyRing) { - boolean uploaded = PGPHelper.uploadKeyRingToServer(server, (PGPPublicKeyRing) keyring); + boolean uploaded = PGPMain.uploadKeyRingToServer(server, (PGPPublicKeyRing) keyring); if (!uploaded) { error = "Unable to export key to selected server"; } diff --git a/org_apg/src/org/thialfihar/android/apg/ui/KeyServerQueryActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/KeyServerQueryActivity.java index ec140e8d2..1cb7ecaca 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/KeyServerQueryActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/KeyServerQueryActivity.java @@ -21,6 +21,7 @@ import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.util.HkpKeyServer; import org.thialfihar.android.apg.util.KeyServer.InsufficientQuery; import org.thialfihar.android.apg.util.KeyServer.KeyInfo; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/MailListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/MailListActivity.java index 3b32265a8..85d9d6ce5 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/MailListActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/MailListActivity.java @@ -20,7 +20,7 @@ import java.util.Vector; import java.util.regex.Matcher; import org.thialfihar.android.apg.R; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.Preferences; import android.app.ListActivity; @@ -121,11 +121,11 @@ public class MailListActivity extends ListActivity { String data = messageCursor.getString(bodyIndex); data = Html.fromHtml(data).toString(); boolean signedOnly = false; - Matcher matcher = PGPHelper.PGP_MESSAGE.matcher(data); + Matcher matcher = PGPMain.PGP_MESSAGE.matcher(data); if (matcher.matches()) { data = matcher.group(1); } else { - matcher = PGPHelper.PGP_SIGNED_MESSAGE.matcher(data); + matcher = PGPMain.PGP_SIGNED_MESSAGE.matcher(data); if (matcher.matches()) { data = matcher.group(1); signedOnly = true; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/MainActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/MainActivity.java index 465daf5c9..db30b0671 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/MainActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/MainActivity.java @@ -22,7 +22,7 @@ import java.security.Security; import org.spongycastle.jce.provider.BouncyCastleProvider; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockActivity; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java index b56fb676c..84beee428 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/PreferencesActivity.java @@ -20,7 +20,7 @@ import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.openpgp.PGPEncryptedData; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.Preferences; import org.thialfihar.android.apg.passphrase.PassphraseCacheService; import org.thialfihar.android.apg.ui.widget.IntegerListPreference; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/PreferencesKeyServerActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/PreferencesKeyServerActivity.java index 9e8b638aa..ee193cdd5 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/PreferencesKeyServerActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/PreferencesKeyServerActivity.java @@ -20,7 +20,7 @@ import java.util.Vector; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.ui.widget.Editor; import org.thialfihar.android.apg.ui.widget.KeyServerEditor; import org.thialfihar.android.apg.ui.widget.Editor.EditorListener; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/PublicKeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/PublicKeyListActivity.java index 30205fe7b..601f467aa 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/PublicKeyListActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/PublicKeyListActivity.java @@ -21,6 +21,7 @@ import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; @@ -115,7 +116,7 @@ public class PublicKeyListActivity extends KeyListActivity { mSelectedItem = groupPosition; final int keyRingId = mListAdapter.getKeyRingId(groupPosition); long keyId = 0; - Object keyRing = PGPHelper.getKeyRing(keyRingId); + Object keyRing = PGPMain.getKeyRing(keyRingId); if (keyRing != null && keyRing instanceof PGPPublicKeyRing) { keyId = PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID(); } @@ -148,7 +149,7 @@ public class PublicKeyListActivity extends KeyListActivity { mSelectedItem = groupPosition; final int keyRingId = mListAdapter.getKeyRingId(groupPosition); long keyId = 0; - Object keyRing = PGPHelper.getKeyRing(keyRingId); + Object keyRing = PGPMain.getKeyRing(keyRingId); if (keyRing != null && keyRing instanceof PGPPublicKeyRing) { keyId = PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing).getKeyID(); } diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java index 18b051571..60c6a6ef6 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java @@ -20,6 +20,7 @@ import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.passphrase.AskForPassphrase; import com.actionbarsherlock.view.Menu; @@ -146,11 +147,11 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli public void checkPassPhraseAndEdit() { long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem); - String passPhrase = PGPHelper.getCachedPassPhrase(keyId); + String passPhrase = PGPMain.getCachedPassPhrase(keyId); if (passPhrase == null) { showDialog(Id.dialog.pass_phrase); } else { - PGPHelper.setEditPassPhrase(passPhrase); + PGPMain.setEditPassPhrase(passPhrase); editKey(); } } @@ -158,12 +159,12 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli @Override public void passPhraseCallback(long keyId, String passPhrase) { super.passPhraseCallback(keyId, passPhrase); - PGPHelper.setEditPassPhrase(passPhrase); + PGPMain.setEditPassPhrase(passPhrase); editKey(); } private void createKey() { - PGPHelper.setEditPassPhrase(""); + PGPMain.setEditPassPhrase(""); Intent intent = new Intent(EditKeyActivity.ACTION_CREATE_KEY); startActivityForResult(intent, Id.message.create_key); } diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SelectPublicKeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SelectPublicKeyListActivity.java index 903631ffd..fb7e5a0dd 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/SelectPublicKeyListActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/SelectPublicKeyListActivity.java @@ -21,7 +21,7 @@ import java.util.Vector; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Id; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.ui.widget.SelectPublicKeyListAdapter; import com.actionbarsherlock.app.ActionBar; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SelectSecretKeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SelectSecretKeyListActivity.java index dafe9a4c2..865fab789 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/SelectSecretKeyListActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/SelectSecretKeyListActivity.java @@ -19,7 +19,7 @@ package org.thialfihar.android.apg.ui; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Id; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.ui.widget.SelectSecretKeyListAdapter; import com.actionbarsherlock.app.ActionBar; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java index 5781410c5..d4985fdb5 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java @@ -35,7 +35,7 @@ import org.spongycastle.openpgp.PGPUtil; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.util.HkpKeyServer; import com.actionbarsherlock.view.MenuItem; @@ -143,7 +143,7 @@ public class SignKeyActivity extends BaseActivity { * handles the UI bits of the signing process on the UI thread */ private void initiateSigning() { - PGPPublicKeyRing pubring = PGPHelper.getPublicKeyRing(pubKeyId); + PGPPublicKeyRing pubring = PGPMain.getPublicKeyRing(pubKeyId); if (pubring != null) { // if we have already signed this key, dont bother doing it again boolean alreadySigned = false; @@ -162,7 +162,7 @@ public class SignKeyActivity extends BaseActivity { /* * get the user's passphrase for this key (if required) */ - String passphrase = PGPHelper.getCachedPassPhrase(masterKeyId); + String passphrase = PGPMain.getCachedPassPhrase(masterKeyId); if (passphrase == null) { showDialog(Id.dialog.pass_phrase); return; // bail out; need to wait until the user has entered the passphrase @@ -212,16 +212,16 @@ public class SignKeyActivity extends BaseActivity { Message msg = new Message(); try { - String passphrase = PGPHelper.getCachedPassPhrase(masterKeyId); + String passphrase = PGPMain.getCachedPassPhrase(masterKeyId); if (passphrase == null || passphrase.length() <= 0) { status.putString(EXTRA_ERROR, "Unable to obtain passphrase"); } else { - PGPPublicKeyRing pubring = PGPHelper.getPublicKeyRing(pubKeyId); + PGPPublicKeyRing pubring = PGPMain.getPublicKeyRing(pubKeyId); /* * sign the incoming key */ - PGPSecretKey secretKey = PGPHelper.getSecretKey(masterKeyId); + PGPSecretKey secretKey = PGPMain.getSecretKey(masterKeyId); PGPPrivateKey signingKey = secretKey.extractPrivateKey(passphrase.toCharArray(), BouncyCastleProvider.PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(secretKey.getPublicKey() @@ -247,11 +247,11 @@ public class SignKeyActivity extends BaseActivity { * upload the newly signed key to the key server */ - PGPHelper.uploadKeyRingToServer(server, pubring); + PGPMain.uploadKeyRingToServer(server, pubring); } // store the signed key in our local cache - int retval = PGPHelper.storeKeyRingInCache(pubring); + int retval = PGPMain.storeKeyRingInCache(pubring); if (retval != Id.return_value.ok && retval != Id.return_value.updated) { status.putString(EXTRA_ERROR, "Failed to store signed key in local cache"); } diff --git a/org_apg/src/org/thialfihar/android/apg/ui/dialog/FileDialogFragment.java b/org_apg/src/org/thialfihar/android/apg/ui/dialog/FileDialogFragment.java index 531cddfcf..2a83febc2 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/dialog/FileDialogFragment.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/dialog/FileDialogFragment.java @@ -19,7 +19,6 @@ package org.thialfihar.android.apg.ui.dialog; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.helper.FileHelper; -import org.thialfihar.android.apg.helper.OtherHelper; import android.app.Activity; import android.app.AlertDialog; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java b/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java index ce08c6c86..21dcc1b09 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java @@ -22,7 +22,8 @@ import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.thialfihar.android.apg.helper.PGPHelper; -import org.thialfihar.android.apg.helper.PGPHelper.GeneralException; +import org.thialfihar.android.apg.helper.PGPMain; +import org.thialfihar.android.apg.helper.PGPMain.GeneralException; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; @@ -68,7 +69,7 @@ public class PassphraseDialogFragment extends DialogFragment { // check if secret key has a passphrase if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) { if (!hasPassphrase(secretKeyId)) { - throw new PGPHelper.GeneralException("No passphrase! No passphrase dialog needed!"); + throw new PGPMain.GeneralException("No passphrase! No passphrase dialog needed!"); } } @@ -91,7 +92,8 @@ public class PassphraseDialogFragment extends DialogFragment { private static boolean hasPassphrase(long secretKeyId) { // check if the key has no passphrase try { - PGPSecretKey secretKey = PGPHelper.getMasterKey(PGPHelper.getSecretKeyRing(secretKeyId)); + PGPSecretKey secretKey = PGPHelper.getMasterKey(PGPMain + .getSecretKeyRing(secretKeyId)); Log.d(Constants.TAG, "Check if key has no passphrase..."); PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( @@ -101,7 +103,7 @@ public class PassphraseDialogFragment extends DialogFragment { Log.d(Constants.TAG, "Key has no passphrase! Caches empty passphrase!"); // cache empty passphrase - PGPHelper.setCachedPassPhrase(secretKey.getKeyID(), ""); + PGPMain.setCachedPassPhrase(secretKey.getKeyID(), ""); return false; } @@ -132,7 +134,7 @@ public class PassphraseDialogFragment extends DialogFragment { secretKey = null; alert.setMessage(getString(R.string.passPhraseForSymmetricEncryption)); } else { - secretKey = PGPHelper.getMasterKey(PGPHelper.getSecretKeyRing(secretKeyId)); + secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId)); if (secretKey == null) { alert.setTitle(R.string.title_keyNotFound); alert.setMessage(getString(R.string.keyNotFound, secretKeyId)); @@ -189,7 +191,7 @@ public class PassphraseDialogFragment extends DialogFragment { // cache the new passphrase Log.d(Constants.TAG, "Everything okay! Caching entered passphrase"); - PGPHelper.setCachedPassPhrase(keyId, passPhrase); + PGPMain.setCachedPassPhrase(keyId, passPhrase); sendMessageToHandler(MESSAGE_OKAY); } diff --git a/org_apg/src/org/thialfihar/android/apg/ui/widget/KeyEditor.java b/org_apg/src/org/thialfihar/android/apg/ui/widget/KeyEditor.java index 87d715fd9..6efe17c6d 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/widget/KeyEditor.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/widget/KeyEditor.java @@ -20,6 +20,7 @@ import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSecretKey; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.util.Choice; import org.thialfihar.android.apg.R; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java b/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java index 22a2ecb5b..4bedd1ede 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java @@ -19,7 +19,7 @@ package org.thialfihar.android.apg.ui.widget; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.Id; -import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.PGPConversionHelper; import org.thialfihar.android.apg.service.ApgHandler; import org.thialfihar.android.apg.service.ApgService; @@ -259,7 +259,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor String passPhrase; if (mEditors.getChildCount() > 0) { PGPSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue(); - passPhrase = PGPHelper.getCachedPassPhrase(masterKey.getKeyID()); + passPhrase = PGPMain.getCachedPassPhrase(masterKey.getKeyID()); data.putByteArray(ApgService.MASTER_KEY, PGPConversionHelper.PGPSecretKeyToBytes(masterKey)); diff --git a/org_apg/src/org/thialfihar/android/apg/ui/widget/SelectPublicKeyListAdapter.java b/org_apg/src/org/thialfihar/android/apg/ui/widget/SelectPublicKeyListAdapter.java index 240d6a078..ee78e8f88 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/widget/SelectPublicKeyListAdapter.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/widget/SelectPublicKeyListAdapter.java @@ -21,6 +21,7 @@ import java.util.Date; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.provider.KeyRings; import org.thialfihar.android.apg.provider.Keys; import org.thialfihar.android.apg.provider.UserIds; @@ -53,7 +54,7 @@ public class SelectPublicKeyListAdapter extends BaseAdapter { mActivity = activity; mParent = parent; - mDatabase = PGPHelper.getDatabase().db(); + mDatabase = PGPMain.getDatabase().db(); mInflater = (LayoutInflater) parent.getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); long now = new Date().getTime() / 1000; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/widget/SelectSecretKeyListAdapter.java b/org_apg/src/org/thialfihar/android/apg/ui/widget/SelectSecretKeyListAdapter.java index fc8c4e8b0..2caa593ff 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/widget/SelectSecretKeyListAdapter.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/widget/SelectSecretKeyListAdapter.java @@ -19,6 +19,7 @@ import java.util.Date; import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.provider.KeyRings; import org.thialfihar.android.apg.provider.Keys; import org.thialfihar.android.apg.provider.UserIds; @@ -48,7 +49,7 @@ public class SelectSecretKeyListAdapter extends BaseAdapter { mActivity = activity; mParent = parent; - mDatabase = PGPHelper.getDatabase().db(); + mDatabase = PGPMain.getDatabase().db(); mInflater = (LayoutInflater) parent.getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); long now = new Date().getTime() / 1000; diff --git a/org_apg/src/org/thialfihar/android/apg/util/HkpKeyServer.java b/org_apg/src/org/thialfihar/android/apg/util/HkpKeyServer.java index 38f3e2dc3..bdef7b59e 100644 --- a/org_apg/src/org/thialfihar/android/apg/util/HkpKeyServer.java +++ b/org_apg/src/org/thialfihar/android/apg/util/HkpKeyServer.java @@ -45,6 +45,7 @@ import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.thialfihar.android.apg.helper.PGPHelper; +import org.thialfihar.android.apg.helper.PGPMain; import android.text.Html; @@ -223,7 +224,7 @@ public class HkpKeyServer extends KeyServer { HttpEntity entity = response.getEntity(); InputStream is = entity.getContent(); String data = readAll(is, EntityUtils.getContentCharSet(entity)); - Matcher matcher = PGPHelper.PGP_PUBLIC_KEY.matcher(data); + Matcher matcher = PGPMain.PGP_PUBLIC_KEY.matcher(data); if (matcher.find()) { return matcher.group(1); }