Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Haydar #96

Open
wants to merge 8 commits into
base: apgpro
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import android.app.Application;
import android.os.Environment;

import com.fsck.k9.K9;

import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.thialfihar.android.apg.util.Log;
import org.thialfihar.android.apg.util.PRNGFixes;
Expand All @@ -28,7 +30,7 @@
import java.security.Provider;
import java.security.Security;

public class ApgApplication extends Application {
public class ApgApplication extends K9 {

/**
* Called when the application is starting, before any activity, service, or receiver objects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@

import org.spongycastle.jce.provider.BouncyCastleProvider;

import org.thialfihar.android.apg.service.remote.RegisteredAppsListActivity;
import org.thialfihar.android.apg.ui.DecryptActivity;
import org.thialfihar.android.apg.ui.EncryptActivity;
import org.thialfihar.android.apg.ui.ImportKeysActivity;
import org.thialfihar.android.apg.ui.KeyListActivity;

public final class Constants {

public static final boolean DEBUG = BuildConfig.DEBUG;
Expand Down Expand Up @@ -67,14 +61,4 @@ public static final class Pref {
public static final class Defaults {
public static final String KEY_SERVERS = "pool.sks-keyservers.net, subkeys.pgp.net, pgp.mit.edu";
}

public static final class DrawerItems {
public static final Class KEY_LIST = KeyListActivity.class;
public static final Class ENCRYPT = EncryptActivity.class;
public static final Class DECRYPT = DecryptActivity.class;
public static final Class IMPORT_KEYS = ImportKeysActivity.class;
public static final Class REGISTERED_APPS_LIST = RegisteredAppsListActivity.class;
public static final Class[] ARRAY = new Class[] {KEY_LIST, ENCRYPT, DECRYPT,
IMPORT_KEYS, REGISTERED_APPS_LIST};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ public static final class mode {
public static final class key {
public static final int none = 0;
public static final int symmetric = -1;
public static final int not_required = -2;
}

public static final class content {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,20 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;

import org.spongycastle.bcpg.ArmoredInputStream;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedDataList;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPUtil;

import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.pgp.PgpDecryptVerify;
import org.thialfihar.android.apg.pgp.exception.NoAsymmetricEncryptionException;
import org.thialfihar.android.apg.pgp.exception.PgpGeneralException;
import org.thialfihar.android.apg.provider.ProviderHelper;
Expand Down Expand Up @@ -77,8 +81,16 @@ public static String getFullVersion(Context context) {
}

public static long getDecryptionKeyId(Context context, InputStream inputStream)
throws PgpGeneralException, NoAsymmetricEncryptionException, IOException {
throws PgpGeneralException, IOException {
InputStream in = PGPUtil.getDecoderStream(inputStream);
if (in instanceof ArmoredInputStream) {
ArmoredInputStream aIn = (ArmoredInputStream) in;
// it is ascii armored
if (aIn.isClearText()) {
return Id.key.not_required;
}
}

PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
Expand Down Expand Up @@ -112,7 +124,10 @@ public static long getDecryptionKeyId(Context context, InputStream inputStream)
}

if (!gotAsymmetricEncryption) {
throw new NoAsymmetricEncryptionException();
inputStream.reset();
if (PgpDecryptVerify.hasSymmetricEncryption(context, inputStream)) {
return Id.key.symmetric;
}
}

if (secretKey == null) {
Expand Down Expand Up @@ -216,4 +231,13 @@ public static void deleteFileSecurely(Context context, Progressable progress, Fi
raf.close();
file.delete();
}

public static String getHashAlgorithmMicAlgName(int hashAlgorithm) {
switch (hashAlgorithm) {
case HashAlgorithmTags.MD5: return "pgp-md5";
case HashAlgorithmTags.SHA1: return "pgp-sha1";
case HashAlgorithmTags.RIPEMD160: return "pgp-ripemd160";
default: return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import android.os.Messenger;
import android.os.RemoteException;

import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPPublicKeyRing;
Expand Down Expand Up @@ -123,6 +124,7 @@ public class ApgIntentService extends IntentService implements Progressable, Key
public static final String ENCRYPT_INPUT_FILE = "input_file";
public static final String ENCRYPT_OUTPUT_FILE = "output_file";
public static final String ENCRYPT_PROVIDER_URI = "provider_uri";
public static final String ENCRYPT_FOR_PGP_MIME = "for_pgp_mime";

// decrypt/verify
public static final String DECRYPT_RETURN_BYTES = "return_binary";
Expand Down Expand Up @@ -183,6 +185,7 @@ public class ApgIntentService extends IntentService implements Progressable, Key
public static final String RESULT_ENCRYPTED_STRING = "encrypted_message";
public static final String RESULT_ENCRYPTED_BYTES = "encrypted_data";
public static final String RESULT_URI = "result_uri";
public static final String RESULT_MICALG = "result_micalg";

// decrypt/verify
public static final String RESULT_DECRYPTED_STRING = "decrypted_message";
Expand Down Expand Up @@ -259,6 +262,7 @@ protected void onHandleIntent(Intent intent) {
int compressionId = data.getInt(ENCRYPT_COMPRESSION_ID);
boolean generateSignature = data.getBoolean(ENCRYPT_GENERATE_SIGNATURE);
boolean signOnly = data.getBoolean(ENCRYPT_SIGN_ONLY);
boolean forPgpMime = data.getBoolean(ENCRYPT_FOR_PGP_MIME);

InputStream inStream = null;
long inLength = -1;
Expand Down Expand Up @@ -325,18 +329,30 @@ protected void onHandleIntent(Intent intent) {

}

Bundle resultData = new Bundle();

/* Operation */
PgpSignEncrypt.Builder builder =
new PgpSignEncrypt.Builder(this, inputData, outStream, new ProviderHelper(this));
builder.setProgressable(this);

int hashAlgorithm = Preferences.getPreferences(this).getDefaultHashAlgorithm();
if (forPgpMime) {
String micalg = PgpHelper.getHashAlgorithmMicAlgName(hashAlgorithm);
if (micalg == null) {
// use SHA-1 if the default algorithm isn't acceptable for PGP/MIME
hashAlgorithm = HashAlgorithmTags.SHA1;
micalg = PgpHelper.getHashAlgorithmMicAlgName(hashAlgorithm);
}
resultData.putString(RESULT_MICALG, micalg);
}

if (generateSignature) {
Log.d(Constants.TAG, "generating signature...");
builder.setEnableAsciiArmorOutput(useAsciiArmor)
.setSignatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
.setSignatureKeyId(secretKeyId)
.setSignatureHashAlgorithm(
Preferences.getPreferences(this).getDefaultHashAlgorithm())
.setSignatureHashAlgorithm(hashAlgorithm)
.setSignaturePassphrase(
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));

Expand All @@ -346,8 +362,7 @@ protected void onHandleIntent(Intent intent) {
builder.setEnableAsciiArmorOutput(useAsciiArmor)
.setSignatureForceV3(Preferences.getPreferences(this).getForceV3Signatures())
.setSignatureKeyId(secretKeyId)
.setSignatureHashAlgorithm(
Preferences.getPreferences(this).getDefaultHashAlgorithm())
.setSignatureHashAlgorithm(hashAlgorithm)
.setSignaturePassphrase(
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));

Expand All @@ -362,8 +377,7 @@ protected void onHandleIntent(Intent intent) {
.setEncryptionKeyIds(encryptionKeyIds)
.setEncryptionPassphrase(encryptionPassphrase)
.setSignatureKeyId(secretKeyId)
.setSignatureHashAlgorithm(
Preferences.getPreferences(this).getDefaultHashAlgorithm())
.setSignatureHashAlgorithm(hashAlgorithm)
.setSignaturePassphrase(
PassphraseCacheService.getCachedPassphrase(this, secretKeyId));

Expand All @@ -374,8 +388,6 @@ protected void onHandleIntent(Intent intent) {

/* Output */

Bundle resultData = new Bundle();

switch (target) {
case TARGET_BYTES:
if (useAsciiArmor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ private String getCachedPassphraseImpl(long keyId) {
* @return true if it has a passphrase
*/
public static boolean hasPassphrase(Context context, long secretKeyId) {
if (secretKeyId == Id.key.symmetric) {
return true;
}
// check if the key has no passphrase
try {
PGPSecretKeyRing secRing = ProviderHelper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.support.v7.app.ActionBarActivity;
import android.view.View;

Expand All @@ -31,7 +30,6 @@
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.helper.ActionBarHelper;
import org.thialfihar.android.apg.pgp.exception.PgpGeneralException;
import org.thialfihar.android.apg.provider.ProviderHelper;
import org.thialfihar.android.apg.ui.SelectPublicKeyFragment;
import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
Expand Down Expand Up @@ -129,9 +127,21 @@ public void onClick(View v) {
mSettingsFragment.setAppSettings(settings);
} else if (ACTION_CACHE_PASSPHRASE.equals(action)) {
long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID);
Intent resultData = extras.getParcelable(EXTRA_DATA);
final Intent resultData = extras.getParcelable(EXTRA_DATA);

PassphraseDialogFragment.show(this, secretKeyId, new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
// return given params again, for calling the service method again
RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
} else {
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
}

showPassphraseDialog(resultData, secretKeyId);
RemoteServiceActivity.this.finish();
}
});
} else if (ACTION_SELECT_PUB_KEYS.equals(action)) {
long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
ArrayList<String> missingUserIds = intent
Expand Down Expand Up @@ -239,41 +249,4 @@ public void onClick(View v) {
finish();
}
}

/**
* Shows passphrase dialog to cache a new passphrase the user enters for using it later for
* encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks
* for a symmetric passphrase
*/
private void showPassphraseDialog(final Intent data, long secretKeyId) {
// Message is received after passphrase is cached
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
// return given params again, for calling the service method again
RemoteServiceActivity.this.setResult(RESULT_OK, data);
} else {
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
}

RemoteServiceActivity.this.finish();
}
};

// Create a new Messenger for the communication back
Messenger messenger = new Messenger(returnHandler);

try {
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this,
messenger, secretKeyId);

passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
} catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No passphrase for this secret key, do pgp operation directly!");
// return given params again, for calling the service method again
setResult(RESULT_OK, data);
finish();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.helper.Preferences;
import org.thialfihar.android.apg.pgp.PgpKeyHelper;
import org.thialfihar.android.apg.pgp.exception.PgpGeneralException;
import org.thialfihar.android.apg.provider.KeychainContract;
import org.thialfihar.android.apg.provider.ProviderHelper;
import org.thialfihar.android.apg.service.ApgIntentService;
Expand Down Expand Up @@ -240,32 +239,6 @@ public void onLoaderReset(Loader<Cursor> loader) {
}
}

private void showPassphraseDialog(final long secretKeyId) {
// Message is received after passphrase is cached
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
startSigning();
}
}
};

// Create a new Messenger for the communication back
Messenger messenger = new Messenger(returnHandler);

try {
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(this,
messenger, secretKeyId);

passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
} catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No passphrase for this secret key!");
// send message to handler to start certification directly
returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
}
}

/**
* handles the UI bits of the signing process on the UI thread
*/
Expand Down Expand Up @@ -293,7 +266,14 @@ private void initiateSigning() {
*/
String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId);
if (passphrase == null) {
showPassphraseDialog(mMasterKeyId);
PassphraseDialogFragment.show(this, mMasterKeyId, new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
startSigning();
}
}
});
// bail out; need to wait until the user has entered the passphrase before trying again
return;
} else {
Expand Down
Loading