diff options
author | Dominik <dominik@dominikschuermann.de> | 2012-03-10 20:22:29 +0100 |
---|---|---|
committer | Dominik <dominik@dominikschuermann.de> | 2012-03-10 20:22:29 +0100 |
commit | 630780cae4683e8ba403b28da84f963221d80ee3 (patch) | |
tree | 74ee9eac3a4c5640451e88b29a1b3350ca538def /src/org/apg/Apg.java | |
parent | 3fd5a55516eace832d2d2300ebf7a2579ab9c6dc (diff) | |
download | open-keychain-630780cae4683e8ba403b28da84f963221d80ee3.tar.gz open-keychain-630780cae4683e8ba403b28da84f963221d80ee3.tar.bz2 open-keychain-630780cae4683e8ba403b28da84f963221d80ee3.zip |
new directory structure
Diffstat (limited to 'src/org/apg/Apg.java')
-rw-r--r-- | src/org/apg/Apg.java | 2283 |
1 files changed, 0 insertions, 2283 deletions
diff --git a/src/org/apg/Apg.java b/src/org/apg/Apg.java deleted file mode 100644 index 2bfdb31e6..000000000 --- a/src/org/apg/Apg.java +++ /dev/null @@ -1,2283 +0,0 @@ -/* - * Copyright (C) 2010 Thialfihar <thi@thialfihar.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apg; - -import org.apg.KeyServer.AddKeyException; -import org.apg.provider.DataProvider; -import org.apg.provider.Database; -import org.apg.provider.KeyRings; -import org.apg.provider.Keys; -import org.apg.provider.UserIds; -import org.apg.ui.BaseActivity; -import org.apg.ui.widget.KeyEditor; -import org.apg.ui.widget.SectionView; -import org.apg.ui.widget.UserIdEditor; -import org.apg.util.IterableIterator; -import org.spongycastle.bcpg.ArmoredInputStream; -import org.spongycastle.bcpg.ArmoredOutputStream; -import org.spongycastle.bcpg.BCPGOutputStream; -import org.spongycastle.bcpg.CompressionAlgorithmTags; -import org.spongycastle.bcpg.HashAlgorithmTags; -import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; -import org.spongycastle.bcpg.sig.KeyFlags; -import org.spongycastle.jce.provider.BouncyCastleProvider; -import org.spongycastle.jce.spec.ElGamalParameterSpec; -import org.spongycastle.openpgp.PGPCompressedData; -import org.spongycastle.openpgp.PGPCompressedDataGenerator; -import org.spongycastle.openpgp.PGPEncryptedData; -import org.spongycastle.openpgp.PGPEncryptedDataGenerator; -import org.spongycastle.openpgp.PGPEncryptedDataList; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPKeyPair; -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPKeyRingGenerator; -import org.spongycastle.openpgp.PGPLiteralData; -import org.spongycastle.openpgp.PGPLiteralDataGenerator; -import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPOnePassSignature; -import org.spongycastle.openpgp.PGPOnePassSignatureList; -import org.spongycastle.openpgp.PGPPBEEncryptedData; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyEncryptedData; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.PGPSignatureGenerator; -import org.spongycastle.openpgp.PGPSignatureList; -import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; -import org.spongycastle.openpgp.PGPSignatureSubpacketVector; -import org.spongycastle.openpgp.PGPUtil; -import org.spongycastle.openpgp.PGPV3SignatureGenerator; -import org.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.os.Message; -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.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SecureRandom; -import java.security.Security; -import java.security.SignatureException; -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; - -public class Apg { - private static final String mApgPackageName = "org.thialfihar.android.apg"; - - public static class Intent { - public static final String DECRYPT = "org.thialfihar.android.apg.intent.DECRYPT"; - public static final String ENCRYPT = "org.thialfihar.android.apg.intent.ENCRYPT"; - public static final String DECRYPT_FILE = "org.thialfihar.android.apg.intent.DECRYPT_FILE"; - public static final String ENCRYPT_FILE = "org.thialfihar.android.apg.intent.ENCRYPT_FILE"; - public static final String DECRYPT_AND_RETURN = "org.thialfihar.android.apg.intent.DECRYPT_AND_RETURN"; - public static final String ENCRYPT_AND_RETURN = "org.thialfihar.android.apg.intent.ENCRYPT_AND_RETURN"; - public static final String SELECT_PUBLIC_KEYS = "org.thialfihar.android.apg.intent.SELECT_PUBLIC_KEYS"; - public static final String SELECT_SECRET_KEY = "org.thialfihar.android.apg.intent.SELECT_SECRET_KEY"; - public static final String IMPORT = "org.thialfihar.android.apg.intent.IMPORT"; - public static final String LOOK_UP_KEY_ID = "org.thialfihar.android.apg.intent.LOOK_UP_KEY_ID"; - public static final String LOOK_UP_KEY_ID_AND_RETURN = "org.thialfihar.android.apg.intent.LOOK_UP_KEY_ID_AND_RETURN"; - public static final String GENERATE_SIGNATURE = "org.thialfihar.android.apg.intent.GENERATE_SIGNATURE"; - public static final String EXPORT_KEY_TO_SERVER = "org.thialfihar.android.apg.intent.EXPORT_KEY_TO_SERVER"; - public static final String IMPORT_FROM_QR_CODE = "org.thialfihar.android.apg.intent.IMPORT_FROM_QR_CODE"; - } - - public static final String EXTRA_TEXT = "text"; - public static final String EXTRA_DATA = "data"; - public static final String EXTRA_ERROR = "error"; - public static final String EXTRA_DECRYPTED_MESSAGE = "decryptedMessage"; - public static final String EXTRA_DECRYPTED_DATA = "decryptedData"; - public static final String EXTRA_ENCRYPTED_MESSAGE = "encryptedMessage"; - public static final String EXTRA_ENCRYPTED_DATA = "encryptedData"; - public static final String EXTRA_RESULT_URI = "resultUri"; - public static final String EXTRA_SIGNATURE = "signature"; - public static final String EXTRA_SIGNATURE_KEY_ID = "signatureKeyId"; - public static final String EXTRA_SIGNATURE_USER_ID = "signatureUserId"; - public static final String EXTRA_SIGNATURE_SUCCESS = "signatureSuccess"; - public static final String EXTRA_SIGNATURE_UNKNOWN = "signatureUnknown"; - public static final String EXTRA_SIGNATURE_DATA = "signatureData"; - public static final String EXTRA_SIGNATURE_TEXT = "signatureText"; - public static final String EXTRA_USER_ID = "userId"; - public static final String EXTRA_USER_IDS = "userIds"; - public static final String EXTRA_KEY_ID = "keyId"; - public static final String EXTRA_REPLY_TO = "replyTo"; - public static final String EXTRA_SEND_TO = "sendTo"; - public static final String EXTRA_SUBJECT = "subject"; - public static final String EXTRA_ENCRYPTION_KEY_IDS = "encryptionKeyIds"; - public static final String EXTRA_SELECTION = "selection"; - public static final String EXTRA_ASCII_ARMOUR = "asciiArmour"; - public static final String EXTRA_BINARY = "binary"; - public static final String EXTRA_KEY_SERVERS = "keyServers"; - public static final String EXTRA_EXPECTED_FINGERPRINT = "org.thialfihar.android.apg.EXPECTED_FINGERPRINT"; - - 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<Long, CachedPassPhrase> mPassPhraseCache = new HashMap<Long, CachedPassPhrase>(); - 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<Long> oldKeys = new Vector<Long>(); - for (Map.Entry<Long, CachedPassPhrase> 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; - } - - public static PGPSecretKey createKey(Context context, int algorithmChoice, int keySize, - String passPhrase, PGPSecretKey masterKey) throws NoSuchAlgorithmException, - PGPException, NoSuchProviderException, GeneralException, - InvalidAlgorithmParameterException { - - if (keySize < 512) { - throw new GeneralException(context.getString(R.string.error_keySizeMinimum512bit)); - } - - Security.addProvider(new BouncyCastleProvider()); - - if (passPhrase == null) { - passPhrase = ""; - } - - int algorithm = 0; - KeyPairGenerator keyGen = null; - - switch (algorithmChoice) { - case Id.choice.algorithm.dsa: { - keyGen = KeyPairGenerator.getInstance("DSA", new BouncyCastleProvider()); - keyGen.initialize(keySize, new SecureRandom()); - algorithm = PGPPublicKey.DSA; - break; - } - - case Id.choice.algorithm.elgamal: { - if (masterKey == null) { - throw new GeneralException( - context.getString(R.string.error_masterKeyMustNotBeElGamal)); - } - keyGen = KeyPairGenerator.getInstance("ELGAMAL", new BouncyCastleProvider()); - 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", new BouncyCastleProvider()); - keyGen.initialize(keySize, new SecureRandom()); - - algorithm = PGPPublicKey.RSA_GENERAL; - break; - } - - default: { - throw new GeneralException(context.getString(R.string.error_unknownAlgorithmChoice)); - } - } - - PGPKeyPair keyPair = new PGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date()); - - PGPSecretKey secretKey = null; - if (masterKey == null) { - // enough for now, as we assemble the key again later anyway - secretKey = new PGPSecretKey(PGPSignature.DEFAULT_CERTIFICATION, keyPair, "", - PGPEncryptedData.CAST5, passPhrase.toCharArray(), null, null, - new SecureRandom(), new BouncyCastleProvider().getName()); - - } else { - PGPPublicKey tmpKey = masterKey.getPublicKey(); - PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(), - tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime()); - PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(passPhrase.toCharArray(), - new BouncyCastleProvider()); - - PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey); - PGPKeyRingGenerator ringGen = new PGPKeyRingGenerator( - PGPSignature.POSITIVE_CERTIFICATION, masterKeyPair, "", PGPEncryptedData.CAST5, - passPhrase.toCharArray(), null, null, new SecureRandom(), - new BouncyCastleProvider().getName()); - ringGen.addSubKey(keyPair); - PGPSecretKeyRing secKeyRing = ringGen.generateSecretKeyRing(); - Iterator<PGPSecretKey> it = secKeyRing.getSecretKeys(); - // first one is the master key - it.next(); - secretKey = it.next(); - } - - return secretKey; - } - - private static long getNumDaysBetween(GregorianCalendar first, GregorianCalendar second) { - GregorianCalendar tmp = new GregorianCalendar(); - tmp.setTime(first.getTime()); - long numDays = (second.getTimeInMillis() - first.getTimeInMillis()) / 1000 / 86400; - tmp.add(Calendar.DAY_OF_MONTH, (int) numDays); - while (tmp.before(second)) { - tmp.add(Calendar.DAY_OF_MONTH, 1); - ++numDays; - } - return numDays; - } - - public static void buildSecretKey(Activity context, SectionView userIdsView, - SectionView keysView, String oldPassPhrase, String newPassPhrase, - ProgressDialogUpdater progress) throws Apg.GeneralException, NoSuchProviderException, - PGPException, NoSuchAlgorithmException, SignatureException, IOException, - Database.GeneralException { - - if (progress != null) - progress.setProgress(R.string.progress_buildingKey, 0, 100); - - Security.addProvider(new BouncyCastleProvider()); - - if (oldPassPhrase == null || oldPassPhrase.equals("")) { - oldPassPhrase = ""; - } - - if (newPassPhrase == null || newPassPhrase.equals("")) { - newPassPhrase = ""; - } - - Vector<String> userIds = new Vector<String>(); - Vector<PGPSecretKey> keys = new Vector<PGPSecretKey>(); - - 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(); - 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()); - PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(oldPassPhrase.toCharArray(), - new BouncyCastleProvider()); - - 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 = 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(); - PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(oldPassPhrase.toCharArray(), - new BouncyCastleProvider()); - 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(); - 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 = 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); - Object obj = objectFactory.nextObject(); - - if (obj instanceof PGPKeyRing) { - return (PGPKeyRing) obj; - } - - 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 { - PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey( - new char[] {}, new BouncyCastleProvider()); - 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<Integer> 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(); - } - - public static Date getCreationDate(PGPSecretKey key) { - return key.getPublicKey().getCreationTime(); - } - - @SuppressWarnings("unchecked") - public static PGPPublicKey getMasterKey(PGPPublicKeyRing keyRing) { - if (keyRing == null) { - return null; - } - for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) { - if (key.isMasterKey()) { - return key; - } - } - - return null; - } - - @SuppressWarnings("unchecked") - public static PGPSecretKey getMasterKey(PGPSecretKeyRing keyRing) { - if (keyRing == null) { - return null; - } - for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) { - if (key.isMasterKey()) { - return key; - } - } - - return null; - } - - @SuppressWarnings("unchecked") - public static Vector<PGPPublicKey> getEncryptKeys(PGPPublicKeyRing keyRing) { - Vector<PGPPublicKey> encryptKeys = new Vector<PGPPublicKey>(); - - for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) { - if (isEncryptionKey(key)) { - encryptKeys.add(key); - } - } - - return encryptKeys; - } - - @SuppressWarnings("unchecked") - public static Vector<PGPSecretKey> getSigningKeys(PGPSecretKeyRing keyRing) { - Vector<PGPSecretKey> signingKeys = new Vector<PGPSecretKey>(); - - for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) { - if (isSigningKey(key)) { - signingKeys.add(key); - } - } - - return signingKeys; - } - - public static Vector<PGPPublicKey> getUsableEncryptKeys(PGPPublicKeyRing keyRing) { - Vector<PGPPublicKey> usableKeys = new Vector<PGPPublicKey>(); - Vector<PGPPublicKey> encryptKeys = getEncryptKeys(keyRing); - PGPPublicKey masterKey = null; - for (int i = 0; i < encryptKeys.size(); ++i) { - PGPPublicKey key = encryptKeys.get(i); - if (!isExpired(key)) { - if (key.isMasterKey()) { - masterKey = key; - } else { - usableKeys.add(key); - } - } - } - if (masterKey != null) { - usableKeys.add(masterKey); - } - return usableKeys; - } - - public static boolean isExpired(PGPPublicKey key) { - Date creationDate = getCreationDate(key); - Date expiryDate = getExpiryDate(key); - Date now = new Date(); - if (now.compareTo(creationDate) >= 0 - && (expiryDate == null || now.compareTo(expiryDate) <= 0)) { - return false; - } - return true; - } - - public static boolean isExpired(PGPSecretKey key) { - return isExpired(key.getPublicKey()); - } - - public static Vector<PGPSecretKey> getUsableSigningKeys(PGPSecretKeyRing keyRing) { - Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>(); - Vector<PGPSecretKey> signingKeys = getSigningKeys(keyRing); - PGPSecretKey masterKey = null; - for (int i = 0; i < signingKeys.size(); ++i) { - PGPSecretKey key = signingKeys.get(i); - if (key.isMasterKey()) { - masterKey = key; - } else { - usableKeys.add(key); - } - } - if (masterKey != null) { - usableKeys.add(masterKey); - } - return usableKeys; - } - - public static Date getExpiryDate(PGPPublicKey key) { - Date creationDate = getCreationDate(key); - if (key.getValidDays() == 0) { - // no expiry - return null; - } - Calendar calendar = GregorianCalendar.getInstance(); - calendar.setTime(creationDate); - calendar.add(Calendar.DATE, key.getValidDays()); - Date expiryDate = calendar.getTime(); - - return expiryDate; - } - - public static Date getExpiryDate(PGPSecretKey key) { - return getExpiryDate(key.getPublicKey()); - } - - public static PGPPublicKey getEncryptPublicKey(long masterKeyId) { - PGPPublicKeyRing keyRing = getPublicKeyRing(masterKeyId); - if (keyRing == null) { - return null; - } - Vector<PGPPublicKey> encryptKeys = getUsableEncryptKeys(keyRing); - if (encryptKeys.size() == 0) { - return null; - } - return encryptKeys.get(0); - } - - public static PGPSecretKey getSigningKey(long masterKeyId) { - PGPSecretKeyRing keyRing = getSecretKeyRing(masterKeyId); - if (keyRing == null) { - return null; - } - Vector<PGPSecretKey> signingKeys = getUsableSigningKeys(keyRing); - if (signingKeys.size() == 0) { - return null; - } - return signingKeys.get(0); - } - - @SuppressWarnings("unchecked") - public static String getMainUserId(PGPPublicKey key) { - for (String userId : new IterableIterator<String>(key.getUserIDs())) { - return userId; - } - return null; - } - - @SuppressWarnings("unchecked") - public static String getMainUserId(PGPSecretKey key) { - for (String userId : new IterableIterator<String>(key.getUserIDs())) { - return userId; - } - return null; - } - - public static String getMainUserIdSafe(Context context, PGPPublicKey key) { - String userId = getMainUserId(key); - if (userId == null) { - userId = context.getResources().getString(R.string.unknownUserId); - } - return userId; - } - - public static String getMainUserIdSafe(Context context, PGPSecretKey key) { - String userId = getMainUserId(key); - if (userId == null) { - userId = context.getResources().getString(R.string.unknownUserId); - } - return userId; - } - - @SuppressWarnings("unchecked") - public static boolean isEncryptionKey(PGPPublicKey key) { - if (!key.isEncryptionKey()) { - return false; - } - - if (key.getVersion() <= 3) { - // this must be true now - return key.isEncryptionKey(); - } - - // special cases - if (key.getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT) { - return true; - } - - if (key.getAlgorithm() == PGPPublicKey.RSA_ENCRYPT) { - return true; - } - - for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) { - if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) { - continue; - } - PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); - - if (hashed != null - && (hashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) { - return true; - } - - PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets(); - - if (unhashed != null - && (unhashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) { - return true; - } - } - return false; - } - - public static boolean isEncryptionKey(PGPSecretKey key) { - return isEncryptionKey(key.getPublicKey()); - } - - @SuppressWarnings("unchecked") - public static boolean isSigningKey(PGPPublicKey key) { - if (key.getVersion() <= 3) { - return true; - } - - // special case - if (key.getAlgorithm() == PGPPublicKey.RSA_SIGN) { - return true; - } - - for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) { - if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) { - continue; - } - PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets(); - - if (hashed != null && (hashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) { - return true; - } - - PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets(); - - if (unhashed != null && (unhashed.getKeyFlags() & KeyFlags.SIGN_DATA) != 0) { - return true; - } - } - - return false; - } - - public static boolean isSigningKey(PGPSecretKey key) { - return isSigningKey(key.getPublicKey()); - } - - public static String getAlgorithmInfo(PGPPublicKey key) { - return getAlgorithmInfo(key.getAlgorithm(), key.getBitStrength()); - } - - public static String getAlgorithmInfo(PGPSecretKey key) { - return getAlgorithmInfo(key.getPublicKey()); - } - - public static String getAlgorithmInfo(int algorithm, int keySize) { - String algorithmStr = null; - - switch (algorithm) { - case PGPPublicKey.RSA_ENCRYPT: - case PGPPublicKey.RSA_GENERAL: - case PGPPublicKey.RSA_SIGN: { - algorithmStr = "RSA"; - break; - } - - case PGPPublicKey.DSA: { - algorithmStr = "DSA"; - break; - } - - case PGPPublicKey.ELGAMAL_ENCRYPT: - case PGPPublicKey.ELGAMAL_GENERAL: { - algorithmStr = "ElGamal"; - break; - } - - default: { - algorithmStr = "???"; - break; - } - } - return algorithmStr + ", " + keySize + "bit"; - } - - public static String convertToHex(byte[] fp) { - String fingerPrint = ""; - for (int i = 0; i < fp.length; ++i) { - if (i != 0 && i % 10 == 0) { - fingerPrint += " "; - } else if (i != 0 && i % 2 == 0) { - fingerPrint += " "; - } - String chunk = Integer.toHexString((fp[i] + 256) % 256).toUpperCase(); - while (chunk.length() < 2) { - chunk = "0" + chunk; - } - fingerPrint += chunk; - } - - return fingerPrint; - - } - - public static String getFingerPrint(long keyId) { - PGPPublicKey key = Apg.getPublicKey(keyId); - if (key == null) { - PGPSecretKey secretKey = Apg.getSecretKey(keyId); - if (secretKey == null) { - return ""; - } - key = secretKey.getPublicKey(); - } - - return convertToHex(key.getFingerprint()); - } - - public static String getSmallFingerPrint(long keyId) { - String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(); - while (fingerPrint.length() < 8) { - fingerPrint = "0" + fingerPrint; - } - return fingerPrint; - } - - public static String keyToHex(long keyId) { - return getSmallFingerPrint(keyId >> 32) + getSmallFingerPrint(keyId); - } - - public static long keyFromHex(String data) { - int len = data.length(); - String s2 = data.substring(len - 8); - String s1 = data.substring(0, len - 8); - return (Long.parseLong(s1, 16) << 32) | Long.parseLong(s2, 16); - } - - 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<Integer> getKeyRingIds(int type) { - SQLiteDatabase db = mDatabase.db(); - Vector<Integer> keyIds = new Vector<Integer>(); - 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 { - Security.addProvider(new BouncyCastleProvider()); - - 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 != 0) { - 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); - signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(), - new BouncyCastleProvider()); - 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 - 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 != 0) { - 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 != 0) { - 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 != 0) { - 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 != 0) { - 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 { - Security.addProvider(new BouncyCastleProvider()); - - 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)); - } - signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(), - new BouncyCastleProvider()); - 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 { - Security.addProvider(new BouncyCastleProvider()); - - 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)); - } - signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(), - new BouncyCastleProvider()); - 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, InputData data) throws GeneralException, - NoAsymmetricEncryptionException, IOException { - InputStream in = PGPUtil.getDecoderStream(data.getInputStream()); - 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, InputData data) - throws GeneralException, IOException { - InputStream in = PGPUtil.getDecoderStream(data.getInputStream()); - 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 { - privateKey = secretKey.extractPrivateKey(passPhrase.toCharArray(), - new BouncyCastleProvider()); - } 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(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(EXTRA_SIGNATURE_USER_ID, userId); - break; - } - } - - returnData.putLong(EXTRA_SIGNATURE_KEY_ID, signatureKeyId); - - if (signature != null) { - signature.initVerify(signatureKey, new BouncyCastleProvider()); - } else { - returnData.putBoolean(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(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(EXTRA_SIGNATURE_SUCCESS, true); - } else { - returnData.putBoolean(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(BaseActivity 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(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) { - 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(EXTRA_SIGNATURE_USER_ID, userId); - break; - } - } - - returnData.putLong(EXTRA_SIGNATURE_KEY_ID, signatureKeyId); - - if (signature == null) { - returnData.putBoolean(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(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(mApgPackageName, 0); - if (pi.versionCode % 100 == 99) { - return true; - } else { - return false; - } - } catch (NameNotFoundException e) { - // unpossible! - return false; - } - } - - public static String getVersion(Context context) { - if (VERSION != null) { - return VERSION; - } - try { - PackageInfo pi = context.getPackageManager().getPackageInfo(mApgPackageName, 0); - VERSION = pi.versionName; - return VERSION; - } catch (NameNotFoundException e) { - // unpossible! - 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; - } - - 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(); - } -} |