mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-23 17:22:16 -05:00
Fix decryption of messages/files encrypted for multiple public keys
This commit is contained in:
parent
a1efb24228
commit
d81de8509b
@ -200,7 +200,7 @@ public class PgpDecryptVerify {
|
|||||||
*/
|
*/
|
||||||
private PgpDecryptVerifyResult decryptVerify(InputStream in)
|
private PgpDecryptVerifyResult decryptVerify(InputStream in)
|
||||||
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
||||||
PgpDecryptVerifyResult returnData = new PgpDecryptVerifyResult();
|
PgpDecryptVerifyResult result = new PgpDecryptVerifyResult();
|
||||||
|
|
||||||
PGPObjectFactory pgpF = new PGPObjectFactory(in);
|
PGPObjectFactory pgpF = new PGPObjectFactory(in);
|
||||||
PGPEncryptedDataList enc;
|
PGPEncryptedDataList enc;
|
||||||
@ -228,6 +228,7 @@ public class PgpDecryptVerify {
|
|||||||
PGPPBEEncryptedData encryptedDataSymmetric = null;
|
PGPPBEEncryptedData encryptedDataSymmetric = null;
|
||||||
PGPSecretKey secretKey = null;
|
PGPSecretKey secretKey = null;
|
||||||
Iterator<?> it = enc.getEncryptedDataObjects();
|
Iterator<?> it = enc.getEncryptedDataObjects();
|
||||||
|
boolean asymmetricPacketFound = false;
|
||||||
boolean symmetricPacketFound = false;
|
boolean symmetricPacketFound = false;
|
||||||
// find secret key
|
// find secret key
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
@ -245,18 +246,22 @@ public class PgpDecryptVerify {
|
|||||||
);
|
);
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
Log.e(Constants.TAG, "key not found!", e);
|
Log.e(Constants.TAG, "key not found!", e);
|
||||||
|
// continue with the next packet in the while loop
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
// get actual keyring object based on master key id
|
// get actual keyring object based on master key id
|
||||||
PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRing(mContext, masterKeyId);
|
PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRing(mContext, masterKeyId);
|
||||||
|
|
||||||
if (secretKeyRing == null) {
|
if (secretKeyRing == null) {
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_no_secret_key_found));
|
// continue with the next packet in the while loop
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
secretKey = secretKeyRing.getSecretKey(encData.getKeyID());
|
secretKey = secretKeyRing.getSecretKey(encData.getKeyID());
|
||||||
if (secretKey == null) {
|
if (secretKey == null) {
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_no_secret_key_found));
|
// continue with the next packet in the while loop
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
// secret key exists in database
|
|
||||||
|
/* secret key exists in database! */
|
||||||
|
|
||||||
// allow only a specific key for decryption?
|
// allow only a specific key for decryption?
|
||||||
if (mAllowedKeyIds != null) {
|
if (mAllowedKeyIds != null) {
|
||||||
@ -265,11 +270,15 @@ public class PgpDecryptVerify {
|
|||||||
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
|
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
|
||||||
|
|
||||||
if (!mAllowedKeyIds.contains(masterKeyId)) {
|
if (!mAllowedKeyIds.contains(masterKeyId)) {
|
||||||
throw new PgpGeneralException(
|
// this key is in our db, but NOT allowed!
|
||||||
mContext.getString(R.string.error_no_secret_key_found));
|
// continue with the next packet in the while loop
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* secret key exists in database and is allowed! */
|
||||||
|
asymmetricPacketFound = true;
|
||||||
|
|
||||||
encryptedDataAsymmetric = encData;
|
encryptedDataAsymmetric = encData;
|
||||||
|
|
||||||
// if no passphrase was explicitly set try to get it from the cache service
|
// if no passphrase was explicitly set try to get it from the cache service
|
||||||
@ -281,16 +290,20 @@ public class PgpDecryptVerify {
|
|||||||
// if passphrase was not cached, return here
|
// if passphrase was not cached, return here
|
||||||
// indicating that a passphrase is missing!
|
// indicating that a passphrase is missing!
|
||||||
if (mPassphrase == null) {
|
if (mPassphrase == null) {
|
||||||
returnData.setKeyIdPassphraseNeeded(masterKeyId);
|
result.setKeyIdPassphraseNeeded(masterKeyId);
|
||||||
returnData.setStatus(PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED);
|
result.setStatus(PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED);
|
||||||
return returnData;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// break out of while, only get first object here
|
// break out of while, only decrypt the first packet where we have a key
|
||||||
// TODO???: There could be more pgp objects, which are not decrypted!
|
// TODO???: There could be more pgp objects, which are not decrypted!
|
||||||
break;
|
break;
|
||||||
} else if (mAllowSymmetricDecryption && obj instanceof PGPPBEEncryptedData) {
|
} else if (mAllowSymmetricDecryption && obj instanceof PGPPBEEncryptedData) {
|
||||||
|
/*
|
||||||
|
* When mAllowSymmetricDecryption == true and we find a data packet here,
|
||||||
|
* we do not search for other available asymmetric packets!
|
||||||
|
*/
|
||||||
symmetricPacketFound = true;
|
symmetricPacketFound = true;
|
||||||
|
|
||||||
encryptedDataSymmetric = (PGPPBEEncryptedData) obj;
|
encryptedDataSymmetric = (PGPPBEEncryptedData) obj;
|
||||||
@ -298,11 +311,11 @@ public class PgpDecryptVerify {
|
|||||||
// if no passphrase is given, return here
|
// if no passphrase is given, return here
|
||||||
// indicating that a passphrase is missing!
|
// indicating that a passphrase is missing!
|
||||||
if (mPassphrase == null) {
|
if (mPassphrase == null) {
|
||||||
returnData.setStatus(PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED);
|
result.setStatus(PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED);
|
||||||
return returnData;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// break out of while, only get first object here
|
// break out of while, only decrypt the first packet
|
||||||
// TODO???: There could be more pgp objects, which are not decrypted!
|
// TODO???: There could be more pgp objects, which are not decrypted!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -321,11 +334,7 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
encryptedData = encryptedDataSymmetric;
|
encryptedData = encryptedDataSymmetric;
|
||||||
currentProgress += 5;
|
currentProgress += 5;
|
||||||
} else {
|
} else if (asymmetricPacketFound) {
|
||||||
if (secretKey == null) {
|
|
||||||
throw new PgpGeneralException(mContext.getString(R.string.error_no_secret_key_found));
|
|
||||||
}
|
|
||||||
|
|
||||||
currentProgress += 5;
|
currentProgress += 5;
|
||||||
updateProgress(R.string.progress_extracting_key, currentProgress, 100);
|
updateProgress(R.string.progress_extracting_key, currentProgress, 100);
|
||||||
PGPPrivateKey privateKey;
|
PGPPrivateKey privateKey;
|
||||||
@ -351,6 +360,9 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
encryptedData = encryptedDataAsymmetric;
|
encryptedData = encryptedDataAsymmetric;
|
||||||
currentProgress += 5;
|
currentProgress += 5;
|
||||||
|
} else {
|
||||||
|
// no packet has been found where we have the corresponding secret key in our db
|
||||||
|
throw new PgpGeneralException(mContext.getString(R.string.error_no_secret_key_found));
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
|
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
|
||||||
@ -379,7 +391,7 @@ public class PgpDecryptVerify {
|
|||||||
for (int i = 0; i < sigList.size(); ++i) {
|
for (int i = 0; i < sigList.size(); ++i) {
|
||||||
signature = sigList.get(i);
|
signature = sigList.get(i);
|
||||||
signatureKey = ProviderHelper
|
signatureKey = ProviderHelper
|
||||||
.getPGPPublicKeyRing(mContext, signature.getKeyID()).getPublicKey();
|
.getPGPPublicKeyRingWithKeyId(mContext, signature.getKeyID()).getPublicKey();
|
||||||
if (signatureKeyId == 0) {
|
if (signatureKeyId == 0) {
|
||||||
signatureKeyId = signature.getKeyID();
|
signatureKeyId = signature.getKeyID();
|
||||||
}
|
}
|
||||||
@ -408,6 +420,7 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
signature.init(contentVerifierBuilderProvider, signatureKey);
|
signature.init(contentVerifierBuilderProvider, signatureKey);
|
||||||
} else {
|
} else {
|
||||||
|
Log.d(Constants.TAG, "SIGNATURE_UNKNOWN_PUB_KEY");
|
||||||
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY);
|
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,6 +459,7 @@ public class PgpDecryptVerify {
|
|||||||
try {
|
try {
|
||||||
signature.update(buffer, 0, n);
|
signature.update(buffer, 0, n);
|
||||||
} catch (SignatureException e) {
|
} catch (SignatureException e) {
|
||||||
|
Log.d(Constants.TAG, "SIGNATURE_ERROR");
|
||||||
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
|
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
|
||||||
signature = null;
|
signature = null;
|
||||||
}
|
}
|
||||||
@ -479,7 +493,12 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
// TODO: implement CERTIFIED!
|
// TODO: implement CERTIFIED!
|
||||||
if (validKeyBinding & validSignature) {
|
if (validKeyBinding & validSignature) {
|
||||||
|
Log.d(Constants.TAG, "SIGNATURE_SUCCESS_UNCERTIFIED");
|
||||||
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED);
|
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED);
|
||||||
|
} else {
|
||||||
|
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
|
||||||
|
Log.e(Constants.TAG, "Error!\nvalidKeyBinding: " + validKeyBinding
|
||||||
|
+ "\nvalidSignature: " + validSignature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -503,8 +522,8 @@ public class PgpDecryptVerify {
|
|||||||
|
|
||||||
updateProgress(R.string.progress_done, 100, 100);
|
updateProgress(R.string.progress_done, 100, 100);
|
||||||
|
|
||||||
returnData.setSignatureResult(signatureResult);
|
result.setSignatureResult(signatureResult);
|
||||||
return returnData;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -522,7 +541,7 @@ public class PgpDecryptVerify {
|
|||||||
*/
|
*/
|
||||||
private PgpDecryptVerifyResult verifyCleartextSignature(ArmoredInputStream aIn)
|
private PgpDecryptVerifyResult verifyCleartextSignature(ArmoredInputStream aIn)
|
||||||
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
throws IOException, PgpGeneralException, PGPException, SignatureException {
|
||||||
PgpDecryptVerifyResult returnData = new PgpDecryptVerifyResult();
|
PgpDecryptVerifyResult result = new PgpDecryptVerifyResult();
|
||||||
OpenPgpSignatureResult signatureResult = new OpenPgpSignatureResult();
|
OpenPgpSignatureResult signatureResult = new OpenPgpSignatureResult();
|
||||||
// cleartext signatures are never encrypted ;)
|
// cleartext signatures are never encrypted ;)
|
||||||
signatureResult.setSignatureOnly(true);
|
signatureResult.setSignatureOnly(true);
|
||||||
@ -569,10 +588,10 @@ public class PgpDecryptVerify {
|
|||||||
// find data about this subkey
|
// find data about this subkey
|
||||||
HashMap<String, Object> data = ProviderHelper.getGenericData(mContext,
|
HashMap<String, Object> data = ProviderHelper.getGenericData(mContext,
|
||||||
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(signature.getKeyID())),
|
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(signature.getKeyID())),
|
||||||
new String[] { KeyRings.MASTER_KEY_ID, KeyRings.USER_ID },
|
new String[]{KeyRings.MASTER_KEY_ID, KeyRings.USER_ID},
|
||||||
new int[] { ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_STRING });
|
new int[]{ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_STRING});
|
||||||
// any luck? otherwise, try next.
|
// any luck? otherwise, try next.
|
||||||
if(data.get(KeyRings.MASTER_KEY_ID) == null) {
|
if (data.get(KeyRings.MASTER_KEY_ID) == null) {
|
||||||
signature = null;
|
signature = null;
|
||||||
// do NOT reset signatureKeyId, that one is shown when no known one is found!
|
// do NOT reset signatureKeyId, that one is shown when no known one is found!
|
||||||
continue;
|
continue;
|
||||||
@ -588,11 +607,12 @@ public class PgpDecryptVerify {
|
|||||||
signatureResult.setKeyId(signatureKeyId);
|
signatureResult.setKeyId(signatureKeyId);
|
||||||
|
|
||||||
if (signature == null) {
|
if (signature == null) {
|
||||||
|
Log.d(Constants.TAG, "SIGNATURE_UNKNOWN_PUB_KEY");
|
||||||
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY);
|
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY);
|
||||||
returnData.setSignatureResult(signatureResult);
|
result.setSignatureResult(signatureResult);
|
||||||
|
|
||||||
updateProgress(R.string.progress_done, 100, 100);
|
updateProgress(R.string.progress_done, 100, 100);
|
||||||
return returnData;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||||
@ -622,16 +642,21 @@ public class PgpDecryptVerify {
|
|||||||
boolean validKeyBinding = verifyKeyBinding(mContext, signature, signatureKey);
|
boolean validKeyBinding = verifyKeyBinding(mContext, signature, signatureKey);
|
||||||
boolean validSignature = signature.verify();
|
boolean validSignature = signature.verify();
|
||||||
|
|
||||||
if (validSignature & validKeyBinding) {
|
if (validKeyBinding & validSignature) {
|
||||||
|
Log.d(Constants.TAG, "SIGNATURE_SUCCESS_UNCERTIFIED");
|
||||||
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED);
|
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED);
|
||||||
|
} else {
|
||||||
|
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
|
||||||
|
Log.e(Constants.TAG, "Error!\nvalidKeyBinding: " + validKeyBinding
|
||||||
|
+ "\nvalidSignature: " + validSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: what about SIGNATURE_SUCCESS_CERTIFIED and SIGNATURE_ERROR????
|
// TODO: what about SIGNATURE_SUCCESS_CERTIFIED and SIGNATURE_ERROR????
|
||||||
|
|
||||||
returnData.setSignatureResult(signatureResult);
|
result.setSignatureResult(signatureResult);
|
||||||
|
|
||||||
updateProgress(R.string.progress_done, 100, 100);
|
updateProgress(R.string.progress_done, 100, 100);
|
||||||
return returnData;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean verifyKeyBinding(Context context,
|
private static boolean verifyKeyBinding(Context context,
|
||||||
|
Loading…
Reference in New Issue
Block a user