pgpdecryptverify: refactor signature processing

This commit is contained in:
Vincent Breitmoser
2015-10-06 17:34:47 +02:00
parent 8f40c6df51
commit bafc108969
3 changed files with 82 additions and 79 deletions

View File

@@ -44,13 +44,17 @@ import java.util.Iterator;
public class CanonicalizedPublicKey extends UncachedPublicKey {
// this is the parent key ring
final KeyRing mRing;
final CanonicalizedKeyRing mRing;
CanonicalizedPublicKey(KeyRing ring, PGPPublicKey key) {
CanonicalizedPublicKey(CanonicalizedKeyRing ring, PGPPublicKey key) {
super(key);
mRing = ring;
}
public CanonicalizedKeyRing getKeyRing() {
return mRing;
}
public IterableIterator<String> getUserIds() {
return new IterableIterator<String>(mPublicKey.getUserIDs());
}

View File

@@ -91,11 +91,12 @@ public class OpenPgpSignatureResultBuilder {
return mInsecure;
}
public void initValid(CanonicalizedPublicKeyRing signingRing,
CanonicalizedPublicKey signingKey) {
public void initValid(CanonicalizedPublicKey signingKey) {
setSignatureAvailable(true);
setKnownKey(true);
CanonicalizedKeyRing signingRing = signingKey.getKeyRing();
// from RING
setKeyId(signingRing.getMasterKeyId());
try {

View File

@@ -214,32 +214,15 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
}
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) o;
// go through all signatures (should be just one), make sure we have
// the key and it matches the one were looking for
CanonicalizedPublicKeyRing signingRing = null;
CanonicalizedPublicKey signingKey = null;
int signatureIndex = -1;
for (int i = 0; i < sigList.size(); ++i) {
try {
long sigKeyId = sigList.get(i).getKeyID();
signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
);
signingKey = signingRing.getPublicKey(sigKeyId);
signatureIndex = i;
} catch (ProviderHelper.NotFoundException e) {
Log.d(Constants.TAG, "key not found, trying next signature...");
}
}
SignatureData signatureData = findAvailableSignature(sigList);
// there has to be a key, and it has to be the right one
if (signingKey == null) {
if (signatureData == null) {
log.add(LogType.MSG_VL_ERROR_MISSING_KEY, indent);
Log.d(Constants.TAG, "Failed to find key in signed-literal message");
Log.d(Constants.TAG, "Failed to find signature with available key in signed-literal message");
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
}
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(signingRing.getFingerprint());
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(signatureData.signingKey.getFingerprint());
if (!(input.getRequiredSignerFingerprint().equals(fingerprint))) {
log.add(LogType.MSG_VL_ERROR_MISSING_KEY, indent);
Log.d(Constants.TAG, "Fingerprint mismatch; wanted " + input.getRequiredSignerFingerprint() +
@@ -249,13 +232,13 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
PGPOnePassSignature signature = sigList.get(signatureIndex);
signatureResultBuilder.initValid(signingRing, signingKey);
PGPOnePassSignature signature = sigList.get(signatureData.signatureIndex);
signatureResultBuilder.initValid(signatureData.signingKey);
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
signature.init(contentVerifierBuilderProvider, signatureData.signingKey.getPublicKey());
o = pgpF.nextObject();
@@ -282,7 +265,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
log.add(LogType.MSG_VL_CLEAR_SIGNATURE_CHECK, indent + 1);
PGPSignatureList signatureList = (PGPSignatureList) pgpF.nextObject();
PGPSignature messageSignature = signatureList.get(signatureIndex);
PGPSignature messageSignature = signatureList.get(signatureData.signatureIndex);
// Verify signature and check binding signatures
boolean validSignature = signature.verify(messageSignature);
@@ -415,9 +398,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
log.add(LogType.MSG_DC_PREP_STREAMS, indent);
int signatureIndex = -1;
CanonicalizedPublicKeyRing signingRing = null;
CanonicalizedPublicKey signingKey = null;
SignatureData signatureData = null;
log.add(LogType.MSG_DC_CLEAR, indent);
indent += 1;
@@ -443,34 +424,17 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
updateProgress(R.string.progress_processing_signature, currentProgress, 100);
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk;
signatureData = findAvailableSignature(sigList);
// NOTE: following code is similar to processSignature, but for PGPOnePassSignature
// go through all signatures
// and find out for which signature we have a key in our database
for (int i = 0; i < sigList.size(); ++i) {
try {
long sigKeyId = sigList.get(i).getKeyID();
signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
);
signingKey = signingRing.getPublicKey(sigKeyId);
signatureIndex = i;
} catch (ProviderHelper.NotFoundException e) {
Log.d(Constants.TAG, "key not found, trying next signature...");
}
}
if (signingKey != null) {
if (signatureData != null) {
// key found in our database!
signature = sigList.get(signatureIndex);
signatureResultBuilder.initValid(signingRing, signingKey);
signature = sigList.get(signatureData.signatureIndex);
signatureResultBuilder.initValid(signatureData.signingKey);
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
signature.init(contentVerifierBuilderProvider, signatureData.signingKey.getPublicKey());
} else {
// no key in our database -> return "unknown pub key" status including the first key id
if (!sigList.isEmpty()) {
@@ -482,7 +446,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
// check for insecure signing key
// TODO: checks on signingRing ?
if (signingKey != null && ! PgpSecurityConstants.isSecureKey(signingKey)) {
if (signatureData != null && ! PgpSecurityConstants.isSecureKey(signatureData.signingKey)) {
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
signatureResultBuilder.setInsecure(true);
}
@@ -610,12 +574,12 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
metadata = new OpenPgpMetadata(
originalFilename, mimeType, literalData.getModificationTime().getTime(), alreadyWritten, charset);
if (signature != null) {
if (signatureData != null) {
updateProgress(R.string.progress_verifying_signature, 90, 100);
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
PGPSignature messageSignature = signatureList.get(signatureIndex);
PGPSignature messageSignature = signatureList.get(signatureData.signatureIndex);
// Verify signature
boolean validSignature = signature.verify(messageSignature);
@@ -1147,37 +1111,21 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
PGPSignatureList sigList, OpenPgpSignatureResultBuilder signatureResultBuilder,
OperationLog log, int indent)
throws PGPException {
CanonicalizedPublicKeyRing signingRing = null;
CanonicalizedPublicKey signingKey = null;
int signatureIndex = -1;
// go through all signatures
// and find out for which signature we have a key in our database
for (int i = 0; i < sigList.size(); ++i) {
try {
long sigKeyId = sigList.get(i).getKeyID();
signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
);
signingKey = signingRing.getPublicKey(sigKeyId);
signatureIndex = i;
} catch (ProviderHelper.NotFoundException e) {
Log.d(Constants.TAG, "key not found, trying next signature...");
}
}
SignatureData signatureData = findAvailableSignature(sigList);
PGPSignature signature = null;
if (signingKey != null) {
if (signatureData != null) {
// key found in our database!
signature = sigList.get(signatureIndex);
signature = sigList.get(signatureData.signatureIndex);
signatureResultBuilder.initValid(signingRing, signingKey);
signatureResultBuilder.initValid(signatureData.signingKey);
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
signature.init(contentVerifierBuilderProvider, signatureData.signingKey.getPublicKey());
} else {
// no key in our database -> return "unknown pub key" status including the first key id
if (!sigList.isEmpty()) {
@@ -1189,7 +1137,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
// check for insecure signing key
// TODO: checks on signingRing ?
if (signingKey != null && ! PgpSecurityConstants.isSecureKey(signingKey)) {
if (signatureData != null && ! PgpSecurityConstants.isSecureKey(signatureData.signingKey)) {
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
signatureResultBuilder.setInsecure(true);
}
@@ -1291,4 +1239,54 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
String nl = System.getProperty("line.separator");
return nl.getBytes();
}
private static class SignatureData {
final private CanonicalizedPublicKey signingKey;
// we use the signatureIndex instead of the signature itself here for two reasons:
// 1) the signature may be either of type PGPSignature or PGPOnePassSignature (which have no common ancestor)
// 2) in case of the latter, we need the signatureIndex to know which PGPSignature to use later on
final private int signatureIndex;
SignatureData(CanonicalizedPublicKey signingKey, int signatureIndex) {
this.signingKey = signingKey;
this.signatureIndex = signatureIndex;
}
}
public SignatureData findAvailableSignature(PGPOnePassSignatureList sigList) {
// go through all signatures (should be just one), make sure we have
// the key and it matches the one were looking for
for (int i = 0; i < sigList.size(); ++i) {
try {
long sigKeyId = sigList.get(i).getKeyID();
CanonicalizedPublicKeyRing signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
);
return new SignatureData(signingRing.getPublicKey(sigKeyId), i);
} catch (ProviderHelper.NotFoundException e) {
Log.d(Constants.TAG, "key not found, trying next signature...");
}
}
return null;
}
public SignatureData findAvailableSignature(PGPSignatureList sigList) {
// go through all signatures (should be just one), make sure we have
// the key and it matches the one were looking for
for (int i = 0; i < sigList.size(); ++i) {
try {
long sigKeyId = sigList.get(i).getKeyID();
CanonicalizedPublicKeyRing signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
);
return new SignatureData(signingRing.getPublicKey(sigKeyId), i);
} catch (ProviderHelper.NotFoundException e) {
Log.d(Constants.TAG, "key not found, trying next signature...");
}
}
return null;
}
}