pgpdecryptverify: refactor signature processing
This commit is contained in:
@@ -44,13 +44,17 @@ import java.util.Iterator;
|
|||||||
public class CanonicalizedPublicKey extends UncachedPublicKey {
|
public class CanonicalizedPublicKey extends UncachedPublicKey {
|
||||||
|
|
||||||
// this is the parent key ring
|
// this is the parent key ring
|
||||||
final KeyRing mRing;
|
final CanonicalizedKeyRing mRing;
|
||||||
|
|
||||||
CanonicalizedPublicKey(KeyRing ring, PGPPublicKey key) {
|
CanonicalizedPublicKey(CanonicalizedKeyRing ring, PGPPublicKey key) {
|
||||||
super(key);
|
super(key);
|
||||||
mRing = ring;
|
mRing = ring;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CanonicalizedKeyRing getKeyRing() {
|
||||||
|
return mRing;
|
||||||
|
}
|
||||||
|
|
||||||
public IterableIterator<String> getUserIds() {
|
public IterableIterator<String> getUserIds() {
|
||||||
return new IterableIterator<String>(mPublicKey.getUserIDs());
|
return new IterableIterator<String>(mPublicKey.getUserIDs());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,11 +91,12 @@ public class OpenPgpSignatureResultBuilder {
|
|||||||
return mInsecure;
|
return mInsecure;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initValid(CanonicalizedPublicKeyRing signingRing,
|
public void initValid(CanonicalizedPublicKey signingKey) {
|
||||||
CanonicalizedPublicKey signingKey) {
|
|
||||||
setSignatureAvailable(true);
|
setSignatureAvailable(true);
|
||||||
setKnownKey(true);
|
setKnownKey(true);
|
||||||
|
|
||||||
|
CanonicalizedKeyRing signingRing = signingKey.getKeyRing();
|
||||||
|
|
||||||
// from RING
|
// from RING
|
||||||
setKeyId(signingRing.getMasterKeyId());
|
setKeyId(signingRing.getMasterKeyId());
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -214,32 +214,15 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
}
|
}
|
||||||
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) o;
|
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) o;
|
||||||
|
|
||||||
// go through all signatures (should be just one), make sure we have
|
SignatureData signatureData = findAvailableSignature(sigList);
|
||||||
// the key and it matches the one we’re 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...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// there has to be a key, and it has to be the right one
|
if (signatureData == null) {
|
||||||
if (signingKey == null) {
|
|
||||||
log.add(LogType.MSG_VL_ERROR_MISSING_KEY, indent);
|
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);
|
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))) {
|
if (!(input.getRequiredSignerFingerprint().equals(fingerprint))) {
|
||||||
log.add(LogType.MSG_VL_ERROR_MISSING_KEY, indent);
|
log.add(LogType.MSG_VL_ERROR_MISSING_KEY, indent);
|
||||||
Log.d(Constants.TAG, "Fingerprint mismatch; wanted " + input.getRequiredSignerFingerprint() +
|
Log.d(Constants.TAG, "Fingerprint mismatch; wanted " + input.getRequiredSignerFingerprint() +
|
||||||
@@ -249,13 +232,13 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
|
|
||||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
||||||
|
|
||||||
PGPOnePassSignature signature = sigList.get(signatureIndex);
|
PGPOnePassSignature signature = sigList.get(signatureData.signatureIndex);
|
||||||
signatureResultBuilder.initValid(signingRing, signingKey);
|
signatureResultBuilder.initValid(signatureData.signingKey);
|
||||||
|
|
||||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||||
new JcaPGPContentVerifierBuilderProvider()
|
new JcaPGPContentVerifierBuilderProvider()
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
|
signature.init(contentVerifierBuilderProvider, signatureData.signingKey.getPublicKey());
|
||||||
|
|
||||||
o = pgpF.nextObject();
|
o = pgpF.nextObject();
|
||||||
|
|
||||||
@@ -282,7 +265,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
log.add(LogType.MSG_VL_CLEAR_SIGNATURE_CHECK, indent + 1);
|
log.add(LogType.MSG_VL_CLEAR_SIGNATURE_CHECK, indent + 1);
|
||||||
|
|
||||||
PGPSignatureList signatureList = (PGPSignatureList) pgpF.nextObject();
|
PGPSignatureList signatureList = (PGPSignatureList) pgpF.nextObject();
|
||||||
PGPSignature messageSignature = signatureList.get(signatureIndex);
|
PGPSignature messageSignature = signatureList.get(signatureData.signatureIndex);
|
||||||
|
|
||||||
// Verify signature and check binding signatures
|
// Verify signature and check binding signatures
|
||||||
boolean validSignature = signature.verify(messageSignature);
|
boolean validSignature = signature.verify(messageSignature);
|
||||||
@@ -415,9 +398,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
|
|
||||||
log.add(LogType.MSG_DC_PREP_STREAMS, indent);
|
log.add(LogType.MSG_DC_PREP_STREAMS, indent);
|
||||||
|
|
||||||
int signatureIndex = -1;
|
SignatureData signatureData = null;
|
||||||
CanonicalizedPublicKeyRing signingRing = null;
|
|
||||||
CanonicalizedPublicKey signingKey = null;
|
|
||||||
|
|
||||||
log.add(LogType.MSG_DC_CLEAR, indent);
|
log.add(LogType.MSG_DC_CLEAR, indent);
|
||||||
indent += 1;
|
indent += 1;
|
||||||
@@ -443,34 +424,17 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
updateProgress(R.string.progress_processing_signature, currentProgress, 100);
|
updateProgress(R.string.progress_processing_signature, currentProgress, 100);
|
||||||
|
|
||||||
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk;
|
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk;
|
||||||
|
signatureData = findAvailableSignature(sigList);
|
||||||
|
|
||||||
// NOTE: following code is similar to processSignature, but for PGPOnePassSignature
|
if (signatureData != null) {
|
||||||
|
|
||||||
// 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) {
|
|
||||||
// key found in our database!
|
// key found in our database!
|
||||||
signature = sigList.get(signatureIndex);
|
signature = sigList.get(signatureData.signatureIndex);
|
||||||
|
signatureResultBuilder.initValid(signatureData.signingKey);
|
||||||
signatureResultBuilder.initValid(signingRing, signingKey);
|
|
||||||
|
|
||||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||||
new JcaPGPContentVerifierBuilderProvider()
|
new JcaPGPContentVerifierBuilderProvider()
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
|
signature.init(contentVerifierBuilderProvider, signatureData.signingKey.getPublicKey());
|
||||||
} else {
|
} else {
|
||||||
// no key in our database -> return "unknown 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()) {
|
if (!sigList.isEmpty()) {
|
||||||
@@ -482,7 +446,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
|
|
||||||
// check for insecure signing key
|
// check for insecure signing key
|
||||||
// TODO: checks on signingRing ?
|
// 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);
|
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
|
||||||
signatureResultBuilder.setInsecure(true);
|
signatureResultBuilder.setInsecure(true);
|
||||||
}
|
}
|
||||||
@@ -610,12 +574,12 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
metadata = new OpenPgpMetadata(
|
metadata = new OpenPgpMetadata(
|
||||||
originalFilename, mimeType, literalData.getModificationTime().getTime(), alreadyWritten, charset);
|
originalFilename, mimeType, literalData.getModificationTime().getTime(), alreadyWritten, charset);
|
||||||
|
|
||||||
if (signature != null) {
|
if (signatureData != null) {
|
||||||
updateProgress(R.string.progress_verifying_signature, 90, 100);
|
updateProgress(R.string.progress_verifying_signature, 90, 100);
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
|
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
|
||||||
|
|
||||||
PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
|
PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
|
||||||
PGPSignature messageSignature = signatureList.get(signatureIndex);
|
PGPSignature messageSignature = signatureList.get(signatureData.signatureIndex);
|
||||||
|
|
||||||
// Verify signature
|
// Verify signature
|
||||||
boolean validSignature = signature.verify(messageSignature);
|
boolean validSignature = signature.verify(messageSignature);
|
||||||
@@ -1147,37 +1111,21 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
PGPSignatureList sigList, OpenPgpSignatureResultBuilder signatureResultBuilder,
|
PGPSignatureList sigList, OpenPgpSignatureResultBuilder signatureResultBuilder,
|
||||||
OperationLog log, int indent)
|
OperationLog log, int indent)
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
CanonicalizedPublicKeyRing signingRing = null;
|
|
||||||
CanonicalizedPublicKey signingKey = null;
|
|
||||||
int signatureIndex = -1;
|
|
||||||
|
|
||||||
// go through all signatures
|
SignatureData signatureData = findAvailableSignature(sigList);
|
||||||
// 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...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PGPSignature signature = null;
|
PGPSignature signature = null;
|
||||||
|
|
||||||
if (signingKey != null) {
|
if (signatureData != null) {
|
||||||
// key found in our database!
|
// key found in our database!
|
||||||
signature = sigList.get(signatureIndex);
|
signature = sigList.get(signatureData.signatureIndex);
|
||||||
|
|
||||||
signatureResultBuilder.initValid(signingRing, signingKey);
|
signatureResultBuilder.initValid(signatureData.signingKey);
|
||||||
|
|
||||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||||
new JcaPGPContentVerifierBuilderProvider()
|
new JcaPGPContentVerifierBuilderProvider()
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
|
signature.init(contentVerifierBuilderProvider, signatureData.signingKey.getPublicKey());
|
||||||
} else {
|
} else {
|
||||||
// no key in our database -> return "unknown 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()) {
|
if (!sigList.isEmpty()) {
|
||||||
@@ -1189,7 +1137,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
|
|
||||||
// check for insecure signing key
|
// check for insecure signing key
|
||||||
// TODO: checks on signingRing ?
|
// 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);
|
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
|
||||||
signatureResultBuilder.setInsecure(true);
|
signatureResultBuilder.setInsecure(true);
|
||||||
}
|
}
|
||||||
@@ -1291,4 +1239,54 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
String nl = System.getProperty("line.separator");
|
String nl = System.getProperty("line.separator");
|
||||||
return nl.getBytes();
|
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 we’re 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 we’re 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user