1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-09 10:19:39 +02:00

Add workaround for decryption with non-encryption subkey

This commit is contained in:
Paul Schaub 2025-02-18 15:14:04 +01:00
parent fac87c371a
commit 0583a826d1
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
3 changed files with 32 additions and 4 deletions

View file

@ -43,6 +43,7 @@ class ConsumerOptions {
private val decryptionPassphrases = mutableSetOf<Passphrase>()
private var missingKeyPassphraseStrategy = MissingKeyPassphraseStrategy.INTERACTIVE
private var multiPassStrategy: MultiPassStrategy = InMemoryMultiPassStrategy()
private var allowDecryptionWithNonEncryptionKey: Boolean = false
/**
* Consider signatures on the message made before the given timestamp invalid. Null means no
@ -328,6 +329,14 @@ class ConsumerOptions {
fun isIgnoreMDCErrors(): Boolean = ignoreMDCErrors
fun setAllowDecryptionWithNonEncryptionKey(allow: Boolean): ConsumerOptions = apply {
allowDecryptionWithNonEncryptionKey = allow
}
fun getAllowDecryptionWithNonEncryptionKey(): Boolean {
return allowDecryptionWithNonEncryptionKey
}
/**
* Force PGPainless to handle the data provided by the [InputStream] as non-OpenPGP data. This
* workaround might come in handy if PGPainless accidentally mistakes the data for binary

View file

@ -409,6 +409,11 @@ class OpenPgpMessageInputStream(
val decryptionKeyCandidates = getDecryptionKeys(pkesk)
for (decryptionKeys in decryptionKeyCandidates) {
val secretKey = decryptionKeys.getSecretKeyFor(pkesk)!!
if (!secretKey.isEncryptionKey && !options.getAllowDecryptionWithNonEncryptionKey()) {
LOGGER.debug(
"Message is encrypted for ${secretKey.keyIdentifier}, but the key is not encryption capable.")
continue
}
if (hasUnsupportedS2KSpecifier(secretKey)) {
continue
}

View file

@ -14,7 +14,6 @@ import java.nio.charset.StandardCharsets;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.exception.MissingDecryptionMethodException;
@ -206,7 +205,6 @@ public class PreventDecryptionUsingNonEncryptionKeyTest {
}
@Test
@Disabled
public void nonEncryptionKeyCannotDecrypt() throws IOException {
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(ENCRYPTION_INCAPABLE_KEY);
@ -217,4 +215,20 @@ public class PreventDecryptionUsingNonEncryptionKeyTest {
.onInputStream(msgIn)
.withOptions(ConsumerOptions.get().addDecryptionKey(secretKeys)));
}
@Test
public void nonEncryptionKeyCanDecryptIfAllowed() throws IOException, PGPException {
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(ENCRYPTION_INCAPABLE_KEY);
ByteArrayInputStream msgIn = new ByteArrayInputStream(MSG.getBytes(StandardCharsets.UTF_8));
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(msgIn)
.withOptions(ConsumerOptions.get()
.setAllowDecryptionWithNonEncryptionKey(true)
.addDecryptionKey(secretKeys));
byte[] decrypted = Streams.readAll(decryptionStream);
decryptionStream.close();
}
}