Rework verifyCleartextSignature

This commit is contained in:
Dominik Schürmann 2014-04-13 21:06:39 +02:00
parent e10b24e2ea
commit 55bad4cac7
1 changed files with 101 additions and 77 deletions

View File

@ -67,7 +67,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.SignatureException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
@ -450,7 +449,7 @@ public class PgpDecryptVerify {
isSignatureKeyCertified = (Long) data > 0;
} else {
// no key in our database -> return "unknwon pub key" status including the first key id
// no key in our database -> return "unknown pub key" status including the first key id
if (!sigList.isEmpty()) {
signatureResult.setKeyId(sigList.get(0).getKeyID());
}
@ -522,23 +521,13 @@ public class PgpDecryptVerify {
// TODO: what about binary signatures?
signatureResult.setSignatureOnly(false);
//Now check binding signatures
boolean validKeyBinding = verifyKeyBinding(messageSignature, signatureKey);
// Verify signature and check binding signatures
boolean validSignature = signature.verify(messageSignature);
boolean validKeyBinding = verifyKeyBinding(messageSignature, signatureKey);
if (validKeyBinding && validSignature) {
if (isSignatureKeyCertified) {
Log.d(Constants.TAG, "SIGNATURE_SUCCESS_CERTIFIED");
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED);
} else {
Log.d(Constants.TAG, "SIGNATURE_SUCCESS_UNCERTIFIED");
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED);
}
} else {
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
Log.e(Constants.TAG, "Error!\nvalidKeyBinding: " + validKeyBinding
+ "\nvalidSignature: " + validSignature);
}
signatureResult.setStatus(
getSignatureResultStatus(validSignature, validKeyBinding, isSignatureKeyCertified)
);
}
}
@ -610,92 +599,127 @@ public class PgpDecryptVerify {
if (sigList == null) {
throw new InvalidDataException();
}
PGPSignature signature = null;
long signatureKeyId = 0;
PGPPublicKey signatureKey = null;
// go through all signatures
// and find out for which signature we have a key in our database
Long masterKeyId = null;
int signatureIndex = 0;
for (int i = 0; i < sigList.size(); ++i) {
signature = sigList.get(i);
signatureKeyId = signature.getKeyID();
// find data about this subkey
HashMap<String, Object> data = mProviderHelper.getGenericData(
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(signature.getKeyID())),
new String[]{KeyRings.MASTER_KEY_ID, KeyRings.USER_ID},
new int[]{ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_STRING});
// any luck? otherwise, try next.
if (data.get(KeyRings.MASTER_KEY_ID) == null) {
signature = null;
// do NOT reset signatureMasterKeyId, that one is shown when no known one is found!
continue;
}
// this one can't fail now (yay database constraints)
try {
signatureKey = mProviderHelper.getPGPPublicKeyRing((Long) data.get(KeyRings.MASTER_KEY_ID)).getPublicKey();
Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(
Long.toString(sigList.get(i).getKeyID()));
masterKeyId = mProviderHelper.getMasterKeyId(uri);
signatureIndex = i;
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
Log.d(Constants.TAG, "key not found!");
// try next one...
}
signatureResult.setUserId((String) data.get(KeyRings.USER_ID));
break;
}
signatureResult.setKeyId(signatureKeyId);
PGPSignature signature = null;
PGPPublicKey signatureKey = null;
boolean isSignatureKeyCertified = false;
if (masterKeyId != null) {
// key found in our database!
try {
signatureKey = mProviderHelper
.getPGPPublicKeyRing(masterKeyId).getPublicKey();
} catch (ProviderHelper.NotFoundException e) {
// can't happen
}
signature = sigList.get(signatureIndex);
signatureResult.setUserId(PgpKeyHelper.getMainUserId(signatureKey));
signatureResult.setKeyId(signature.getKeyID());
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
signature.init(contentVerifierBuilderProvider, signatureKey);
// get certification status of this key
Object data = mProviderHelper.getGenericData(
KeychainContract.UserIds.buildUserIdsUri(Long.toString(masterKeyId)),
KeyRings.VERIFIED,
ProviderHelper.FIELD_TYPE_INTEGER);
isSignatureKeyCertified = (Long) data > 0;
} else {
// no key in our database -> return "unknown pub key" status including the first key id
if (!sigList.isEmpty()) {
signatureResult.setKeyId(sigList.get(0).getKeyID());
}
if (signature == null) {
Log.d(Constants.TAG, "SIGNATURE_UNKNOWN_PUB_KEY");
signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY);
result.setSignatureResult(signatureResult);
updateProgress(R.string.progress_done, 100, 100);
return result;
}
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
if (signature != null) {
updateProgress(R.string.progress_verifying_signature, 90, 100);
signature.init(contentVerifierBuilderProvider, signatureKey);
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
InputStream sigIn = new BufferedInputStream(new ByteArrayInputStream(clearText));
signature.init(contentVerifierBuilderProvider, signatureKey);
lookAhead = readInputLine(lineOut, sigIn);
InputStream sigIn = new BufferedInputStream(new ByteArrayInputStream(clearText));
processLine(signature, lineOut.toByteArray());
lookAhead = readInputLine(lineOut, sigIn);
if (lookAhead != -1) {
do {
lookAhead = readInputLine(lineOut, lookAhead, sigIn);
processLine(signature, lineOut.toByteArray());
signature.update((byte) '\r');
signature.update((byte) '\n');
if (lookAhead != -1) {
do {
lookAhead = readInputLine(lineOut, lookAhead, sigIn);
processLine(signature, lineOut.toByteArray());
} while (lookAhead != -1);
signature.update((byte) '\r');
signature.update((byte) '\n');
processLine(signature, lineOut.toByteArray());
} while (lookAhead != -1);
}
// Verify signature and check binding signatures
boolean validSignature = signature.verify();
boolean validKeyBinding = verifyKeyBinding(signature, signatureKey);
signatureResult.setStatus(
getSignatureResultStatus(validSignature, validKeyBinding, isSignatureKeyCertified)
);
}
//Now check binding signatures
boolean validKeyBinding = verifyKeyBinding(signature, signatureKey);
boolean validSignature = signature.verify();
if (validKeyBinding && validSignature) {
Log.d(Constants.TAG, "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????
result.setSignatureResult(signatureResult);
updateProgress(R.string.progress_done, 100, 100);
return result;
}
/**
* Returns SIGNATURE_SUCCESS_CERTIFIED, SIGNATURE_SUCCESS_UNCERTIFIED, or SIGNATURE_ERROR
*
* @param validSignature
* @param validKeyBinding
* @param isSignatureKeyCertified
* @return
*/
private int getSignatureResultStatus(boolean validSignature, boolean validKeyBinding, boolean isSignatureKeyCertified) {
if (validKeyBinding && validSignature) {
if (isSignatureKeyCertified) {
Log.d(Constants.TAG, "SIGNATURE_SUCCESS_CERTIFIED");
return OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED;
} else {
Log.d(Constants.TAG, "SIGNATURE_SUCCESS_UNCERTIFIED");
return OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED;
}
} else {
Log.e(Constants.TAG, "Error!\nvalidKeyBinding: " + validKeyBinding
+ "\nvalidSignature: " + validSignature);
return OpenPgpSignatureResult.SIGNATURE_ERROR;
}
}
private boolean verifyKeyBinding(PGPSignature signature, PGPPublicKey signatureKey) {
long signatureKeyId = signature.getKeyID();
boolean validKeyBinding = false;