1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-09 18:29: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 ce65e406c1
commit cb440776f2
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 val decryptionPassphrases = mutableSetOf<Passphrase>()
private var missingKeyPassphraseStrategy = MissingKeyPassphraseStrategy.INTERACTIVE private var missingKeyPassphraseStrategy = MissingKeyPassphraseStrategy.INTERACTIVE
private var multiPassStrategy: MultiPassStrategy = InMemoryMultiPassStrategy() private var multiPassStrategy: MultiPassStrategy = InMemoryMultiPassStrategy()
private var allowDecryptionWithNonEncryptionKey: Boolean = false
/** /**
* Consider signatures on the message made before the given timestamp invalid. Null means no * 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 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 * 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 * 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) val decryptionKeyCandidates = getDecryptionKeys(pkesk)
for (decryptionKeys in decryptionKeyCandidates) { for (decryptionKeys in decryptionKeyCandidates) {
val secretKey = decryptionKeys.getSecretKeyFor(pkesk)!! 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)) { if (hasUnsupportedS2KSpecifier(secretKey)) {
continue continue
} }

View file

@ -14,7 +14,6 @@ import java.nio.charset.StandardCharsets;
import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.util.io.Streams; import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless; import org.pgpainless.PGPainless;
import org.pgpainless.exception.MissingDecryptionMethodException; import org.pgpainless.exception.MissingDecryptionMethodException;
@ -206,7 +205,6 @@ public class PreventDecryptionUsingNonEncryptionKeyTest {
} }
@Test @Test
@Disabled
public void nonEncryptionKeyCannotDecrypt() throws IOException { public void nonEncryptionKeyCannotDecrypt() throws IOException {
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(ENCRYPTION_INCAPABLE_KEY); PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(ENCRYPTION_INCAPABLE_KEY);
@ -217,4 +215,20 @@ public class PreventDecryptionUsingNonEncryptionKeyTest {
.onInputStream(msgIn) .onInputStream(msgIn)
.withOptions(ConsumerOptions.get().addDecryptionKey(secretKeys))); .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();
}
} }