mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-01-09 19:57:57 +01:00
Throw WrongConsumingMethodException when processing Cleartext Signed Messages with Inband Signature verification API and vice versa
This commit is contained in:
parent
2885ff7a14
commit
97c8ff8312
5 changed files with 88 additions and 3 deletions
|
@ -58,6 +58,7 @@ import org.pgpainless.exception.MessageNotIntegrityProtectedException;
|
||||||
import org.pgpainless.exception.MissingDecryptionMethodException;
|
import org.pgpainless.exception.MissingDecryptionMethodException;
|
||||||
import org.pgpainless.exception.MissingLiteralDataException;
|
import org.pgpainless.exception.MissingLiteralDataException;
|
||||||
import org.pgpainless.exception.UnacceptableAlgorithmException;
|
import org.pgpainless.exception.UnacceptableAlgorithmException;
|
||||||
|
import org.pgpainless.exception.WrongConsumingMethodException;
|
||||||
import org.pgpainless.implementation.ImplementationFactory;
|
import org.pgpainless.implementation.ImplementationFactory;
|
||||||
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
||||||
import org.pgpainless.key.SubkeyIdentifier;
|
import org.pgpainless.key.SubkeyIdentifier;
|
||||||
|
@ -121,6 +122,15 @@ public final class DecryptionStreamFactory {
|
||||||
InputStream decoderStream = PGPUtil.getDecoderStream(bufferedIn);
|
InputStream decoderStream = PGPUtil.getDecoderStream(bufferedIn);
|
||||||
decoderStream = CRCingArmoredInputStreamWrapper.possiblyWrap(decoderStream);
|
decoderStream = CRCingArmoredInputStreamWrapper.possiblyWrap(decoderStream);
|
||||||
|
|
||||||
|
if (decoderStream instanceof ArmoredInputStream) {
|
||||||
|
ArmoredInputStream armor = (ArmoredInputStream) decoderStream;
|
||||||
|
|
||||||
|
if (armor.isClearText()) {
|
||||||
|
throw new WrongConsumingMethodException("Message appears to be using the Cleartext Signature Framework. " +
|
||||||
|
"Use PGPainless.verifyCleartextSignedMessage() to verify this message instead.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PGPObjectFactory objectFactory = new PGPObjectFactory(
|
PGPObjectFactory objectFactory = new PGPObjectFactory(
|
||||||
decoderStream, keyFingerprintCalculator);
|
decoderStream, keyFingerprintCalculator);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 Paul Schaub.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.pgpainless.exception;
|
||||||
|
|
||||||
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
|
||||||
|
public class WrongConsumingMethodException extends PGPException {
|
||||||
|
|
||||||
|
public WrongConsumingMethodException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import org.bouncycastle.bcpg.ArmoredInputStream;
|
||||||
import org.bouncycastle.openpgp.PGPObjectFactory;
|
import org.bouncycastle.openpgp.PGPObjectFactory;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureList;
|
import org.bouncycastle.openpgp.PGPSignatureList;
|
||||||
import org.bouncycastle.util.Strings;
|
import org.bouncycastle.util.Strings;
|
||||||
|
import org.pgpainless.exception.WrongConsumingMethodException;
|
||||||
import org.pgpainless.implementation.ImplementationFactory;
|
import org.pgpainless.implementation.ImplementationFactory;
|
||||||
import org.pgpainless.util.ArmoredInputStreamFactory;
|
import org.pgpainless.util.ArmoredInputStreamFactory;
|
||||||
|
|
||||||
|
@ -49,10 +50,10 @@ public final class ClearsignedMessageUtil {
|
||||||
*/
|
*/
|
||||||
public static PGPSignatureList detachSignaturesFromInbandClearsignedMessage(InputStream clearsignedInputStream,
|
public static PGPSignatureList detachSignaturesFromInbandClearsignedMessage(InputStream clearsignedInputStream,
|
||||||
OutputStream messageOutputStream)
|
OutputStream messageOutputStream)
|
||||||
throws IOException {
|
throws IOException, WrongConsumingMethodException {
|
||||||
ArmoredInputStream in = ArmoredInputStreamFactory.get(clearsignedInputStream);
|
ArmoredInputStream in = ArmoredInputStreamFactory.get(clearsignedInputStream);
|
||||||
if (!in.isClearText()) {
|
if (!in.isClearText()) {
|
||||||
throw new IOException("Message is not clearsigned.");
|
throw new WrongConsumingMethodException("Message is not using the Cleartext Signature Framework.");
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream out = new BufferedOutputStream(messageOutputStream);
|
OutputStream out = new BufferedOutputStream(messageOutputStream);
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.pgpainless.decryption_verification;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
@ -32,6 +33,7 @@ import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.util.io.Streams;
|
import org.bouncycastle.util.io.Streams;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
import org.pgpainless.exception.WrongConsumingMethodException;
|
||||||
import org.pgpainless.key.TestKeys;
|
import org.pgpainless.key.TestKeys;
|
||||||
import org.pgpainless.signature.CertificateValidator;
|
import org.pgpainless.signature.CertificateValidator;
|
||||||
import org.pgpainless.signature.SignatureUtils;
|
import org.pgpainless.signature.SignatureUtils;
|
||||||
|
@ -157,4 +159,45 @@ public class CleartextSignatureVerificationTest {
|
||||||
OpenPgpMetadata metadata = decryptionStream.getResult();
|
OpenPgpMetadata metadata = decryptionStream.getResult();
|
||||||
assertEquals(1, metadata.getVerifiedSignatures().size());
|
assertEquals(1, metadata.getVerifiedSignatures().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void consumingCleartextSignedMessageWithNormalAPIThrowsWrongConsumingMethodException() throws IOException, PGPException {
|
||||||
|
PGPPublicKeyRing certificate = TestKeys.getEmilPublicKeyRing();
|
||||||
|
ConsumerOptions options = new ConsumerOptions()
|
||||||
|
.addVerificationCert(certificate);
|
||||||
|
|
||||||
|
assertThrows(WrongConsumingMethodException.class, () ->
|
||||||
|
PGPainless.decryptAndOrVerify()
|
||||||
|
.onInputStream(new ByteArrayInputStream(MESSAGE_SIGNED))
|
||||||
|
.withOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void consumingInlineSignedMessageWithCleartextSignedVerificationApiThrowsWrongConsumingMethodException() throws PGPException, IOException {
|
||||||
|
String inlineSignedMessage = "-----BEGIN PGP MESSAGE-----\n" +
|
||||||
|
"Version: PGPainless\n" +
|
||||||
|
"\n" +
|
||||||
|
"kA0DAQoTVzbmkxrPNwwBy8BJYgAAAAAAQWgsIEp1bGlldCwgaWYgdGhlIG1lYXN1\n" +
|
||||||
|
"cmUgb2YgdGh5IGpveQpCZSBoZWFwZWQgbGlrZSBtaW5lLCBhbmQgdGhhdCB0aHkg\n" +
|
||||||
|
"c2tpbGwgYmUgbW9yZQpUbyBibGF6b24gaXQsIHRoZW4gc3dlZXRlbiB3aXRoIHRo\n" +
|
||||||
|
"eSBicmVhdGgKVGhpcyBuZWlnaGJvciBhaXIsIGFuZCBsZXQgcmljaCBtdXNpY+KA\n" +
|
||||||
|
"mXMgdG9uZ3VlClVuZm9sZCB0aGUgaW1hZ2luZWQgaGFwcGluZXNzIHRoYXQgYm90\n" +
|
||||||
|
"aApSZWNlaXZlIGluIGVpdGhlciBieSB0aGlzIGRlYXIgZW5jb3VudGVyLoh1BAET\n" +
|
||||||
|
"CgAGBQJhK2q9ACEJEFc25pMazzcMFiEET2ZcTcLEZgvGQl5BVzbmkxrPNwxr8gD+\n" +
|
||||||
|
"MDfg+qccpsoJVgHIW8mRPBQowXDyw+oNHsf28ii+/pEBAO/RXhFkZBPzlfDJMJVT\n" +
|
||||||
|
"UwJJeuna1R4yOoWjq0zqRvrg\n" +
|
||||||
|
"=dBiV\n" +
|
||||||
|
"-----END PGP MESSAGE-----\n";
|
||||||
|
|
||||||
|
PGPPublicKeyRing certificate = TestKeys.getEmilPublicKeyRing();
|
||||||
|
ConsumerOptions options = new ConsumerOptions()
|
||||||
|
.addVerificationCert(certificate);
|
||||||
|
|
||||||
|
assertThrows(WrongConsumingMethodException.class, () ->
|
||||||
|
PGPainless.verifyCleartextSignedMessage()
|
||||||
|
.onInputStream(new ByteArrayInputStream(inlineSignedMessage.getBytes(StandardCharsets.UTF_8)))
|
||||||
|
.withStrategy(new InMemoryMultiPassStrategy())
|
||||||
|
.withOptions(options)
|
||||||
|
.process());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.io.OutputStream;
|
||||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureList;
|
import org.bouncycastle.openpgp.PGPSignatureList;
|
||||||
|
import org.pgpainless.exception.WrongConsumingMethodException;
|
||||||
import org.pgpainless.signature.cleartext_signatures.ClearsignedMessageUtil;
|
import org.pgpainless.signature.cleartext_signatures.ClearsignedMessageUtil;
|
||||||
import org.pgpainless.util.ArmoredOutputStreamFactory;
|
import org.pgpainless.util.ArmoredOutputStreamFactory;
|
||||||
import sop.ReadyWithResult;
|
import sop.ReadyWithResult;
|
||||||
|
@ -49,7 +50,12 @@ public class DetachInbandSignatureAndMessageImpl implements DetachInbandSignatur
|
||||||
return new Signatures() {
|
return new Signatures() {
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(OutputStream signatureOutputStream) throws IOException {
|
public void writeTo(OutputStream signatureOutputStream) throws IOException {
|
||||||
PGPSignatureList signatures = ClearsignedMessageUtil.detachSignaturesFromInbandClearsignedMessage(messageInputStream, messageOutputStream);
|
PGPSignatureList signatures = null;
|
||||||
|
try {
|
||||||
|
signatures = ClearsignedMessageUtil.detachSignaturesFromInbandClearsignedMessage(messageInputStream, messageOutputStream);
|
||||||
|
} catch (WrongConsumingMethodException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
if (armor) {
|
if (armor) {
|
||||||
ArmoredOutputStream armorOut = ArmoredOutputStreamFactory.get(signatureOutputStream);
|
ArmoredOutputStream armorOut = ArmoredOutputStreamFactory.get(signatureOutputStream);
|
||||||
for (PGPSignature signature : signatures) {
|
for (PGPSignature signature : signatures) {
|
||||||
|
|
Loading…
Reference in a new issue