From ec3d22bf1e307c90923f8c7795e69d9b0fcfaf9b Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Wed, 23 Jul 2025 11:25:12 +0200 Subject: [PATCH] Add fuzzer test for generate-key for testing fuzzed passphrases and user-ids --- .../sop/fuzzing/GenerateKeyFuzzTest.java | 67 +++++++++++++++++++ ...h-ab461f6b8a6842a473257a2561c1fbdf91bdfe77 | 0 ...h-e15f6d2aaf7124b3412b4ba69928aa087a2c37f3 | 2 + ...h-1a5db5bb461c354c040c6aff91bbf119661b19e8 | 1 + ...h-5088fe58b92db5e48f739e69e327d0b502f76d1a | 1 + ...h-6ef3f0fcd6325e34a205ca8e9f8ed2a648072776 | 1 + ...h-74ee2de3da27436407d779d58cc9256be185fede | 2 + ...h-a1a7715c7596c77b892dc6d4debb7c108ca4ef97 | 1 + ...h-ec9f11fde2456714178aecb8b78f181216a8150f | 3 + 9 files changed, 78 insertions(+) create mode 100644 pgpainless-sop/src/test/java/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTest.java create mode 100644 pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedPassphrase/crash-ab461f6b8a6842a473257a2561c1fbdf91bdfe77 create mode 100644 pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedPassphrase/crash-e15f6d2aaf7124b3412b4ba69928aa087a2c37f3 create mode 100644 pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-1a5db5bb461c354c040c6aff91bbf119661b19e8 create mode 100644 pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-5088fe58b92db5e48f739e69e327d0b502f76d1a create mode 100644 pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-6ef3f0fcd6325e34a205ca8e9f8ed2a648072776 create mode 100644 pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-74ee2de3da27436407d779d58cc9256be185fede create mode 100644 pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-a1a7715c7596c77b892dc6d4debb7c108ca4ef97 create mode 100644 pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-ec9f11fde2456714178aecb8b78f181216a8150f diff --git a/pgpainless-sop/src/test/java/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTest.java b/pgpainless-sop/src/test/java/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTest.java new file mode 100644 index 00000000..d90abb1c --- /dev/null +++ b/pgpainless-sop/src/test/java/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTest.java @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: 2025 Paul Schaub +// +// 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.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.api.KeyPassphraseProvider; +import org.bouncycastle.openpgp.api.OpenPGPKey; +import org.bouncycastle.openpgp.api.OpenPGPKeyReader; +import org.bouncycastle.openpgp.api.exception.KeyPassphraseException; +import org.bouncycastle.util.encoders.Hex; +import org.junit.jupiter.api.Test; +import org.pgpainless.sop.SOPImpl; +import sop.SOP; +import sop.exception.SOPGPException; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class GenerateKeyFuzzTest { + + private final SOP sop = new SOPImpl(); + + @FuzzTest(maxDuration = "5m") + public void generateKeyWithFuzzedUserId(FuzzedDataProvider provider) throws IOException { + String userId = provider.consumeRemainingAsString(); + + try { + byte[] keyBytes = sop.generateKey() + .userId(userId) + .generate() + .getBytes(); + + OpenPGPKey key = new OpenPGPKeyReader().parseKey(keyBytes); + assertNotNull(key.getUserId(userId), "Cannot fetch user-id for '" + userId + "' (" + Hex.toHexString(userId.getBytes(StandardCharsets.UTF_8)) + ")\n" + new String(keyBytes)); + } catch (IllegalArgumentException e) { + // expected. + } + } + + @FuzzTest + public void generateKeyWithFuzzedPassphrase(FuzzedDataProvider provider) throws IOException, KeyPassphraseException { + byte[] passphrase = provider.consumeRemainingAsBytes(); + + try { + byte[] keyBytes = sop.generateKey() + .withKeyPassword(passphrase) + .generate() + .getBytes(); + + OpenPGPKey key = new OpenPGPKeyReader().parseKey(keyBytes); + OpenPGPKey.OpenPGPPrivateKey pk = key.getPrimarySecretKey().unlock(new String(passphrase).toCharArray()); + assertNotNull(pk, "Got null result unlocking key that was generated with passphrase 0x'" + Hex.toHexString(passphrase) + "'"); + } + catch (SOPGPException.PasswordNotHumanReadable e) { + // expected. + } + catch (PGPException e) { + throw new RuntimeException("Cannot unlock key that was generated with passphrase 0x'" + Hex.toHexString(passphrase) + "'", e); + } + } +} diff --git a/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedPassphrase/crash-ab461f6b8a6842a473257a2561c1fbdf91bdfe77 b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedPassphrase/crash-ab461f6b8a6842a473257a2561c1fbdf91bdfe77 new file mode 100644 index 00000000..e69de29b diff --git a/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedPassphrase/crash-e15f6d2aaf7124b3412b4ba69928aa087a2c37f3 b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedPassphrase/crash-e15f6d2aaf7124b3412b4ba69928aa087a2c37f3 new file mode 100644 index 00000000..45518ca5 --- /dev/null +++ b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedPassphrase/crash-e15f6d2aaf7124b3412b4ba69928aa087a2c37f3 @@ -0,0 +1,2 @@ + +/ \ No newline at end of file diff --git a/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-1a5db5bb461c354c040c6aff91bbf119661b19e8 b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-1a5db5bb461c354c040c6aff91bbf119661b19e8 new file mode 100644 index 00000000..e6b455b2 --- /dev/null +++ b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-1a5db5bb461c354c040c6aff91bbf119661b19e8 @@ -0,0 +1 @@ +] M \ No newline at end of file diff --git a/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-5088fe58b92db5e48f739e69e327d0b502f76d1a b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-5088fe58b92db5e48f739e69e327d0b502f76d1a new file mode 100644 index 00000000..5b487190 --- /dev/null +++ b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-5088fe58b92db5e48f739e69e327d0b502f76d1a @@ -0,0 +1 @@ +  ¡  \ No newline at end of file diff --git a/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-6ef3f0fcd6325e34a205ca8e9f8ed2a648072776 b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-6ef3f0fcd6325e34a205ca8e9f8ed2a648072776 new file mode 100644 index 00000000..2b36e1be --- /dev/null +++ b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-6ef3f0fcd6325e34a205ca8e9f8ed2a648072776 @@ -0,0 +1 @@ +   \ No newline at end of file diff --git a/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-74ee2de3da27436407d779d58cc9256be185fede b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-74ee2de3da27436407d779d58cc9256be185fede new file mode 100644 index 00000000..4edaa423 --- /dev/null +++ b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-74ee2de3da27436407d779d58cc9256be185fede @@ -0,0 +1,2 @@ + +] \ No newline at end of file diff --git a/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-a1a7715c7596c77b892dc6d4debb7c108ca4ef97 b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-a1a7715c7596c77b892dc6d4debb7c108ca4ef97 new file mode 100644 index 00000000..39583112 --- /dev/null +++ b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-a1a7715c7596c77b892dc6d4debb7c108ca4ef97 @@ -0,0 +1 @@ +ù \ No newline at end of file diff --git a/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-ec9f11fde2456714178aecb8b78f181216a8150f b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-ec9f11fde2456714178aecb8b78f181216a8150f new file mode 100644 index 00000000..6d51bd5d --- /dev/null +++ b/pgpainless-sop/src/test/resources/org/pgpainless/sop/fuzzing/GenerateKeyFuzzTestInputs/generateKeyWithFuzzedUserId/crash-ec9f11fde2456714178aecb8b78f181216a8150f @@ -0,0 +1,3 @@ + +] +] \ No newline at end of file