mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-09 18:29:39 +02:00
Fuzzer tests
This commit is contained in:
parent
556766e0bf
commit
599c689c2e
27 changed files with 160 additions and 29 deletions
|
@ -8,6 +8,7 @@ import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import openpgp.plusSeconds
|
import openpgp.plusSeconds
|
||||||
|
import org.bouncycastle.bcpg.UnsupportedPacketVersionException
|
||||||
import org.bouncycastle.bcpg.sig.KeyExpirationTime
|
import org.bouncycastle.bcpg.sig.KeyExpirationTime
|
||||||
import org.bouncycastle.openpgp.*
|
import org.bouncycastle.openpgp.*
|
||||||
import org.bouncycastle.util.encoders.Hex
|
import org.bouncycastle.util.encoders.Hex
|
||||||
|
@ -151,37 +152,46 @@ class SignatureUtils {
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun readSignatures(inputStream: InputStream, maxIterations: Int): List<PGPSignature> {
|
fun readSignatures(inputStream: InputStream, maxIterations: Int): List<PGPSignature> {
|
||||||
val signatures = mutableListOf<PGPSignature>()
|
try {
|
||||||
val pgpIn = ArmorUtils.getDecoderStream(inputStream)
|
val signatures = mutableListOf<PGPSignature>()
|
||||||
val objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(pgpIn)
|
val pgpIn = ArmorUtils.getDecoderStream(inputStream)
|
||||||
|
val objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(pgpIn)
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
var nextObject: Any? = null
|
var nextObject: Any? = null
|
||||||
while (i++ < maxIterations &&
|
while (i++ < maxIterations &&
|
||||||
objectFactory.nextObject().also { nextObject = it } != null) {
|
objectFactory.nextObject().also { nextObject = it } != null) {
|
||||||
// Since signatures are indistinguishable from randomness, there is no point in
|
// Since signatures are indistinguishable from randomness, there is no point in
|
||||||
// having them compressed,
|
// having them compressed,
|
||||||
// except for an attacker who is trying to exploit flaws in the decompression
|
// except for an attacker who is trying to exploit flaws in the decompression
|
||||||
// algorithm.
|
// algorithm.
|
||||||
// Therefore, we ignore compressed data packets without attempting decompression.
|
// Therefore, we ignore compressed data packets without attempting decompression.
|
||||||
if (nextObject is PGPCompressedData) {
|
if (nextObject is PGPCompressedData) {
|
||||||
// getInputStream() does not do decompression, contrary to getDataStream().
|
// getInputStream() does not do decompression, contrary to getDataStream().
|
||||||
Streams.drain(
|
Streams.drain(
|
||||||
(nextObject as PGPCompressedData)
|
(nextObject as PGPCompressedData)
|
||||||
.inputStream) // Skip packet without decompressing
|
.inputStream
|
||||||
|
) // Skip packet without decompressing
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextObject is PGPSignatureList) {
|
||||||
|
signatures.addAll(nextObject as PGPSignatureList)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextObject is PGPSignature) {
|
||||||
|
signatures.add(nextObject as PGPSignature)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextObject is PGPSignatureList) {
|
pgpIn.close()
|
||||||
signatures.addAll(nextObject as PGPSignatureList)
|
return signatures.toList()
|
||||||
}
|
} catch (e: UnsupportedPacketVersionException) {
|
||||||
|
throw PGPException("Unsupported packet version encountered.", e)
|
||||||
if (nextObject is PGPSignature) {
|
} catch (e: ClassCastException) {
|
||||||
signatures.add(nextObject as PGPSignature)
|
throw PGPException("Unexpected packet encountered.", e)
|
||||||
}
|
} catch (e: IllegalArgumentException) {
|
||||||
|
throw PGPException("Malformed packet encountered.", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
pgpIn.close()
|
|
||||||
return signatures.toList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,8 +29,11 @@ class DetachedVerifyImpl : DetachedVerify {
|
||||||
override fun data(data: InputStream): List<Verification> {
|
override fun data(data: InputStream): List<Verification> {
|
||||||
try {
|
try {
|
||||||
val verificationStream =
|
val verificationStream =
|
||||||
PGPainless.decryptAndOrVerify().onInputStream(data).withOptions(options)
|
try {
|
||||||
|
PGPainless.decryptAndOrVerify().onInputStream(data).withOptions(options)
|
||||||
|
} catch (e: RuntimeException) {
|
||||||
|
throw SOPGPException.BadData(e)
|
||||||
|
}
|
||||||
Streams.drain(verificationStream)
|
Streams.drain(verificationStream)
|
||||||
verificationStream.close()
|
verificationStream.close()
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package org.pgpainless.sop.fuzzing;
|
package org.pgpainless.sop.fuzzing;
|
||||||
|
|
||||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package org.pgpainless.sop.fuzzing;
|
package org.pgpainless.sop.fuzzing;
|
||||||
|
|
||||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
// SPDX-FileCopyrightText: 2025 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.sop.fuzzing;
|
||||||
|
|
||||||
|
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||||
|
import com.code_intelligence.jazzer.junit.FuzzTest;
|
||||||
|
import org.pgpainless.sop.SOPImpl;
|
||||||
|
import sop.SOP;
|
||||||
|
import sop.Verification;
|
||||||
|
import sop.exception.SOPGPException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SignatureFuzzTest {
|
||||||
|
|
||||||
|
private final SOP sop = new SOPImpl();
|
||||||
|
private final byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
private final String key = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||||
|
"Comment: D7BC FF6B B105 40D9 87F9 CB6E 542D C9F6 FCAE AD63\n" +
|
||||||
|
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||||
|
"\n" +
|
||||||
|
"lFgEaGzu+BYJKwYBBAHaRw8BAQdAlqjB241N44drAJvxa3wx0uRb5bxuVNXrCwPZ\n" +
|
||||||
|
"yf4Qg+MAAQCpACcGmoOPZISRbMjRzI/0Wf5iIZwp7r9huzLe6NToBRFxtBxBbGlj\n" +
|
||||||
|
"ZSA8YWxpY2VAcGdwYWlubGVzcy5vcmc+wpUEExYKAEcFgmhs7vgJEFQtyfb8rq1j\n" +
|
||||||
|
"FiEE17z/a7EFQNmH+ctuVC3J9vyurWMCngECmwEFFgIDAQAECwkIBwUVCgkICwWJ\n" +
|
||||||
|
"CWYBfwKZAQAA1SMBAIuffSIKKkG73rWInDrfV6G0kCh/uP7Qf3Jh4A+x5BrvAP42\n" +
|
||||||
|
"KANAmmLmDVsPGWEPEAlCAJFwKZvHzvYsk8dEFNZEDJxYBGhs7vgWCSsGAQQB2kcP\n" +
|
||||||
|
"AQEHQOPChGD0z51fOsnFswJPNmhzxdhZHuXCxbEJ+/5WhU9QAAEA3i0J/Vbyhj92\n" +
|
||||||
|
"kd8gsjLUIkbDHGGDb/vfRCgmRAySF1MOL8LAFQQYFgoAfQWCaGzu+AKeAQKbAgUW\n" +
|
||||||
|
"AgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFgmhs7vgACgkQIvV9b29BRNSV1AEAtywX\n" +
|
||||||
|
"h7bdVq0597D0JfASIvo/ksyHsTyf/JRVH6M0Gv0A/RvFJnVRt1EitamD8i2mX2H3\n" +
|
||||||
|
"yC2lP2t1WzTafT7GzkYMAAoJEFQtyfb8rq1jhRABAIb/GkyCOlU02zfDMd5UHQ4J\n" +
|
||||||
|
"EpexaSodCvrGcQMA5t2nAPsEPXQOl1AOdJoc/sICsVAi4DvxohelpWJ19ZUy7WYQ\n" +
|
||||||
|
"CZxdBGhs7vgSCisGAQQBl1UBBQEBB0BeCegzdBr3B6+q3IBjkzNXPfLopNi2d+sL\n" +
|
||||||
|
"9hcbV9ztDgMBCAcAAP9hFCttDV8qWyven96rQ0WKGfVo1bKp2EZHGUR7tIScWA9P\n" +
|
||||||
|
"wnUEGBYKAB0Fgmhs7vgCngECmwwFFgIDAQAECwkIBwUVCgkICwAKCRBULcn2/K6t\n" +
|
||||||
|
"Y7GuAP9Kf1Ec1GJmZ99UHsgiN60os+6adMLj4G2ASiIbNSDvKgD9F/VLFIb/eN7k\n" +
|
||||||
|
"JQp3E5C15x5pMMKEI/rjwdrKmYH3aAw=\n" +
|
||||||
|
"=hnEg\n" +
|
||||||
|
"-----END PGP PRIVATE KEY BLOCK-----";
|
||||||
|
private final String cert = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||||
|
"Comment: D7BC FF6B B105 40D9 87F9 CB6E 542D C9F6 FCAE AD63\n" +
|
||||||
|
"Comment: Alice <alice@pgpainless.org>\n" +
|
||||||
|
"\n" +
|
||||||
|
"mDMEaGzu+BYJKwYBBAHaRw8BAQdAlqjB241N44drAJvxa3wx0uRb5bxuVNXrCwPZ\n" +
|
||||||
|
"yf4Qg+O0HEFsaWNlIDxhbGljZUBwZ3BhaW5sZXNzLm9yZz7ClQQTFgoARwWCaGzu\n" +
|
||||||
|
"+AkQVC3J9vyurWMWIQTXvP9rsQVA2Yf5y25ULcn2/K6tYwKeAQKbAQUWAgMBAAQL\n" +
|
||||||
|
"CQgHBRUKCQgLBYkJZgF/ApkBAADVIwEAi599IgoqQbvetYicOt9XobSQKH+4/tB/\n" +
|
||||||
|
"cmHgD7HkGu8A/jYoA0CaYuYNWw8ZYQ8QCUIAkXApm8fO9iyTx0QU1kQMuDMEaGzu\n" +
|
||||||
|
"+BYJKwYBBAHaRw8BAQdA48KEYPTPnV86ycWzAk82aHPF2Fke5cLFsQn7/laFT1DC\n" +
|
||||||
|
"wBUEGBYKAH0Fgmhs7vgCngECmwIFFgIDAQAECwkIBwUVCgkIC18gBBkWCgAGBYJo\n" +
|
||||||
|
"bO74AAoJECL1fW9vQUTUldQBALcsF4e23VatOfew9CXwEiL6P5LMh7E8n/yUVR+j\n" +
|
||||||
|
"NBr9AP0bxSZ1UbdRIrWpg/Itpl9h98gtpT9rdVs02n0+xs5GDAAKCRBULcn2/K6t\n" +
|
||||||
|
"Y4UQAQCG/xpMgjpVNNs3wzHeVB0OCRKXsWkqHQr6xnEDAObdpwD7BD10DpdQDnSa\n" +
|
||||||
|
"HP7CArFQIuA78aIXpaVidfWVMu1mEAm4OARobO74EgorBgEEAZdVAQUBAQdAXgno\n" +
|
||||||
|
"M3Qa9wevqtyAY5MzVz3y6KTYtnfrC/YXG1fc7Q4DAQgHwnUEGBYKAB0Fgmhs7vgC\n" +
|
||||||
|
"ngECmwwFFgIDAQAECwkIBwUVCgkICwAKCRBULcn2/K6tY7GuAP9Kf1Ec1GJmZ99U\n" +
|
||||||
|
"HsgiN60os+6adMLj4G2ASiIbNSDvKgD9F/VLFIb/eN7kJQp3E5C15x5pMMKEI/rj\n" +
|
||||||
|
"wdrKmYH3aAw=\n" +
|
||||||
|
"=4uX6\n" +
|
||||||
|
"-----END PGP PUBLIC KEY BLOCK-----";
|
||||||
|
|
||||||
|
@FuzzTest(
|
||||||
|
maxDuration = "60s"
|
||||||
|
)
|
||||||
|
public void verifyFuzzedSig(FuzzedDataProvider provider) throws IOException {
|
||||||
|
byte[] sig = provider.consumeBytes(1024);
|
||||||
|
if (sig.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<Verification> verifs = sop.verify()
|
||||||
|
.cert(cert.getBytes(StandardCharsets.UTF_8))
|
||||||
|
.signatures(sig)
|
||||||
|
.data(data);
|
||||||
|
|
||||||
|
if (verifs.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Verification v : verifs) {
|
||||||
|
System.out.println(v.toString());
|
||||||
|
}
|
||||||
|
} catch (SOPGPException.NoSignature e) {
|
||||||
|
// ignore
|
||||||
|
} catch (SOPGPException.BadData e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
xjsFwxylML8M9MlS
|
|
@ -0,0 +1 @@
|
||||||
|
xjx
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
00000000000000000000000000000000000000000000000000000000000000
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧#
|
|
@ -0,0 +1,7 @@
|
||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
wnUEABYKACcFgmhs7vgJECL1fW9vQUTUFiEELgSiuyj9W99u41BmIvV9b29BRNQA
|
||||||
|
ALkiAQDRulwayys9tufqrCg+AGCTyBp0SZT9PBOiCk2iZSb4zgEAvc3R88D3LI0C
|
||||||
|
kmchJW/WW7JGsmrwO4EZIBu1alzkggk=
|
||||||
|
=w4js
|
||||||
|
-----END PGP SIGNATURE-----
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue