mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-24 01:32:16 -05:00
Work on new result handling (WIP)
This commit is contained in:
parent
3defd194aa
commit
d686c55a0a
@ -0,0 +1,11 @@
|
|||||||
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
|
public interface PassphraseCacheInterface {
|
||||||
|
public static class NoSecretKeyException extends Exception {
|
||||||
|
public NoSecretKeyException() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCachedPassphrase(long masterKeyId) throws NoSecretKeyException;
|
||||||
|
|
||||||
|
}
|
@ -72,7 +72,7 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class PgpDecryptVerify {
|
public class PgpDecryptVerify {
|
||||||
private ProviderHelper mProviderHelper;
|
private ProviderHelper mProviderHelper;
|
||||||
private PassphraseCache mPassphraseCache;
|
private PassphraseCacheInterface mPassphraseCache;
|
||||||
private InputData mData;
|
private InputData mData;
|
||||||
private OutputStream mOutStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ public class PgpDecryptVerify {
|
|||||||
public static class Builder {
|
public static class Builder {
|
||||||
// mandatory parameter
|
// mandatory parameter
|
||||||
private ProviderHelper mProviderHelper;
|
private ProviderHelper mProviderHelper;
|
||||||
private PassphraseCache mPassphraseCache;
|
private PassphraseCacheInterface mPassphraseCache;
|
||||||
private InputData mData;
|
private InputData mData;
|
||||||
private OutputStream mOutStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
@ -113,12 +113,12 @@ public class PgpDecryptVerify {
|
|||||||
private boolean mDecryptMetadataOnly = false;
|
private boolean mDecryptMetadataOnly = false;
|
||||||
private byte[] mDecryptedSessionKey = null;
|
private byte[] mDecryptedSessionKey = null;
|
||||||
|
|
||||||
public Builder(ProviderHelper providerHelper, PassphraseCache passphraseCache,
|
public Builder(ProviderHelper providerHelper, PassphraseCacheInterface passphraseCache,
|
||||||
InputData data, OutputStream outStream) {
|
InputData data, OutputStream outStream) {
|
||||||
this.mProviderHelper = providerHelper;
|
mProviderHelper = providerHelper;
|
||||||
this.mPassphraseCache = passphraseCache;
|
mPassphraseCache = passphraseCache;
|
||||||
this.mData = data;
|
mData = data;
|
||||||
this.mOutStream = outStream;
|
mOutStream = outStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setProgressable(Progressable progressable) {
|
public Builder setProgressable(Progressable progressable) {
|
||||||
@ -176,16 +176,6 @@ public class PgpDecryptVerify {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface PassphraseCache {
|
|
||||||
public String getCachedPassphrase(long masterKeyId)
|
|
||||||
throws NoSecretKeyException;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class NoSecretKeyException extends Exception {
|
|
||||||
public NoSecretKeyException() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts and/or verifies data based on parameters of class
|
* Decrypts and/or verifies data based on parameters of class
|
||||||
*/
|
*/
|
||||||
@ -322,7 +312,7 @@ public class PgpDecryptVerify {
|
|||||||
// returns "" if key has no passphrase
|
// returns "" if key has no passphrase
|
||||||
mPassphrase = mPassphraseCache.getCachedPassphrase(subKeyId);
|
mPassphrase = mPassphraseCache.getCachedPassphrase(subKeyId);
|
||||||
log.add(LogType.MSG_DC_PASS_CACHED, indent +1);
|
log.add(LogType.MSG_DC_PASS_CACHED, indent +1);
|
||||||
} catch (NoSecretKeyException e) {
|
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
|
||||||
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent +1);
|
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent +1);
|
||||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ import java.util.LinkedList;
|
|||||||
*/
|
*/
|
||||||
public class PgpSignEncrypt {
|
public class PgpSignEncrypt {
|
||||||
private ProviderHelper mProviderHelper;
|
private ProviderHelper mProviderHelper;
|
||||||
|
private PassphraseCacheInterface mPassphraseCache;
|
||||||
private String mVersionHeader;
|
private String mVersionHeader;
|
||||||
private InputData mData;
|
private InputData mData;
|
||||||
private OutputStream mOutStream;
|
private OutputStream mOutStream;
|
||||||
@ -93,6 +94,7 @@ public class PgpSignEncrypt {
|
|||||||
private PgpSignEncrypt(Builder builder) {
|
private PgpSignEncrypt(Builder builder) {
|
||||||
// private Constructor can only be called from Builder
|
// private Constructor can only be called from Builder
|
||||||
this.mProviderHelper = builder.mProviderHelper;
|
this.mProviderHelper = builder.mProviderHelper;
|
||||||
|
this.mPassphraseCache = builder.mPassphraseCache;
|
||||||
this.mVersionHeader = builder.mVersionHeader;
|
this.mVersionHeader = builder.mVersionHeader;
|
||||||
this.mData = builder.mData;
|
this.mData = builder.mData;
|
||||||
this.mOutStream = builder.mOutStream;
|
this.mOutStream = builder.mOutStream;
|
||||||
@ -117,6 +119,7 @@ public class PgpSignEncrypt {
|
|||||||
public static class Builder {
|
public static class Builder {
|
||||||
// mandatory parameter
|
// mandatory parameter
|
||||||
private ProviderHelper mProviderHelper;
|
private ProviderHelper mProviderHelper;
|
||||||
|
private PassphraseCacheInterface mPassphraseCache;
|
||||||
private InputData mData;
|
private InputData mData;
|
||||||
private OutputStream mOutStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
@ -138,8 +141,10 @@ public class PgpSignEncrypt {
|
|||||||
private byte[] mNfcSignedHash = null;
|
private byte[] mNfcSignedHash = null;
|
||||||
private Date mNfcCreationTimestamp = null;
|
private Date mNfcCreationTimestamp = null;
|
||||||
|
|
||||||
public Builder(ProviderHelper providerHelper, InputData data, OutputStream outStream) {
|
public Builder(ProviderHelper providerHelper, PassphraseCacheInterface passphraseCache,
|
||||||
|
InputData data, OutputStream outStream) {
|
||||||
mProviderHelper = providerHelper;
|
mProviderHelper = providerHelper;
|
||||||
|
mPassphraseCache = passphraseCache;
|
||||||
mData = data;
|
mData = data;
|
||||||
mOutStream = outStream;
|
mOutStream = outStream;
|
||||||
}
|
}
|
||||||
@ -290,20 +295,15 @@ public class PgpSignEncrypt {
|
|||||||
|
|
||||||
/* Get keys for signature generation for later usage */
|
/* Get keys for signature generation for later usage */
|
||||||
CanonicalizedSecretKey signingKey = null;
|
CanonicalizedSecretKey signingKey = null;
|
||||||
|
long signKeyId;
|
||||||
if (enableSignature) {
|
if (enableSignature) {
|
||||||
|
|
||||||
// If we weren't handed a passphrase, throw early
|
|
||||||
if (mSignaturePassphrase == null) {
|
|
||||||
log.add(LogType.MSG_SE_ERROR_NO_PASSPHRASE, indent);
|
|
||||||
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// fetch the indicated master key id (the one whose name we sign in)
|
// fetch the indicated master key id (the one whose name we sign in)
|
||||||
CanonicalizedSecretKeyRing signingKeyRing =
|
CanonicalizedSecretKeyRing signingKeyRing =
|
||||||
mProviderHelper.getCanonicalizedSecretKeyRing(mSignatureMasterKeyId);
|
mProviderHelper.getCanonicalizedSecretKeyRing(mSignatureMasterKeyId);
|
||||||
// fetch the specific subkey to sign with, or just use the master key if none specified
|
// fetch the specific subkey to sign with, or just use the master key if none specified
|
||||||
long signKeyId = mSignatureSubKeyId != null ? mSignatureSubKeyId : mSignatureMasterKeyId;
|
signKeyId = mSignatureSubKeyId != null ? mSignatureSubKeyId : mSignatureMasterKeyId;
|
||||||
signingKey = signingKeyRing.getSecretKey(signKeyId);
|
signingKey = signingKeyRing.getSecretKey(signKeyId);
|
||||||
// make sure it's a signing key alright!
|
// make sure it's a signing key alright!
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
@ -317,6 +317,28 @@ public class PgpSignEncrypt {
|
|||||||
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);
|
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if no passphrase was explicitly set try to get it from the cache service
|
||||||
|
if (mSignaturePassphrase == null) {
|
||||||
|
try {
|
||||||
|
// returns "" if key has no passphrase
|
||||||
|
mSignaturePassphrase = mPassphraseCache.getCachedPassphrase(signKeyId);
|
||||||
|
// TODO
|
||||||
|
// log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
|
||||||
|
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
|
||||||
|
// TODO
|
||||||
|
// log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
|
||||||
|
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if passphrase was not cached, return here indicating that a passphrase is missing!
|
||||||
|
if (mSignaturePassphrase == null) {
|
||||||
|
log.add(LogType.MSG_SE_PENDING_PASSPHRASE, indent + 1);
|
||||||
|
SignEncryptResult result = new SignEncryptResult(SignEncryptResult.RESULT_PENDING_PASSPHRASE, log);
|
||||||
|
result.setKeyIdPassphraseNeeded(signKeyId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateProgress(R.string.progress_extracting_signature_key, 0, 100);
|
updateProgress(R.string.progress_extracting_signature_key, 0, 100);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -369,10 +391,10 @@ public class PgpSignEncrypt {
|
|||||||
log.add(LogType.MSG_SE_KEY_OK, indent + 1,
|
log.add(LogType.MSG_SE_KEY_OK, indent + 1,
|
||||||
PgpKeyHelper.convertKeyIdToHex(id));
|
PgpKeyHelper.convertKeyIdToHex(id));
|
||||||
} catch (PgpGeneralException e) {
|
} catch (PgpGeneralException e) {
|
||||||
log.add(LogType.MSG_SE_KEY_WARN, indent +1,
|
log.add(LogType.MSG_SE_KEY_WARN, indent + 1,
|
||||||
PgpKeyHelper.convertKeyIdToHex(id));
|
PgpKeyHelper.convertKeyIdToHex(id));
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
log.add(LogType.MSG_SE_KEY_UNKNOWN, indent +1,
|
log.add(LogType.MSG_SE_KEY_UNKNOWN, indent + 1,
|
||||||
PgpKeyHelper.convertKeyIdToHex(id));
|
PgpKeyHelper.convertKeyIdToHex(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,9 +429,10 @@ public class PgpSignEncrypt {
|
|||||||
/* actual encryption */
|
/* actual encryption */
|
||||||
updateProgress(R.string.progress_encrypting, 8, 100);
|
updateProgress(R.string.progress_encrypting, 8, 100);
|
||||||
log.add(enableSignature
|
log.add(enableSignature
|
||||||
? LogType.MSG_SE_SIGCRYPTING
|
? LogType.MSG_SE_SIGCRYPTING
|
||||||
: LogType.MSG_SE_ENCRYPTING,
|
: LogType.MSG_SE_ENCRYPTING,
|
||||||
indent);
|
indent
|
||||||
|
);
|
||||||
indent += 1;
|
indent += 1;
|
||||||
|
|
||||||
encryptionOut = cPk.open(out, new byte[1 << 16]);
|
encryptionOut = cPk.open(out, new byte[1 << 16]);
|
||||||
|
@ -32,6 +32,7 @@ import org.openintents.openpgp.OpenPgpSignatureResult;
|
|||||||
import org.openintents.openpgp.util.OpenPgpApi;
|
import org.openintents.openpgp.util.OpenPgpApi;
|
||||||
import org.sufficientlysecure.keychain.nfc.NfcActivity;
|
import org.sufficientlysecure.keychain.nfc.NfcActivity;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
|
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||||
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
|
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
|
||||||
@ -259,6 +260,17 @@ public class OpenPgpService extends RemoteService {
|
|||||||
// sign-only
|
// sign-only
|
||||||
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
|
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
|
||||||
new ProviderHelper(getContext()),
|
new ProviderHelper(getContext()),
|
||||||
|
new PassphraseCacheInterface() {
|
||||||
|
@Override
|
||||||
|
public String getCachedPassphrase(long masterKeyId) throws PassphraseCacheInterface.NoSecretKeyException {
|
||||||
|
try {
|
||||||
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
|
OpenPgpService.this, masterKeyId);
|
||||||
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
|
throw new PassphraseCacheInterface.NoSecretKeyException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
inputData, os);
|
inputData, os);
|
||||||
builder.setEnableAsciiArmorOutput(asciiArmor)
|
builder.setEnableAsciiArmorOutput(asciiArmor)
|
||||||
.setVersionHeader(PgpHelper.getVersionForHeader(this))
|
.setVersionHeader(PgpHelper.getVersionForHeader(this))
|
||||||
@ -271,24 +283,27 @@ public class OpenPgpService extends RemoteService {
|
|||||||
builder.setCleartextInput(true);
|
builder.setCleartextInput(true);
|
||||||
|
|
||||||
// execute PGP operation!
|
// execute PGP operation!
|
||||||
SignEncryptResult result = builder.build().execute();
|
SignEncryptResult pgpResult = builder.build().execute();
|
||||||
|
|
||||||
if (result.isPending()) {
|
if (pgpResult.isPending()) {
|
||||||
switch (result.getResult()) {
|
if ((pgpResult.getResult() & SignEncryptResult.RESULT_PENDING_PASSPHRASE) ==
|
||||||
case SignEncryptResult.RESULT_PENDING_NFC:
|
SignEncryptResult.RESULT_PENDING_PASSPHRASE) {
|
||||||
// return PendingIntent to execute NFC activity
|
return getPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded());
|
||||||
// pass through the signature creation timestamp to be used again on second execution
|
} else if ((pgpResult.getResult() & SignEncryptResult.RESULT_PENDING_NFC) ==
|
||||||
// of PgpSignEncrypt when we have the signed hash!
|
SignEncryptResult.RESULT_PENDING_NFC) {
|
||||||
data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, result.getNfcTimestamp().getTime());
|
// return PendingIntent to execute NFC activity
|
||||||
return getNfcSignIntent(data, passphrase, result.getNfcHash(), result.getNfcAlgo());
|
// pass through the signature creation timestamp to be used again on second execution
|
||||||
|
// of PgpSignEncrypt when we have the signed hash!
|
||||||
default:
|
data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, pgpResult.getNfcTimestamp().getTime());
|
||||||
throw new Exception("Encountered unhandled pending state - please file a bug report!");
|
return getNfcSignIntent(data, passphrase, pgpResult.getNfcHash(), pgpResult.getNfcAlgo());
|
||||||
|
} else {
|
||||||
|
throw new PgpGeneralException(
|
||||||
|
"Encountered unhandled type of pending action not supported by API!");
|
||||||
}
|
}
|
||||||
}
|
} else if (pgpResult.success()) {
|
||||||
|
// see end of method
|
||||||
if (!result.success()) {
|
} else {
|
||||||
LogEntryParcel errorMsg = result.getLog().getLast();
|
LogEntryParcel errorMsg = pgpResult.getLog().getLast();
|
||||||
throw new Exception(getString(errorMsg.mType.getMsgId()));
|
throw new Exception(getString(errorMsg.mType.getMsgId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,6 +361,17 @@ public class OpenPgpService extends RemoteService {
|
|||||||
|
|
||||||
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
|
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
|
||||||
new ProviderHelper(getContext()),
|
new ProviderHelper(getContext()),
|
||||||
|
new PassphraseCacheInterface() {
|
||||||
|
@Override
|
||||||
|
public String getCachedPassphrase(long masterKeyId) throws PassphraseCacheInterface.NoSecretKeyException {
|
||||||
|
try {
|
||||||
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
|
OpenPgpService.this, masterKeyId);
|
||||||
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
|
throw new PassphraseCacheInterface.NoSecretKeyException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
inputData, os);
|
inputData, os);
|
||||||
builder.setEnableAsciiArmorOutput(asciiArmor)
|
builder.setEnableAsciiArmorOutput(asciiArmor)
|
||||||
.setVersionHeader(PgpHelper.getVersionForHeader(this))
|
.setVersionHeader(PgpHelper.getVersionForHeader(this))
|
||||||
@ -384,24 +410,27 @@ public class OpenPgpService extends RemoteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// execute PGP operation!
|
// execute PGP operation!
|
||||||
SignEncryptResult result = builder.build().execute();
|
SignEncryptResult pgpResult = builder.build().execute();
|
||||||
|
|
||||||
if (result.isPending()) {
|
if (pgpResult.isPending()) {
|
||||||
switch (result.getResult()) {
|
if ((pgpResult.getResult() & SignEncryptResult.RESULT_PENDING_PASSPHRASE) ==
|
||||||
case SignEncryptResult.RESULT_PENDING_NFC:
|
SignEncryptResult.RESULT_PENDING_PASSPHRASE) {
|
||||||
// return PendingIntent to execute NFC activity
|
return getPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded());
|
||||||
// pass through the signature creation timestamp to be used again on second execution
|
} else if ((pgpResult.getResult() & SignEncryptResult.RESULT_PENDING_NFC) ==
|
||||||
// of PgpSignEncrypt when we have the signed hash!
|
SignEncryptResult.RESULT_PENDING_NFC) {
|
||||||
data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, result.getNfcTimestamp().getTime());
|
// return PendingIntent to execute NFC activity
|
||||||
return getNfcSignIntent(data, passphrase, result.getNfcHash(), result.getNfcAlgo());
|
// pass through the signature creation timestamp to be used again on second execution
|
||||||
|
// of PgpSignEncrypt when we have the signed hash!
|
||||||
default:
|
data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, pgpResult.getNfcTimestamp().getTime());
|
||||||
throw new Exception("Encountered unhandled pending state - please file a bug report!");
|
return getNfcSignIntent(data, passphrase, pgpResult.getNfcHash(), pgpResult.getNfcAlgo());
|
||||||
|
} else {
|
||||||
|
throw new PgpGeneralException(
|
||||||
|
"Encountered unhandled type of pending action not supported by API!");
|
||||||
}
|
}
|
||||||
}
|
} else if (pgpResult.success()) {
|
||||||
|
// see end of method
|
||||||
if (!result.success()) {
|
} else {
|
||||||
LogEntryParcel errorMsg = result.getLog().getLast();
|
LogEntryParcel errorMsg = pgpResult.getLog().getLast();
|
||||||
throw new Exception(getString(errorMsg.mType.getMsgId()));
|
throw new Exception(getString(errorMsg.mType.getMsgId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,14 +474,14 @@ public class OpenPgpService extends RemoteService {
|
|||||||
|
|
||||||
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
||||||
new ProviderHelper(this),
|
new ProviderHelper(this),
|
||||||
new PgpDecryptVerify.PassphraseCache() {
|
new PassphraseCacheInterface() {
|
||||||
@Override
|
@Override
|
||||||
public String getCachedPassphrase(long masterKeyId) throws PgpDecryptVerify.NoSecretKeyException {
|
public String getCachedPassphrase(long masterKeyId) throws PassphraseCacheInterface.NoSecretKeyException {
|
||||||
try {
|
try {
|
||||||
return PassphraseCacheService.getCachedPassphrase(
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
OpenPgpService.this, masterKeyId);
|
OpenPgpService.this, masterKeyId);
|
||||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
throw new PgpDecryptVerify.NoSecretKeyException();
|
throw new PassphraseCacheInterface.NoSecretKeyException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -470,57 +499,64 @@ public class OpenPgpService extends RemoteService {
|
|||||||
.setNfcState(nfcDecryptedSessionKey);
|
.setNfcState(nfcDecryptedSessionKey);
|
||||||
|
|
||||||
// TODO: currently does not support binary signed-only content
|
// TODO: currently does not support binary signed-only content
|
||||||
DecryptVerifyResult decryptVerifyResult = builder.build().execute();
|
DecryptVerifyResult pgpResult = builder.build().execute();
|
||||||
|
|
||||||
if (decryptVerifyResult.isPending()) {
|
if (pgpResult.isPending()) {
|
||||||
switch (decryptVerifyResult.getResult()) {
|
if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==
|
||||||
case DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE:
|
DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) {
|
||||||
return getPassphraseIntent(data, decryptVerifyResult.getKeyIdPassphraseNeeded());
|
return getPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded());
|
||||||
case DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE:
|
} else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==
|
||||||
throw new PgpGeneralException(
|
DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) {
|
||||||
"Decryption of symmetric content not supported by API!");
|
throw new PgpGeneralException(
|
||||||
case DecryptVerifyResult.RESULT_PENDING_NFC:
|
"Decryption of symmetric content not supported by API!");
|
||||||
// TODO get passphrase here? currently not in DecryptVerifyResult
|
} else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==
|
||||||
return getNfcDecryptIntent(
|
DecryptVerifyResult.RESULT_PENDING_NFC) {
|
||||||
data, null, decryptVerifyResult.getNfcEncryptedSessionKey());
|
// TODO get passphrase here? currently not in DecryptVerifyResult
|
||||||
|
return getNfcDecryptIntent(
|
||||||
|
data, null, pgpResult.getNfcEncryptedSessionKey());
|
||||||
|
} else {
|
||||||
|
throw new PgpGeneralException(
|
||||||
|
"Encountered unhandled type of pending action not supported by API!");
|
||||||
}
|
}
|
||||||
throw new PgpGeneralException(
|
} else if (pgpResult.success()) {
|
||||||
"Encountered unhandled type of pending action not supported by API!");
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
|
OpenPgpSignatureResult signatureResult = pgpResult.getSignatureResult();
|
||||||
if (signatureResult != null) {
|
if (signatureResult != null) {
|
||||||
result.putExtra(OpenPgpApi.RESULT_SIGNATURE, signatureResult);
|
result.putExtra(OpenPgpApi.RESULT_SIGNATURE, signatureResult);
|
||||||
|
|
||||||
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 5) {
|
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 5) {
|
||||||
// SIGNATURE_KEY_REVOKED and SIGNATURE_KEY_EXPIRED have been added in version 5
|
// SIGNATURE_KEY_REVOKED and SIGNATURE_KEY_EXPIRED have been added in version 5
|
||||||
if (signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED
|
if (signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED
|
||||||
|| signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED) {
|
|| signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED) {
|
||||||
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
|
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_MISSING) {
|
||||||
|
// If signature is unknown we return an _additional_ PendingIntent
|
||||||
|
// to retrieve the missing key
|
||||||
|
Intent intent = new Intent(getBaseContext(), ImportKeysActivity.class);
|
||||||
|
intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE);
|
||||||
|
intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, signatureResult.getKeyId());
|
||||||
|
intent.putExtra(ImportKeysActivity.EXTRA_PENDING_INTENT_DATA, data);
|
||||||
|
|
||||||
|
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
|
||||||
|
result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_MISSING) {
|
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) >= 4) {
|
||||||
// If signature is unknown we return an _additional_ PendingIntent
|
OpenPgpMetadata metadata = pgpResult.getDecryptMetadata();
|
||||||
// to retrieve the missing key
|
if (metadata != null) {
|
||||||
Intent intent = new Intent(getBaseContext(), ImportKeysActivity.class);
|
result.putExtra(OpenPgpApi.RESULT_METADATA, metadata);
|
||||||
intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE);
|
}
|
||||||
intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, signatureResult.getKeyId());
|
|
||||||
intent.putExtra(ImportKeysActivity.EXTRA_PENDING_INTENT_DATA, data);
|
|
||||||
|
|
||||||
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0,
|
|
||||||
intent,
|
|
||||||
PendingIntent.FLAG_CANCEL_CURRENT);
|
|
||||||
|
|
||||||
result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) >= 4) {
|
|
||||||
OpenPgpMetadata metadata = decryptVerifyResult.getDecryptMetadata();
|
|
||||||
if (metadata != null) {
|
|
||||||
result.putExtra(OpenPgpApi.RESULT_METADATA, metadata);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LogEntryParcel errorMsg = pgpResult.getLog().getLast();
|
||||||
|
throw new Exception(getString(errorMsg.mType.getMsgId()));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
is.close();
|
is.close();
|
||||||
|
@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
|||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
|
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
|
||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
|
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
|
||||||
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
|
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||||
@ -269,6 +270,17 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
/* Operation */
|
/* Operation */
|
||||||
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
|
PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
|
||||||
new ProviderHelper(this),
|
new ProviderHelper(this),
|
||||||
|
new PassphraseCacheInterface() {
|
||||||
|
@Override
|
||||||
|
public String getCachedPassphrase(long masterKeyId) throws PassphraseCacheInterface.NoSecretKeyException {
|
||||||
|
try {
|
||||||
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
|
KeychainIntentService.this, masterKeyId);
|
||||||
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
|
throw new PassphraseCacheInterface.NoSecretKeyException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
inputData, outStream
|
inputData, outStream
|
||||||
);
|
);
|
||||||
builder.setProgressable(this)
|
builder.setProgressable(this)
|
||||||
@ -342,14 +354,14 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
// verification of signatures
|
// verification of signatures
|
||||||
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
||||||
new ProviderHelper(this),
|
new ProviderHelper(this),
|
||||||
new PgpDecryptVerify.PassphraseCache() {
|
new PassphraseCacheInterface() {
|
||||||
@Override
|
@Override
|
||||||
public String getCachedPassphrase(long masterKeyId) {
|
public String getCachedPassphrase(long masterKeyId) throws PassphraseCacheInterface.NoSecretKeyException {
|
||||||
try {
|
try {
|
||||||
return PassphraseCacheService.getCachedPassphrase(
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
KeychainIntentService.this, masterKeyId);
|
KeychainIntentService.this, masterKeyId);
|
||||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
return null;
|
throw new PassphraseCacheInterface.NoSecretKeyException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -390,14 +402,14 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
// verification of signatures
|
// verification of signatures
|
||||||
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
|
||||||
new ProviderHelper(this),
|
new ProviderHelper(this),
|
||||||
new PgpDecryptVerify.PassphraseCache() {
|
new PassphraseCacheInterface() {
|
||||||
@Override
|
@Override
|
||||||
public String getCachedPassphrase(long masterKeyId) throws PgpDecryptVerify.NoSecretKeyException {
|
public String getCachedPassphrase(long masterKeyId) throws PassphraseCacheInterface.NoSecretKeyException {
|
||||||
try {
|
try {
|
||||||
return PassphraseCacheService.getCachedPassphrase(
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
KeychainIntentService.this, masterKeyId);
|
KeychainIntentService.this, masterKeyId);
|
||||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
throw new PgpDecryptVerify.NoSecretKeyException();
|
throw new PassphraseCacheInterface.NoSecretKeyException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -26,12 +26,12 @@ import org.openintents.openpgp.OpenPgpSignatureResult;
|
|||||||
public class DecryptVerifyResult extends OperationResult {
|
public class DecryptVerifyResult extends OperationResult {
|
||||||
|
|
||||||
// the fourth bit indicates a "data pending" result! (it's also a form of non-success)
|
// the fourth bit indicates a "data pending" result! (it's also a form of non-success)
|
||||||
public static final int RESULT_PENDING = RESULT_ERROR +8;
|
public static final int RESULT_PENDING = RESULT_ERROR + 8;
|
||||||
|
|
||||||
// fifth to sixth bit in addition indicate specific type of pending
|
// fifth to sixth bit in addition indicate specific type of pending
|
||||||
public static final int RESULT_PENDING_ASYM_PASSPHRASE = RESULT_PENDING +16;
|
public static final int RESULT_PENDING_ASYM_PASSPHRASE = RESULT_PENDING + 16;
|
||||||
public static final int RESULT_PENDING_SYM_PASSPHRASE = RESULT_PENDING +32;
|
public static final int RESULT_PENDING_SYM_PASSPHRASE = RESULT_PENDING + 32;
|
||||||
public static final int RESULT_PENDING_NFC = RESULT_PENDING +48;
|
public static final int RESULT_PENDING_NFC = RESULT_PENDING + 48;
|
||||||
|
|
||||||
long mKeyIdPassphraseNeeded;
|
long mKeyIdPassphraseNeeded;
|
||||||
byte[] mNfcSessionKey;
|
byte[] mNfcSessionKey;
|
||||||
|
@ -475,7 +475,6 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_SE_ERROR_SIGN_KEY(LogLevel.ERROR, R.string.msg_se_error_sign_key),
|
MSG_SE_ERROR_SIGN_KEY(LogLevel.ERROR, R.string.msg_se_error_sign_key),
|
||||||
MSG_SE_ERROR_KEY_SIGN (LogLevel.ERROR, R.string.msg_se_error_key_sign),
|
MSG_SE_ERROR_KEY_SIGN (LogLevel.ERROR, R.string.msg_se_error_key_sign),
|
||||||
MSG_SE_ERROR_NFC (LogLevel.ERROR, R.string.msg_se_error_nfc),
|
MSG_SE_ERROR_NFC (LogLevel.ERROR, R.string.msg_se_error_nfc),
|
||||||
MSG_SE_ERROR_NO_PASSPHRASE (LogLevel.ERROR, R.string.msg_se_error_no_passphrase),
|
|
||||||
MSG_SE_ERROR_PGP (LogLevel.ERROR, R.string.msg_se_error_pgp),
|
MSG_SE_ERROR_PGP (LogLevel.ERROR, R.string.msg_se_error_pgp),
|
||||||
MSG_SE_ERROR_SIG (LogLevel.ERROR, R.string.msg_se_error_sig),
|
MSG_SE_ERROR_SIG (LogLevel.ERROR, R.string.msg_se_error_sig),
|
||||||
MSG_SE_ERROR_UNLOCK (LogLevel.ERROR, R.string.msg_se_error_unlock),
|
MSG_SE_ERROR_UNLOCK (LogLevel.ERROR, R.string.msg_se_error_unlock),
|
||||||
@ -484,6 +483,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_SE_KEY_WARN (LogLevel.WARN, R.string.msg_se_key_warn),
|
MSG_SE_KEY_WARN (LogLevel.WARN, R.string.msg_se_key_warn),
|
||||||
MSG_SE_OK (LogLevel.OK, R.string.msg_se_ok),
|
MSG_SE_OK (LogLevel.OK, R.string.msg_se_ok),
|
||||||
MSG_SE_PENDING_NFC (LogLevel.INFO, R.string.msg_se_pending_nfc),
|
MSG_SE_PENDING_NFC (LogLevel.INFO, R.string.msg_se_pending_nfc),
|
||||||
|
MSG_SE_PENDING_PASSPHRASE (LogLevel.INFO, R.string.msg_se_pending_passphrase),
|
||||||
MSG_SE (LogLevel.DEBUG, R.string.msg_se),
|
MSG_SE (LogLevel.DEBUG, R.string.msg_se),
|
||||||
MSG_SE_SIGNING (LogLevel.DEBUG, R.string.msg_se_signing),
|
MSG_SE_SIGNING (LogLevel.DEBUG, R.string.msg_se_signing),
|
||||||
MSG_SE_SIGCRYPTING (LogLevel.DEBUG, R.string.msg_se_sigcrypting),
|
MSG_SE_SIGCRYPTING (LogLevel.DEBUG, R.string.msg_se_sigcrypting),
|
||||||
|
@ -24,15 +24,26 @@ import java.util.Date;
|
|||||||
public class SignEncryptResult extends OperationResult {
|
public class SignEncryptResult extends OperationResult {
|
||||||
|
|
||||||
// the fourth bit indicates a "data pending" result! (it's also a form of non-success)
|
// the fourth bit indicates a "data pending" result! (it's also a form of non-success)
|
||||||
public static final int RESULT_PENDING = RESULT_ERROR +8;
|
public static final int RESULT_PENDING = RESULT_ERROR + 8;
|
||||||
|
|
||||||
// fifth to sixth bit in addition indicate specific type of pending
|
// fifth to sixth bit in addition indicate specific type of pending
|
||||||
public static final int RESULT_PENDING_NFC = RESULT_PENDING +16;
|
public static final int RESULT_PENDING_PASSPHRASE = RESULT_PENDING + 16;
|
||||||
|
public static final int RESULT_PENDING_NFC = RESULT_PENDING + 32;
|
||||||
|
|
||||||
|
long mKeyIdPassphraseNeeded;
|
||||||
|
|
||||||
byte[] mNfcHash;
|
byte[] mNfcHash;
|
||||||
int mNfcAlgo;
|
int mNfcAlgo;
|
||||||
Date mNfcTimestamp;
|
Date mNfcTimestamp;
|
||||||
|
|
||||||
|
public long getKeyIdPassphraseNeeded() {
|
||||||
|
return mKeyIdPassphraseNeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyIdPassphraseNeeded(long keyIdPassphraseNeeded) {
|
||||||
|
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
|
||||||
|
}
|
||||||
|
|
||||||
public void setNfcData(byte[] sessionKey, int nfcAlgo, Date nfcTimestamp) {
|
public void setNfcData(byte[] sessionKey, int nfcAlgo, Date nfcTimestamp) {
|
||||||
mNfcHash = sessionKey;
|
mNfcHash = sessionKey;
|
||||||
mNfcAlgo = nfcAlgo;
|
mNfcAlgo = nfcAlgo;
|
||||||
@ -52,7 +63,7 @@ public class SignEncryptResult extends OperationResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPending() {
|
public boolean isPending() {
|
||||||
return (mResult & RESULT_PENDING) != 0;
|
return (mResult & RESULT_PENDING) == RESULT_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignEncryptResult(int result, OperationLog log) {
|
public SignEncryptResult(int result, OperationLog log) {
|
||||||
|
@ -22,7 +22,6 @@ import android.app.ProgressDialog;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
@ -35,15 +34,11 @@ import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
|
|||||||
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
||||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||||
import org.sufficientlysecure.keychain.helper.ShareHelper;
|
import org.sufficientlysecure.keychain.helper.ShareHelper;
|
||||||
|
import org.sufficientlysecure.keychain.nfc.NfcActivity;
|
||||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
|
||||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
|
||||||
import org.sufficientlysecure.keychain.service.results.SignEncryptResult;
|
import org.sufficientlysecure.keychain.service.results.SignEncryptResult;
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
|
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.Notify;
|
import org.sufficientlysecure.keychain.util.Notify;
|
||||||
|
|
||||||
@ -200,22 +195,36 @@ public class EncryptTextActivity extends DrawerActivity implements EncryptActivi
|
|||||||
SignEncryptResult result =
|
SignEncryptResult result =
|
||||||
message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT);
|
message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT);
|
||||||
|
|
||||||
// TODO if (result.isPending())
|
if (result.isPending()) {
|
||||||
|
Log.d(Constants.TAG, "result.getResult() " + result.getResult());
|
||||||
|
if ((result.getResult() & SignEncryptResult.RESULT_PENDING_PASSPHRASE) ==
|
||||||
|
SignEncryptResult.RESULT_PENDING_PASSPHRASE) {
|
||||||
|
Log.d(Constants.TAG, "passp");
|
||||||
|
startPassphraseDialog(result.getKeyIdPassphraseNeeded());
|
||||||
|
} else if ((result.getResult() & SignEncryptResult.RESULT_PENDING_NFC) ==
|
||||||
|
SignEncryptResult.RESULT_PENDING_NFC) {
|
||||||
|
Log.d(Constants.TAG, "nfc");
|
||||||
|
|
||||||
if (!result.success()) {
|
// use after nfc sign
|
||||||
result.createNotify(EncryptTextActivity.this).show();
|
//// data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, result.getNfcTimestamp().getTime());
|
||||||
return;
|
startNfcSign("123456", result.getNfcHash(), result.getNfcAlgo());
|
||||||
}
|
} else {
|
||||||
|
throw new RuntimeException("Unhandled pending result!");
|
||||||
|
}
|
||||||
|
|
||||||
if (mShareAfterEncrypt) {
|
} else if (result.success()) {
|
||||||
// Share encrypted message/file
|
if (mShareAfterEncrypt) {
|
||||||
startActivity(sendWithChooserExcludingEncrypt(message));
|
// Share encrypted message/file
|
||||||
|
startActivity(sendWithChooserExcludingEncrypt(message));
|
||||||
|
} else {
|
||||||
|
// Copy to clipboard
|
||||||
|
copyToClipboard(message);
|
||||||
|
result.createNotify(EncryptTextActivity.this).show();
|
||||||
|
// Notify.showNotify(EncryptTextActivity.this,
|
||||||
|
// R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Copy to clipboard
|
|
||||||
copyToClipboard(message);
|
|
||||||
result.createNotify(EncryptTextActivity.this).show();
|
result.createNotify(EncryptTextActivity.this).show();
|
||||||
// Notify.showNotify(EncryptTextActivity.this,
|
|
||||||
// R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,6 +240,36 @@ public class EncryptTextActivity extends DrawerActivity implements EncryptActivi
|
|||||||
startService(intent);
|
startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startNfcSign(String pin, byte[] hashToSign, int hashAlgo) {
|
||||||
|
Intent data = new Intent();
|
||||||
|
|
||||||
|
// build PendingIntent for Yubikey NFC operations
|
||||||
|
Intent intent = new Intent(this, NfcActivity.class);
|
||||||
|
intent.setAction(NfcActivity.ACTION_SIGN_HASH);
|
||||||
|
// pass params through to activity that it can be returned again later to repeat pgp operation
|
||||||
|
intent.putExtra(NfcActivity.EXTRA_DATA, data);
|
||||||
|
intent.putExtra(NfcActivity.EXTRA_PIN, pin);
|
||||||
|
|
||||||
|
intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign);
|
||||||
|
intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
|
||||||
|
startActivityForResult(intent, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startPassphraseDialog(long subkeyId) {
|
||||||
|
Intent data = new Intent();
|
||||||
|
|
||||||
|
// build PendingIntent for Yubikey NFC operations
|
||||||
|
Intent intent = new Intent(this, PassphraseDialogActivity.class);
|
||||||
|
// pass params through to activity that it can be returned again later to repeat pgp operation
|
||||||
|
intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId);
|
||||||
|
|
||||||
|
// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
|
||||||
|
startActivityForResult(intent, 0);
|
||||||
|
}
|
||||||
|
|
||||||
private Bundle createEncryptBundle() {
|
private Bundle createEncryptBundle() {
|
||||||
// fill values for this action
|
// fill values for this action
|
||||||
Bundle data = new Bundle();
|
Bundle data = new Bundle();
|
||||||
@ -326,35 +365,35 @@ public class EncryptTextActivity extends DrawerActivity implements EncryptActivi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
// TODO This should really not be decided here. We do need the info for the passphrase
|
// // TODO This should really not be decided here. We do need the info for the passphrase
|
||||||
// TODO dialog fragment though, so that's just the way it is for now.
|
// // TODO dialog fragment though, so that's just the way it is for now.
|
||||||
if (mSigningKeyId != 0) {
|
// if (mSigningKeyId != 0) {
|
||||||
CachedPublicKeyRing signingRing =
|
// CachedPublicKeyRing signingRing =
|
||||||
new ProviderHelper(this).getCachedPublicKeyRing(mSigningKeyId);
|
// new ProviderHelper(this).getCachedPublicKeyRing(mSigningKeyId);
|
||||||
long sigSubKeyId = signingRing.getSignId();
|
// long sigSubKeyId = signingRing.getSignId();
|
||||||
// Make sure the passphrase is cached, then start over.
|
// // Make sure the passphrase is cached, then start over.
|
||||||
if (PassphraseCacheService.getCachedPassphrase(this, sigSubKeyId) == null) {
|
// if (PassphraseCacheService.getCachedPassphrase(this, sigSubKeyId) == null) {
|
||||||
PassphraseDialogFragment.show(this, sigSubKeyId,
|
// PassphraseDialogFragment.show(this, sigSubKeyId,
|
||||||
new Handler() {
|
// new Handler() {
|
||||||
@Override
|
// @Override
|
||||||
public void handleMessage(Message message) {
|
// public void handleMessage(Message message) {
|
||||||
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
|
// if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
|
||||||
// restart
|
// // restart
|
||||||
startEncrypt();
|
// startEncrypt();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
|
//
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} catch (PgpGeneralException e) {
|
// } catch (PgpGeneralException e) {
|
||||||
Log.e(Constants.TAG, "Key not found!", e);
|
// Log.e(Constants.TAG, "Key not found!", e);
|
||||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
// } catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
Log.e(Constants.TAG, "Key not found!", e);
|
// Log.e(Constants.TAG, "Key not found!", e);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -32,13 +32,12 @@ import org.sufficientlysecure.keychain.R;
|
|||||||
public class EncryptTextFragment extends Fragment {
|
public class EncryptTextFragment extends Fragment {
|
||||||
public static final String ARG_TEXT = "text";
|
public static final String ARG_TEXT = "text";
|
||||||
|
|
||||||
private TextView mMessage = null;
|
private TextView mText;
|
||||||
private View mEncryptShare;
|
private View mEncryptShare;
|
||||||
private View mEncryptClipboard;
|
private View mEncryptClipboard;
|
||||||
|
|
||||||
private EncryptActivityInterface mEncryptInterface;
|
private EncryptActivityInterface mEncryptInterface;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Activity activity) {
|
public void onAttach(Activity activity) {
|
||||||
super.onAttach(activity);
|
super.onAttach(activity);
|
||||||
@ -56,8 +55,8 @@ public class EncryptTextFragment extends Fragment {
|
|||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.encrypt_text_fragment, container, false);
|
View view = inflater.inflate(R.layout.encrypt_text_fragment, container, false);
|
||||||
|
|
||||||
mMessage = (TextView) view.findViewById(R.id.message);
|
mText = (TextView) view.findViewById(R.id.encrypt_text_text);
|
||||||
mMessage.addTextChangedListener(new TextWatcher() {
|
mText.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
|
||||||
@ -98,7 +97,7 @@ public class EncryptTextFragment extends Fragment {
|
|||||||
|
|
||||||
String text = mEncryptInterface.getMessage();
|
String text = mEncryptInterface.getMessage();
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
mMessage.setText(text);
|
mText.setText(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ import org.sufficientlysecure.keychain.util.Log;
|
|||||||
public class PassphraseDialogActivity extends FragmentActivity {
|
public class PassphraseDialogActivity extends FragmentActivity {
|
||||||
public static final String MESSAGE_DATA_PASSPHRASE = "passphrase";
|
public static final String MESSAGE_DATA_PASSPHRASE = "passphrase";
|
||||||
|
|
||||||
public static final String EXTRA_SECRET_KEY_ID = "secret_key_id";
|
public static final String EXTRA_SUBKEY_ID = "secret_key_id";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -76,7 +76,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
|||||||
|
|
||||||
// this activity itself has no content view (see manifest)
|
// this activity itself has no content view (see manifest)
|
||||||
|
|
||||||
long keyId = getIntent().getLongExtra(EXTRA_SECRET_KEY_ID, 0);
|
long keyId = getIntent().getLongExtra(EXTRA_SUBKEY_ID, 0);
|
||||||
|
|
||||||
show(this, keyId);
|
show(this, keyId);
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
|||||||
// do NOT check if the key even needs a passphrase. that's not our job here.
|
// do NOT check if the key even needs a passphrase. that's not our job here.
|
||||||
PassphraseDialogFragment frag = new PassphraseDialogFragment();
|
PassphraseDialogFragment frag = new PassphraseDialogFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putLong(EXTRA_SECRET_KEY_ID, keyId);
|
args.putLong(EXTRA_SUBKEY_ID, keyId);
|
||||||
|
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
|||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
mSubKeyId = getArguments().getLong(EXTRA_SECRET_KEY_ID);
|
mSubKeyId = getArguments().getLong(EXTRA_SUBKEY_ID);
|
||||||
|
|
||||||
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
|
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
|
||||||
|
|
||||||
|
@ -2,12 +2,14 @@ package org.sufficientlysecure.keychain.ui.dialog;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
/** This class extends AlertDiaog.Builder, styling the header using emphasis color.
|
/**
|
||||||
|
* This class extends AlertDiaog.Builder, styling the header using emphasis color.
|
||||||
* Note that this class is a huge hack, because dialog boxes aren't easily stylable.
|
* Note that this class is a huge hack, because dialog boxes aren't easily stylable.
|
||||||
* Also, the dialog NEEDS to be called with show() directly, not create(), otherwise
|
* Also, the dialog NEEDS to be called with show() directly, not create(), otherwise
|
||||||
* the order of internal operations will lead to a crash!
|
* the order of internal operations will lead to a crash!
|
||||||
@ -15,7 +17,9 @@ import org.sufficientlysecure.keychain.R;
|
|||||||
public class CustomAlertDialogBuilder extends AlertDialog.Builder {
|
public class CustomAlertDialogBuilder extends AlertDialog.Builder {
|
||||||
|
|
||||||
public CustomAlertDialogBuilder(Activity activity) {
|
public CustomAlertDialogBuilder(Activity activity) {
|
||||||
super(activity);
|
// if the progress dialog is displayed from the application class, design is missing
|
||||||
|
// hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay
|
||||||
|
super(new ContextThemeWrapper(activity, R.style.Theme_AppCompat_Light));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/message"
|
android:id="@+id/encrypt_text_text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dip"
|
android:layout_height="0dip"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
|
@ -823,6 +823,7 @@
|
|||||||
<string name="msg_se_key_warn">"Bad key for encryption: %s"</string>
|
<string name="msg_se_key_warn">"Bad key for encryption: %s"</string>
|
||||||
<string name="msg_se_ok">"Sign/Encrypt operation successful!"</string>
|
<string name="msg_se_ok">"Sign/Encrypt operation successful!"</string>
|
||||||
<string name="msg_se_pending_nfc">"NFC token required, requesting user input…"</string>
|
<string name="msg_se_pending_nfc">"NFC token required, requesting user input…"</string>
|
||||||
|
<string name="msg_se_pending_passphrase">"Passphrase required, requesting user input…"</string>
|
||||||
<string name="msg_se_signing">"Signing data (without encryption)"</string>
|
<string name="msg_se_signing">"Signing data (without encryption)"</string>
|
||||||
<string name="msg_se_sigcrypting">"Encrypting data with signature"</string>
|
<string name="msg_se_sigcrypting">"Encrypting data with signature"</string>
|
||||||
<string name="msg_se">"Starting sign and/or encrypt operation"</string>
|
<string name="msg_se">"Starting sign and/or encrypt operation"</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user