pgpainless/pgpainless-core/src/test/java/org/pgpainless/signature/CertificateValidatorTest.java

1399 lines
100 KiB
Java

// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.signature;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.pgpainless.PGPainless;
import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.exception.SignatureValidationException;
import org.pgpainless.policy.Policy;
import org.pgpainless.signature.consumer.CertificateValidator;
import org.pgpainless.util.TestAllImplementations;
public class CertificateValidatorTest {
/**
* Primary Key signs and is hard revoked with reason: unknown.
*
* @see <a href="https://tests.sequoia-pgp.org/#Key_revocation_test__primary_key_signs_and_is_revoked__revoked__unknown">Sequoia Test Suite</a>
*/
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testPrimaryKeySignsAndIsHardRevokedUnknown() throws IOException, PGPException {
String key = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"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\n" +
"Y87zSryajDMFXQS0exdvhN4AXDlPlB3Rrkj7CQ==\n" +
"=MhJL\n" +
"-----END PGP ARMORED FILE-----\n";
String sigPredatesPrimaryKey = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJYaEaAACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7ttqgf9Gp4T5Q19cNL9Eyz1nlw11HDHT1wxfGHU5li76y7oo4Jqim15sEPDJWmc\n" +
"IpYVrczpCI95aCuaE6yfzpjZlXMzftwex3DjM98vyZH4W9teKcOnpAVjn3dLoQJA\n" +
"i4fiq3VaLgl+1OYOwu3DmwGKJZubHM3oPia9pbuyvL5Scvx+QCG0AVnssnt2QswG\n" +
"uU6J35QgBdjG2iC043sUoyxTSk929iamdQnOGchjcaATb4E4+HvtkRy4IirKxiKK\n" +
"c535BHJRLgWQzUcDDZ5kHf3SPLTNsigFFEwUyf5voFcn/DSMWSzPaVecaafTVJW2\n" +
"u8G1R5mjuxDRup8p//X1BSk1FpSmvw==\n" +
"=3/dv\n" +
"-----END PGP ARMORED FILE-----\n";
String sigSubkeyNotBound = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJa564AACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7ufRgf/QOsaJZgQaQ5daQrfBItOEcW+5acgY1TCwMVmc/nzBqC32TOvMaM3dypf\n" +
"wJbqzxHQIes+ivKDF872VWlMA2BErifpdsogbS0pdik/qU+AjMhr188xKpZKG/IY\n" +
"6BtuUPeSpsimx3UeEN3kt79fMtewBo0EXo3ujCyPpIF/9Vpd7L9jlJSvRBuM0/aR\n" +
"gbRsclEw4JZ98B3t7F3rLmx+F57Zre0ctzT4tHE6IaCYpEClr6Tepj/UxExYOt2l\n" +
"hKgVN8Wsuug7XYdOFmxqrV967m3CTnF8AspmxwgKK6NXjVLplfqij7Rp2URPWrWn\n" +
"Pp3CQRGUWJdMeMY9P1MpFq6XiXtftw==\n" +
"=Ld1q\n" +
"-----END PGP ARMORED FILE-----\n";
String sigPrimaryKeyRevoked = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJdP4iAACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7sYXQf8CZw6Kx4oyI8ZJ2c9RjVZmUFEirAoXH7oYA+Ye+wSAY9OtqE/x2SOYaC6\n" +
"QHiB93/wkvpqCVkLy2lenzpD7WXLbuFZ+/5jXp1o+sVHXfLSWo6pfIhOjj9FSr8x\n" +
"qqlqUfKwkbA6WYgju+qKC35SYdSptix7unaFkO41UdsM8wGQh880HSRMBMFPzg07\n" +
"3hMNYXoEJjFlIkxJSMu2WL7N0Q/4xE2iJftsQjUYAtJ/C/YK2I6dhW+CZremnv5R\n" +
"/8W+oH5Q63lYU8YL4wYnJQvkHjKs/kjLpoPmqL8kdHjndSpU+KOYr5w61XuEp2hp\n" +
"r8trtljVaVIQX2rYawSlqKkWXt0yag==\n" +
"=xVd8\n" +
"-----END PGP ARMORED FILE-----\n";
String sigPrimaryKeyRevalidated = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJe/cFVACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7vmhQf/UB456IXc8ub8HTExab1d5KqOGSUWpwIznTu8Wk8YuzWKEE8ZeZvPmv8K\n" +
"iJfBoOx59YrlOfpLAKcTR9Ql+IFbWsIkqPxX7U1SGldhfQm7iaK5Dn6+mmQFOz/s\n" +
"ZCIavWJ7opsp11JmQAt4FFojv789YswaS7VI1zjDj7EeRiATtzna/GqCYgeCM0cc\n" +
"sIe/1j1H2oh9YvYIpPMSGDJPo7T1Ji4Ie3iEQEYNYPuw1Hb7gWYncHXZGJq1nDf/\n" +
"WAoI9gSFagpsPW0k9cfEAOVNLNYSyi0CSnQWSjq8THbHKiLPFwsP3hvT2oHycWbK\n" +
"u5SfXaTsbMeVQJNdjCNsHq2bOXPGLw==\n" +
"=2BW4\n" +
"-----END PGP ARMORED FILE-----\n";
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(key);
PGPSignature predatesPrimaryKey = SignatureUtils.readSignatures(sigPredatesPrimaryKey).get(0);
PGPSignature unboundSubkey = SignatureUtils.readSignatures(sigSubkeyNotBound).get(0);
PGPSignature primaryKeyRevoked = SignatureUtils.readSignatures(sigPrimaryKeyRevoked).get(0);
PGPSignature primaryKeyRevalidated = SignatureUtils.readSignatures(sigPrimaryKeyRevalidated).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello, World";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
unboundSubkey, getSignedData(data), publicKeys, policy, validationDate),
"Primary key hard revoked");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
primaryKeyRevoked, getSignedData(data), publicKeys, policy, validationDate),
"Primary key hard revoked");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
primaryKeyRevalidated, getSignedData(data), publicKeys, policy, validationDate),
"Primary key hard revoked");
}
/**
* Subkey signs, primary key is hard revoked with reason: unknown.
* @see <a href="https://tests.sequoia-pgp.org/#Key_revocation_test__subkey_signs__primary_key_is_revoked__revoked__unknown">Sequoia Test Suite</a>
*/
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testSubkeySignsPrimaryKeyIsHardRevokedUnknown() throws IOException, PGPException {
String key = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"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\n" +
"Y87zSryajDMFXQS0exdvhN4AXDlPlB3Rrkj7CQ==\n" +
"=MhJL\n" +
"-----END PGP ARMORED FILE-----\n";
String sigPredatesPrimaryKey = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJYaEaAACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmVtqgf/YSG+b8lY01/4oCrHoNMECDDbpI5+8WkeT0CcdlEd5TGj3AHesT6H6XmL\n" +
"ZxaHHOwtkuDh0bIAiYGl36e4ult5XZQhFIwUXGde6myLE+fpCGsBJwNu+TDIrbg3\n" +
"PGqnVZNlcU+2sP5JhJfAn8VtLENuHkbIC3+kH8xBIrkPTc0rbNBgyzX5eFO20U0D\n" +
"bHCCjfjVDpZ8l7N2NlsRYvU0kTzN5GvwbS1HnMOovF9ZKkEpzxxw6IRJIapaE2L9\n" +
"adMKIRAqrIIjfj6Z9nETd1nZE79t1zSw1trfArPaJQr46krgh1ocLQoD/c+PhB9l\n" +
"sRxQBnWERgQaDJByq0kwKSnwWAsyxw==\n" +
"=SDmD\n" +
"-----END PGP ARMORED FILE-----\n";
String sigSigningKeyUnbound = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJa564AACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmWfRgf9ECjIviU1pN0GiMZGci3Vce2b42LIqH0JZApOeRDpcyXgxi3/CmdaewpT\n" +
"w9l18gsXhioRg4xUzMFrYSgyYZ9VajFggMjbeX5dSV3rsOSJSiEEyDbeGi0TcA/Y\n" +
"GUifX4EfKx5X5nI/wevnYjmruDp9SqaPLHIZK1soOoPzueZ8wKyJ9A4vVG4bvxVX\n" +
"FnwBf6mRE/0Z8IoHlRJdq0fSzW4RgX8KAtK8SfyGOnk7LDaevVuL6iE5v0Gsu0oh\n" +
"cHlI6Llm97EVxP93KZ1J7TQIi/a6PUJb5XCIw0K/iyuNuAzETgm8LVJyn6UwL4ym\n" +
"KcNieOK8Qcoivq0kCYuv/0Tbk13jVQ==\n" +
"=5hOz\n" +
"-----END PGP ARMORED FILE-----";
String sigSubkeyRevoked = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJdP4iAACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmUYXQf/dGNZay40bZEpcnxYl+Kq+gRQESeDhg/xOfGfSCLQncMH+UYPaUKANC2g\n" +
"CfMNN1wd8ZWrvgyTVo3TVfK1P1RYa9nrvKoKN3bjsFcY6V7VciPW58xVNsuxsEEC\n" +
"GEH96TQy+FsP680tRnzQ3Dbw/JT6o6Xi+HLf4JVFceapBgyth61E5gN5w3azxVFr\n" +
"GfwIfHvepOjCIq9tRZsRFEBp3XVZ/AF+zQMG5nfIVSm1kVtZjb7KXc3Bj48DVrmb\n" +
"XLxPJz7PLY0cgOsXXxROIdtFT+mbVQg2j247hxnhItwtLeQrafb5T8ibeihRlkhK\n" +
"1tfKv31EP8tAVqgTjw+qD32bH9h77w==\n" +
"=MOaJ\n" +
"-----END PGP ARMORED FILE-----\n";
String sigSubkeyRevalidated = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJe/cFVACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmXmhQf+LjM2vmdKYnxfVy40Vcdoy2Jov/ZD2RSMFff+fIoCXmWfEetila7v5xHj\n" +
"ZXq6aevTEN1vgW3T6Q1OjFhnGpMl9wvya9mszfn5BBKukFtLkHeay0PtYuUcrfJC\n" +
"UIQCx9PFZzgRJFyGsCqrXBc1VIe2DV3d8dq74unTeCEmWdvAZKdjoUYzRohMtcZ+\n" +
"0QctCCJE1kRFJuH/TIdxxwKPtBZfOolSlpS0Z5xxa2sILqUvQ2Dq3hBctUM4g6hB\n" +
"Y8uafI8qIMwWl4DQDzPpQ917d6J+GCdN0Aib6ZOsvmgR5wrBOFiDpRJ/W9W6+rgs\n" +
"I5V/t2y6h6gaHbanggc0cMOaMTtEKQ==\n" +
"=lkHs\n" +
"-----END PGP ARMORED FILE-----\n";
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(key);
PGPSignature predatesPrimaryKey = SignatureUtils.readSignatures(sigPredatesPrimaryKey).get(0);
PGPSignature unboundSubkey = SignatureUtils.readSignatures(sigSigningKeyUnbound).get(0);
PGPSignature revokedSubkey = SignatureUtils.readSignatures(sigSubkeyRevoked).get(0);
PGPSignature revalidatedSubkey = SignatureUtils.readSignatures(sigSubkeyRevalidated).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello, World";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
unboundSubkey, getSignedData(data), publicKeys, policy, validationDate),
"Signing key unbound + hard revocation");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
revokedSubkey, getSignedData(data), publicKeys, policy, validationDate),
"Primary key is hard revoked");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
revalidatedSubkey, getSignedData(data), publicKeys, policy, validationDate),
"Primary key is hard revoked");
}
/**
* Subkey signs and is hard revoked with reason: unknown.
*
* @see <a href="https://tests.sequoia-pgp.org/#Key_revocation_test__subkey_signs__subkey_is_revoked__revoked__unknown">Sequoia Test Suite</a>
*/
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testSubkeySignsAndIsHardRevokedUnknown() throws IOException, PGPException {
String keyWithHardRev = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"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\n" +
"Y87zSryajDMFXQS0exdvhN4AXDlPlB3Rrkj7CQ==\n" +
"=yTKS\n" +
"-----END PGP ARMORED FILE-----\n";
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(keyWithHardRev);
String sigPredatesPrimaryKey = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJYaEaAACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmVtqgf/YSG+b8lY01/4oCrHoNMECDDbpI5+8WkeT0CcdlEd5TGj3AHesT6H6XmL\n" +
"ZxaHHOwtkuDh0bIAiYGl36e4ult5XZQhFIwUXGde6myLE+fpCGsBJwNu+TDIrbg3\n" +
"PGqnVZNlcU+2sP5JhJfAn8VtLENuHkbIC3+kH8xBIrkPTc0rbNBgyzX5eFO20U0D\n" +
"bHCCjfjVDpZ8l7N2NlsRYvU0kTzN5GvwbS1HnMOovF9ZKkEpzxxw6IRJIapaE2L9\n" +
"adMKIRAqrIIjfj6Z9nETd1nZE79t1zSw1trfArPaJQr46krgh1ocLQoD/c+PhB9l\n" +
"sRxQBnWERgQaDJByq0kwKSnwWAsyxw==\n" +
"=SDmD\n" +
"-----END PGP ARMORED FILE-----\n";
String sigUnboundBeforeHardRevocation = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJa564AACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmWfRgf9ECjIviU1pN0GiMZGci3Vce2b42LIqH0JZApOeRDpcyXgxi3/CmdaewpT\n" +
"w9l18gsXhioRg4xUzMFrYSgyYZ9VajFggMjbeX5dSV3rsOSJSiEEyDbeGi0TcA/Y\n" +
"GUifX4EfKx5X5nI/wevnYjmruDp9SqaPLHIZK1soOoPzueZ8wKyJ9A4vVG4bvxVX\n" +
"FnwBf6mRE/0Z8IoHlRJdq0fSzW4RgX8KAtK8SfyGOnk7LDaevVuL6iE5v0Gsu0oh\n" +
"cHlI6Llm97EVxP93KZ1J7TQIi/a6PUJb5XCIw0K/iyuNuAzETgm8LVJyn6UwL4ym\n" +
"KcNieOK8Qcoivq0kCYuv/0Tbk13jVQ==\n" +
"=5hOz\n" +
"-----END PGP ARMORED FILE-----\n";
String sigAfterHardRevocation = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJdP4iAACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmUYXQf/dGNZay40bZEpcnxYl+Kq+gRQESeDhg/xOfGfSCLQncMH+UYPaUKANC2g\n" +
"CfMNN1wd8ZWrvgyTVo3TVfK1P1RYa9nrvKoKN3bjsFcY6V7VciPW58xVNsuxsEEC\n" +
"GEH96TQy+FsP680tRnzQ3Dbw/JT6o6Xi+HLf4JVFceapBgyth61E5gN5w3azxVFr\n" +
"GfwIfHvepOjCIq9tRZsRFEBp3XVZ/AF+zQMG5nfIVSm1kVtZjb7KXc3Bj48DVrmb\n" +
"XLxPJz7PLY0cgOsXXxROIdtFT+mbVQg2j247hxnhItwtLeQrafb5T8ibeihRlkhK\n" +
"1tfKv31EP8tAVqgTjw+qD32bH9h77w==\n" +
"=MOaJ\n" +
"-----END PGP ARMORED FILE-----\n";
String sigAfterRevalidation = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJe/cFVACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmXmhQf+LjM2vmdKYnxfVy40Vcdoy2Jov/ZD2RSMFff+fIoCXmWfEetila7v5xHj\n" +
"ZXq6aevTEN1vgW3T6Q1OjFhnGpMl9wvya9mszfn5BBKukFtLkHeay0PtYuUcrfJC\n" +
"UIQCx9PFZzgRJFyGsCqrXBc1VIe2DV3d8dq74unTeCEmWdvAZKdjoUYzRohMtcZ+\n" +
"0QctCCJE1kRFJuH/TIdxxwKPtBZfOolSlpS0Z5xxa2sILqUvQ2Dq3hBctUM4g6hB\n" +
"Y8uafI8qIMwWl4DQDzPpQ917d6J+GCdN0Aib6ZOsvmgR5wrBOFiDpRJ/W9W6+rgs\n" +
"I5V/t2y6h6gaHbanggc0cMOaMTtEKQ==\n" +
"=lkHs\n" +
"-----END PGP ARMORED FILE-----\n";
PGPSignature predatesPrimaryKey = SignatureUtils.readSignatures(sigPredatesPrimaryKey).get(0);
PGPSignature unboundKey = SignatureUtils.readSignatures(sigUnboundBeforeHardRevocation).get(0);
PGPSignature afterHardRevocation = SignatureUtils.readSignatures(sigAfterHardRevocation).get(0);
PGPSignature afterRevalidation = SignatureUtils.readSignatures(sigAfterRevalidation).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello World :)";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
unboundKey, getSignedData(data), publicKeys, policy, validationDate),
"Signing key unbound + hard revocation");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
afterHardRevocation, getSignedData(data), publicKeys, policy, validationDate),
"Hard revocation invalidates key at all times");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
afterRevalidation, getSignedData(data), publicKeys, policy, validationDate),
"Hard revocation invalidates key at all times");
}
/**
* Primary Key signs and is soft revoked with reason: superseded.
*
* @see <a href="https://tests.sequoia-pgp.org/#Key_revocation_test__primary_key_signs_and_is_revoked__revoked__superseded">Sequoia Test Suite</a>
*/
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testPrimaryKeySignsAndIsSoftRevokedSuperseded() throws IOException, PGPException {
String keyWithSoftRev = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"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\n" +
"exdvhN4AXDlPlB3Rrkj7CQ==\n" +
"=qQpG\n" +
"-----END PGP ARMORED FILE-----\n";
String sigPredatesPrimaryKey = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJYaEaAACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7ttqgf9Gp4T5Q19cNL9Eyz1nlw11HDHT1wxfGHU5li76y7oo4Jqim15sEPDJWmc\n" +
"IpYVrczpCI95aCuaE6yfzpjZlXMzftwex3DjM98vyZH4W9teKcOnpAVjn3dLoQJA\n" +
"i4fiq3VaLgl+1OYOwu3DmwGKJZubHM3oPia9pbuyvL5Scvx+QCG0AVnssnt2QswG\n" +
"uU6J35QgBdjG2iC043sUoyxTSk929iamdQnOGchjcaATb4E4+HvtkRy4IirKxiKK\n" +
"c535BHJRLgWQzUcDDZ5kHf3SPLTNsigFFEwUyf5voFcn/DSMWSzPaVecaafTVJW2\n" +
"u8G1R5mjuxDRup8p//X1BSk1FpSmvw==\n" +
"=3/dv\n" +
"-----END PGP ARMORED FILE-----\n";
String sigKeyIsValid = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJa564AACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7ufRgf/QOsaJZgQaQ5daQrfBItOEcW+5acgY1TCwMVmc/nzBqC32TOvMaM3dypf\n" +
"wJbqzxHQIes+ivKDF872VWlMA2BErifpdsogbS0pdik/qU+AjMhr188xKpZKG/IY\n" +
"6BtuUPeSpsimx3UeEN3kt79fMtewBo0EXo3ujCyPpIF/9Vpd7L9jlJSvRBuM0/aR\n" +
"gbRsclEw4JZ98B3t7F3rLmx+F57Zre0ctzT4tHE6IaCYpEClr6Tepj/UxExYOt2l\n" +
"hKgVN8Wsuug7XYdOFmxqrV967m3CTnF8AspmxwgKK6NXjVLplfqij7Rp2URPWrWn\n" +
"Pp3CQRGUWJdMeMY9P1MpFq6XiXtftw==\n" +
"=Ld1q\n" +
"-----END PGP ARMORED FILE-----\n";
String sigKeyIsRevoked = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJdP4iAACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7sYXQf8CZw6Kx4oyI8ZJ2c9RjVZmUFEirAoXH7oYA+Ye+wSAY9OtqE/x2SOYaC6\n" +
"QHiB93/wkvpqCVkLy2lenzpD7WXLbuFZ+/5jXp1o+sVHXfLSWo6pfIhOjj9FSr8x\n" +
"qqlqUfKwkbA6WYgju+qKC35SYdSptix7unaFkO41UdsM8wGQh880HSRMBMFPzg07\n" +
"3hMNYXoEJjFlIkxJSMu2WL7N0Q/4xE2iJftsQjUYAtJ/C/YK2I6dhW+CZremnv5R\n" +
"/8W+oH5Q63lYU8YL4wYnJQvkHjKs/kjLpoPmqL8kdHjndSpU+KOYr5w61XuEp2hp\n" +
"r8trtljVaVIQX2rYawSlqKkWXt0yag==\n" +
"=xVd8\n" +
"-----END PGP ARMORED FILE-----\n";
String sigKeyIsRevalidated = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJe/cFVACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7vmhQf/UB456IXc8ub8HTExab1d5KqOGSUWpwIznTu8Wk8YuzWKEE8ZeZvPmv8K\n" +
"iJfBoOx59YrlOfpLAKcTR9Ql+IFbWsIkqPxX7U1SGldhfQm7iaK5Dn6+mmQFOz/s\n" +
"ZCIavWJ7opsp11JmQAt4FFojv789YswaS7VI1zjDj7EeRiATtzna/GqCYgeCM0cc\n" +
"sIe/1j1H2oh9YvYIpPMSGDJPo7T1Ji4Ie3iEQEYNYPuw1Hb7gWYncHXZGJq1nDf/\n" +
"WAoI9gSFagpsPW0k9cfEAOVNLNYSyi0CSnQWSjq8THbHKiLPFwsP3hvT2oHycWbK\n" +
"u5SfXaTsbMeVQJNdjCNsHq2bOXPGLw==\n" +
"=2BW4\n" +
"-----END PGP ARMORED FILE-----\n";
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(keyWithSoftRev);
PGPSignature predatesPrimaryKey = SignatureUtils.readSignatures(sigPredatesPrimaryKey).get(0);
PGPSignature keyIsValid = SignatureUtils.readSignatures(sigKeyIsValid).get(0);
PGPSignature keyIsRevoked = SignatureUtils.readSignatures(sigKeyIsRevoked).get(0);
PGPSignature keyIsRevalidated = SignatureUtils.readSignatures(sigKeyIsRevalidated).get(0);
Policy policy = PGPainless.getPolicy();
String data = "Hello, World";
// Sig not valid, as it predates the signing key creation time
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, predatesPrimaryKey.getCreationTime()),
"Signature predates primary key creation date");
// Sig valid
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
keyIsValid, getSignedData(data), publicKeys, policy, keyIsValid.getCreationTime()),
"Signature is valid");
// Sig not valid, as the signing key is revoked
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
keyIsRevoked, getSignedData(data), publicKeys, policy, keyIsRevoked.getCreationTime()),
"Signing key is revoked at this point");
// Sig valid, as the signing key is revalidated
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
keyIsRevalidated, getSignedData(data), publicKeys, policy, keyIsRevalidated.getCreationTime()),
"Signature is valid, as signing key is revalidated");
}
/**
* Subkey signs, primary key is soft revoked with reason: superseded.
*
* @see <a href="https://tests.sequoia-pgp.org/#Key_revocation_test__subkey_signs__primary_key_is_revoked__revoked__superseded">Sequoia Test Suite</a>
*/
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testSubkeySignsPrimaryKeyIsSoftRevokedSuperseded() throws IOException, PGPException {
String key = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"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\n" +
"exdvhN4AXDlPlB3Rrkj7CQ==\n" +
"=qQpG\n" +
"-----END PGP ARMORED FILE-----\n";
String sigPredatesPrimaryKey = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJYaEaAACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmVtqgf/YSG+b8lY01/4oCrHoNMECDDbpI5+8WkeT0CcdlEd5TGj3AHesT6H6XmL\n" +
"ZxaHHOwtkuDh0bIAiYGl36e4ult5XZQhFIwUXGde6myLE+fpCGsBJwNu+TDIrbg3\n" +
"PGqnVZNlcU+2sP5JhJfAn8VtLENuHkbIC3+kH8xBIrkPTc0rbNBgyzX5eFO20U0D\n" +
"bHCCjfjVDpZ8l7N2NlsRYvU0kTzN5GvwbS1HnMOovF9ZKkEpzxxw6IRJIapaE2L9\n" +
"adMKIRAqrIIjfj6Z9nETd1nZE79t1zSw1trfArPaJQr46krgh1ocLQoD/c+PhB9l\n" +
"sRxQBnWERgQaDJByq0kwKSnwWAsyxw==\n" +
"=SDmD\n" +
"-----END PGP ARMORED FILE-----\n";
String sigSubkeyNotBound = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJa564AACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmWfRgf9ECjIviU1pN0GiMZGci3Vce2b42LIqH0JZApOeRDpcyXgxi3/CmdaewpT\n" +
"w9l18gsXhioRg4xUzMFrYSgyYZ9VajFggMjbeX5dSV3rsOSJSiEEyDbeGi0TcA/Y\n" +
"GUifX4EfKx5X5nI/wevnYjmruDp9SqaPLHIZK1soOoPzueZ8wKyJ9A4vVG4bvxVX\n" +
"FnwBf6mRE/0Z8IoHlRJdq0fSzW4RgX8KAtK8SfyGOnk7LDaevVuL6iE5v0Gsu0oh\n" +
"cHlI6Llm97EVxP93KZ1J7TQIi/a6PUJb5XCIw0K/iyuNuAzETgm8LVJyn6UwL4ym\n" +
"KcNieOK8Qcoivq0kCYuv/0Tbk13jVQ==\n" +
"=5hOz\n" +
"-----END PGP ARMORED FILE-----\n";
String sigKeyRevoked = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJdP4iAACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmUYXQf/dGNZay40bZEpcnxYl+Kq+gRQESeDhg/xOfGfSCLQncMH+UYPaUKANC2g\n" +
"CfMNN1wd8ZWrvgyTVo3TVfK1P1RYa9nrvKoKN3bjsFcY6V7VciPW58xVNsuxsEEC\n" +
"GEH96TQy+FsP680tRnzQ3Dbw/JT6o6Xi+HLf4JVFceapBgyth61E5gN5w3azxVFr\n" +
"GfwIfHvepOjCIq9tRZsRFEBp3XVZ/AF+zQMG5nfIVSm1kVtZjb7KXc3Bj48DVrmb\n" +
"XLxPJz7PLY0cgOsXXxROIdtFT+mbVQg2j247hxnhItwtLeQrafb5T8ibeihRlkhK\n" +
"1tfKv31EP8tAVqgTjw+qD32bH9h77w==\n" +
"=MOaJ\n" +
"-----END PGP ARMORED FILE-----\n";
String sigKeyValid = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJe/cFVACEJEEpyNKOhITplFiEEUXksDkji/alOk7kRSnI0o6Eh\n" +
"OmXmhQf+LjM2vmdKYnxfVy40Vcdoy2Jov/ZD2RSMFff+fIoCXmWfEetila7v5xHj\n" +
"ZXq6aevTEN1vgW3T6Q1OjFhnGpMl9wvya9mszfn5BBKukFtLkHeay0PtYuUcrfJC\n" +
"UIQCx9PFZzgRJFyGsCqrXBc1VIe2DV3d8dq74unTeCEmWdvAZKdjoUYzRohMtcZ+\n" +
"0QctCCJE1kRFJuH/TIdxxwKPtBZfOolSlpS0Z5xxa2sILqUvQ2Dq3hBctUM4g6hB\n" +
"Y8uafI8qIMwWl4DQDzPpQ917d6J+GCdN0Aib6ZOsvmgR5wrBOFiDpRJ/W9W6+rgs\n" +
"I5V/t2y6h6gaHbanggc0cMOaMTtEKQ==\n" +
"=lkHs\n" +
"-----END PGP ARMORED FILE-----\n";
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(key);
PGPSignature predatesPrimaryKey = SignatureUtils.readSignatures(sigPredatesPrimaryKey).get(0);
PGPSignature keyNotBound = SignatureUtils.readSignatures(sigSubkeyNotBound).get(0);
PGPSignature keyRevoked = SignatureUtils.readSignatures(sigKeyRevoked).get(0);
PGPSignature valid = SignatureUtils.readSignatures(sigKeyValid).get(0);
Policy policy = PGPainless.getPolicy();
String data = "Hello, World";
Date validationDate = new Date();
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key creation date");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
keyNotBound, getSignedData(data), publicKeys, policy, validationDate),
"Signing key is not bound at this point");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
keyRevoked, getSignedData(data), publicKeys, policy, validationDate),
"Signing key is revoked at this point");
assertDoesNotThrow(() ->
CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
valid, getSignedData(data), publicKeys, policy, validationDate),
"Signing key is revalidated");
}
/**
* Primary key signs and is soft revoked with reason: retired.
*
* @see <a href="https://tests.sequoia-pgp.org/#Key_revocation_test__primary_key_signs_and_is_revoked__revoked__key_retired">Sequoia Test Suite</a>
*/
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testPrimaryKeySignsAndIsSoftRevokedRetired() throws IOException, PGPException {
String key = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"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\n" +
"=7j+m\n" +
"-----END PGP ARMORED FILE-----\n";
String sigPredatesPrimaryKey = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJYaEaAACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7ttqgf9Gp4T5Q19cNL9Eyz1nlw11HDHT1wxfGHU5li76y7oo4Jqim15sEPDJWmc\n" +
"IpYVrczpCI95aCuaE6yfzpjZlXMzftwex3DjM98vyZH4W9teKcOnpAVjn3dLoQJA\n" +
"i4fiq3VaLgl+1OYOwu3DmwGKJZubHM3oPia9pbuyvL5Scvx+QCG0AVnssnt2QswG\n" +
"uU6J35QgBdjG2iC043sUoyxTSk929iamdQnOGchjcaATb4E4+HvtkRy4IirKxiKK\n" +
"c535BHJRLgWQzUcDDZ5kHf3SPLTNsigFFEwUyf5voFcn/DSMWSzPaVecaafTVJW2\n" +
"u8G1R5mjuxDRup8p//X1BSk1FpSmvw==\n" +
"=3/dv\n" +
"-----END PGP ARMORED FILE-----\n";
String sigValid = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJa564AACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7ufRgf/QOsaJZgQaQ5daQrfBItOEcW+5acgY1TCwMVmc/nzBqC32TOvMaM3dypf\n" +
"wJbqzxHQIes+ivKDF872VWlMA2BErifpdsogbS0pdik/qU+AjMhr188xKpZKG/IY\n" +
"6BtuUPeSpsimx3UeEN3kt79fMtewBo0EXo3ujCyPpIF/9Vpd7L9jlJSvRBuM0/aR\n" +
"gbRsclEw4JZ98B3t7F3rLmx+F57Zre0ctzT4tHE6IaCYpEClr6Tepj/UxExYOt2l\n" +
"hKgVN8Wsuug7XYdOFmxqrV967m3CTnF8AspmxwgKK6NXjVLplfqij7Rp2URPWrWn\n" +
"Pp3CQRGUWJdMeMY9P1MpFq6XiXtftw==\n" +
"=Ld1q\n" +
"-----END PGP ARMORED FILE-----\n";
String sigRevoked = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJdP4iAACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7sYXQf8CZw6Kx4oyI8ZJ2c9RjVZmUFEirAoXH7oYA+Ye+wSAY9OtqE/x2SOYaC6\n" +
"QHiB93/wkvpqCVkLy2lenzpD7WXLbuFZ+/5jXp1o+sVHXfLSWo6pfIhOjj9FSr8x\n" +
"qqlqUfKwkbA6WYgju+qKC35SYdSptix7unaFkO41UdsM8wGQh880HSRMBMFPzg07\n" +
"3hMNYXoEJjFlIkxJSMu2WL7N0Q/4xE2iJftsQjUYAtJ/C/YK2I6dhW+CZremnv5R\n" +
"/8W+oH5Q63lYU8YL4wYnJQvkHjKs/kjLpoPmqL8kdHjndSpU+KOYr5w61XuEp2hp\n" +
"r8trtljVaVIQX2rYawSlqKkWXt0yag==\n" +
"=xVd8\n" +
"-----END PGP ARMORED FILE-----\n";
String sigReLegitimized = "-----BEGIN PGP ARMORED FILE-----\n" +
"Comment: ASCII Armor added by openpgp-interoperability-test-suite\n" +
"\n" +
"wsBzBAABCgAGBYJe/cFVACEJEGhPrWLcA4+7FiEE8tFQpP6Ykl1R6RU5aE+tYtwD\n" +
"j7vmhQf/UB456IXc8ub8HTExab1d5KqOGSUWpwIznTu8Wk8YuzWKEE8ZeZvPmv8K\n" +
"iJfBoOx59YrlOfpLAKcTR9Ql+IFbWsIkqPxX7U1SGldhfQm7iaK5Dn6+mmQFOz/s\n" +
"ZCIavWJ7opsp11JmQAt4FFojv789YswaS7VI1zjDj7EeRiATtzna/GqCYgeCM0cc\n" +
"sIe/1j1H2oh9YvYIpPMSGDJPo7T1Ji4Ie3iEQEYNYPuw1Hb7gWYncHXZGJq1nDf/\n" +
"WAoI9gSFagpsPW0k9cfEAOVNLNYSyi0CSnQWSjq8THbHKiLPFwsP3hvT2oHycWbK\n" +
"u5SfXaTsbMeVQJNdjCNsHq2bOXPGLw==\n" +
"=2BW4\n" +
"-----END PGP ARMORED FILE-----\n";
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(key);
PGPSignature predatesPrimaryKey = SignatureUtils.readSignatures(sigPredatesPrimaryKey).get(0);
PGPSignature valid = SignatureUtils.readSignatures(sigValid).get(0);
PGPSignature revoked = SignatureUtils.readSignatures(sigRevoked).get(0);
PGPSignature revalidated = SignatureUtils.readSignatures(sigReLegitimized).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello, World";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key creation date");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
valid, getSignedData(data), publicKeys, policy, validationDate),
"Signature is valid");
assertThrows(SignatureValidationException.class, () ->
CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
revoked, getSignedData(data), publicKeys, policy, validationDate),
"Primary key is revoked");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
revalidated, getSignedData(data), publicKeys, policy, validationDate),
"Primary key is re-legitimized");
}
/**
* Keys with temporary validity.
*
* @see <a href="https://tests.sequoia-pgp.org/#Temporary_validity">Sequoia Test Suite</a>
*/
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void testTemporaryValidity() throws IOException, PGPException {
String keyA = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"Comment: D1A6 6E1A 23B1 82C9 980F 788C FBFC C82A 015E 7330\n" +
"Comment: Bob Babbage <bob@openpgp.example>\n" +
"\n" +
"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\n" +
"=UNh9\n" +
"-----END PGP PUBLIC KEY BLOCK-----\n";
String keyB = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"Comment: D1A6 6E1A 23B1 82C9 980F 788C FBFC C82A 015E 7330\n" +
"Comment: Bob Babbage <bob@openpgp.example>\n" +
"\n" +
"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\n" +
"iz7OblW3I9Dt\n" +
"=qacX\n" +
"-----END PGP PUBLIC KEY BLOCK-----\n";
String keyC = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"Comment: D1A6 6E1A 23B1 82C9 980F 788C FBFC C82A 015E 7330\n" +
"Comment: Bob Babbage <bob@openpgp.example>\n" +
"\n" +
"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\n" +
"916X5bFdC0Rr\n" +
"=RTZe\n" +
"-----END PGP PUBLIC KEY BLOCK-----\n";
String keyASigT0 = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJdkyfyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmfAtB+VtWWsZc4DiK/QK7LEDG+KAl+ORwXnUahXErz3\n" +
"GhYhBNGmbhojsYLJmA94jPv8yCoBXnMwAABlEAv/fe0No+TMQTq5xkyv2xNgzibB\n" +
"sqeOBbmZL82PfGJTthEtZ+eKi0pNnGPlFH0VIkRskNRKEZqLGJh2d/xDstiPBTfc\n" +
"TzTn66f43h+WnGRqGLYbKHfrJ+Mn/wHub9zxauDvpjcIqOLYscuZ+rvp/OyExoST\n" +
"lOmfLsrpGgS//eMDchgeFTybZy3UP7dw+BHHSlMW/s4QvgqqS8v5x2bNgMcairzN\n" +
"BMxafx6Mp4RSk46tF+INzPgV8W+ImyGXtkZcBmiv9/u36X6GESSyHl/DVf+ZlHm9\n" +
"u35dGn8S2PhyE12eQnLZJoorqcIOtwx1sAD+317Dprv8fwcHBhgyKLVsx2O5NTWn\n" +
"fZNRtdjQiUBt03D4Qdxoru/UzpGZWq4OLLZVB7u2B4tRQohkBCH96s5hvY2GHXSN\n" +
"Md3FCvms+lCEFi70Ae1KZCpD1/DHCFQcT5fYMYVNU1HFB8eQoKMM3kmv0VpJ31CB\n" +
"bJ0esmX6JDukiepzcr09w7bbkhGvKnDgUM3dNxhv\n" +
"=PfHW\n" +
"-----END PGP SIGNATURE-----\n";
String keyASigT1_T2 = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJduBHyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmcglTWhGNT4tUfWuGHHpZUQZGDvZ4AKjIM/B97lFgac\n" +
"XBYhBNGmbhojsYLJmA94jPv8yCoBXnMwAADPmAv9EZlRAp65+JLsABQa8sk0YgRU\n" +
"28n6/Wcv2nj0iZMtbnXu2hLJqPj62JihCNbElEgJb7NIYbTPEAiyUisq8sa+E12F\n" +
"PvBsqcNAdLxlDRyPcwlDrbl0fRqLt/fiItMp6lHnfl2SfrSkzWv8t2DswPS+LXpt\n" +
"k5GBWxnJMRQ2Lf1L8rriFY1p6D9XtO8n9wGWMzCoxp3q+diQa8YJbhppPPskU5rT\n" +
"bPYH7f1FnU2OzzxgeqlAjtpjkTmzy3RNRlzGEYk6NnNbHQN0sQoiQdOaHMJ/qKMF\n" +
"wanYX2iatYCCYJGMDv3Ysw6nXLyiZ6dbqFEJwzRCiZQ2ZBYvzRyEnMojIZE3CXOv\n" +
"a+h5qm8Ffc+ZPc0spBoTxFCz8+Rmp5qNT9kFOIQUF9YOs/fo8sCr32ZbLu/bBsy9\n" +
"RhswX42fnAZ4DZJKlAORbtYmM52WsPxArGLnpOpgD8aT4Mt7SsVpAJXnjn43NKTS\n" +
"Qu+KulEt+Sn2/ioiQoKknxJWDkBZxHLkgRC3ejTO\n" +
"=et/I\n" +
"-----END PGP SIGNATURE-----\n";
String keyASigT2_T3 = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJd3PvyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmexsHg/HXrdneCOLkWkDj95sRwrSkFKyzFUJtY+9xLv\n" +
"1RYhBNGmbhojsYLJmA94jPv8yCoBXnMwAAAqEQv+NdTRkL4vJA1Gst/LK7f3ytjF\n" +
"H7kkMI9aTQVxnscsNMGZYBjzaT410if/axqCyAmJX3lPWfHIsIZWmglxEPK04K2b\n" +
"Ql04JEpTzEVKIKGLBPhfLT/QamtZJmGpoGw7ba8lZ8Xrarb1Lf9srRBF+WKIzuwd\n" +
"FQAGsPw/57Q4YXNwPnPJwQbOrfuZLLGGZLczGiBW8900NH0Rg82fcMdO2XmuXhMb\n" +
"NnwYoXH7vV+i2uodfdmNhts9ENeiPmPF7DPiKDQtSQ6LLspVE/RoP/lXdd7cGSQR\n" +
"J1IaWX1rN598wBz1wNVwBpxucxxIjm9JYER9+eV3oo08b0+DF4OppDcrJvGnQcdE\n" +
"QuEOAqNeSrFGqXglfZ/Cep5ZkIVPtJA88e9FZYz7xlx49bh1os1jc7jeSA6xG/1O\n" +
"48ZQiPrLkVZp/62j0GvFEZzOj0CVb+/J2gsQ32SYkKeiZfXIdodReQMYAiXHeEj2\n" +
"mtuOFO8yVqWUwnlUwQoVAnr9zMulZB2Np29wvevU\n" +
"=kusD\n" +
"-----END PGP SIGNATURE-----\n";
String keyASigT3_now = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJeAeXyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmcElcHwXV0gKjafJ0j2dKF+EeukF5ywMBZMMkEyyjG4\n" +
"jhYhBNGmbhojsYLJmA94jPv8yCoBXnMwAAASuAwAnu1KFMNci1CEkzJb5fkVZRGz\n" +
"Cvo2wC0HXhwMoGm/icuw3qTNWpj3wCA6tOTgIGT6FwfYV42mNkFYpiUSelpIdTP7\n" +
"R5wf7cvu2wS5sZo+q9a3K4T2gWu+hlLO00/q8LJYTAG3dQZd6Mhk3gPUh3qNWHuR\n" +
"zi3gXajxaQ1yJrFHjRt86DBks5vCBWeFkcNQcuIZgoKlHsGxEgfQo0Yej6v4FBrQ\n" +
"xr3iU4GhSAQOFmZQPL2AVOfE8if9CqNRNLGpkloEDAhoSf+TxRyWXFfvXZQGKgSA\n" +
"oKbgQFyUgdybPFXiQa8ezZaO23risIG/7oe+rAM0vOWMA0f2F0d2W5t4UeZLLxsu\n" +
"Gh+7ZYK/MDF1HgFHjYefoW7pSPoNzaSIFv6goCtTr1O2c7BnO9QxU1H1rWgkFUd0\n" +
"NWHrk3H89te7fP94GtBskR1OnT8zxWVMtFx8NEDicrSw/sKqmxkxh0xW434ZtXgi\n" +
"FT2kVzTaUKN+UQ7UIs9wgtqb+s7Dvb7b1bO8wvLg\n" +
"=DeXH\n" +
"-----END PGP SIGNATURE-----\n";
String keyBSigT0 = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJdkyfyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmfAtB+VtWWsZc4DiK/QK7LEDG+KAl+ORwXnUahXErz3\n" +
"GhYhBNGmbhojsYLJmA94jPv8yCoBXnMwAABlEAv/fe0No+TMQTq5xkyv2xNgzibB\n" +
"sqeOBbmZL82PfGJTthEtZ+eKi0pNnGPlFH0VIkRskNRKEZqLGJh2d/xDstiPBTfc\n" +
"TzTn66f43h+WnGRqGLYbKHfrJ+Mn/wHub9zxauDvpjcIqOLYscuZ+rvp/OyExoST\n" +
"lOmfLsrpGgS//eMDchgeFTybZy3UP7dw+BHHSlMW/s4QvgqqS8v5x2bNgMcairzN\n" +
"BMxafx6Mp4RSk46tF+INzPgV8W+ImyGXtkZcBmiv9/u36X6GESSyHl/DVf+ZlHm9\n" +
"u35dGn8S2PhyE12eQnLZJoorqcIOtwx1sAD+317Dprv8fwcHBhgyKLVsx2O5NTWn\n" +
"fZNRtdjQiUBt03D4Qdxoru/UzpGZWq4OLLZVB7u2B4tRQohkBCH96s5hvY2GHXSN\n" +
"Md3FCvms+lCEFi70Ae1KZCpD1/DHCFQcT5fYMYVNU1HFB8eQoKMM3kmv0VpJ31CB\n" +
"bJ0esmX6JDukiepzcr09w7bbkhGvKnDgUM3dNxhv\n" +
"=PfHW\n" +
"-----END PGP SIGNATURE-----\n";
String keyBSigT1_T2 = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJduBHyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmcglTWhGNT4tUfWuGHHpZUQZGDvZ4AKjIM/B97lFgac\n" +
"XBYhBNGmbhojsYLJmA94jPv8yCoBXnMwAADPmAv9EZlRAp65+JLsABQa8sk0YgRU\n" +
"28n6/Wcv2nj0iZMtbnXu2hLJqPj62JihCNbElEgJb7NIYbTPEAiyUisq8sa+E12F\n" +
"PvBsqcNAdLxlDRyPcwlDrbl0fRqLt/fiItMp6lHnfl2SfrSkzWv8t2DswPS+LXpt\n" +
"k5GBWxnJMRQ2Lf1L8rriFY1p6D9XtO8n9wGWMzCoxp3q+diQa8YJbhppPPskU5rT\n" +
"bPYH7f1FnU2OzzxgeqlAjtpjkTmzy3RNRlzGEYk6NnNbHQN0sQoiQdOaHMJ/qKMF\n" +
"wanYX2iatYCCYJGMDv3Ysw6nXLyiZ6dbqFEJwzRCiZQ2ZBYvzRyEnMojIZE3CXOv\n" +
"a+h5qm8Ffc+ZPc0spBoTxFCz8+Rmp5qNT9kFOIQUF9YOs/fo8sCr32ZbLu/bBsy9\n" +
"RhswX42fnAZ4DZJKlAORbtYmM52WsPxArGLnpOpgD8aT4Mt7SsVpAJXnjn43NKTS\n" +
"Qu+KulEt+Sn2/ioiQoKknxJWDkBZxHLkgRC3ejTO\n" +
"=et/I\n" +
"-----END PGP SIGNATURE-----\n";
String keyBSigT2_T3 = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJd3PvyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmexsHg/HXrdneCOLkWkDj95sRwrSkFKyzFUJtY+9xLv\n" +
"1RYhBNGmbhojsYLJmA94jPv8yCoBXnMwAAAqEQv+NdTRkL4vJA1Gst/LK7f3ytjF\n" +
"H7kkMI9aTQVxnscsNMGZYBjzaT410if/axqCyAmJX3lPWfHIsIZWmglxEPK04K2b\n" +
"Ql04JEpTzEVKIKGLBPhfLT/QamtZJmGpoGw7ba8lZ8Xrarb1Lf9srRBF+WKIzuwd\n" +
"FQAGsPw/57Q4YXNwPnPJwQbOrfuZLLGGZLczGiBW8900NH0Rg82fcMdO2XmuXhMb\n" +
"NnwYoXH7vV+i2uodfdmNhts9ENeiPmPF7DPiKDQtSQ6LLspVE/RoP/lXdd7cGSQR\n" +
"J1IaWX1rN598wBz1wNVwBpxucxxIjm9JYER9+eV3oo08b0+DF4OppDcrJvGnQcdE\n" +
"QuEOAqNeSrFGqXglfZ/Cep5ZkIVPtJA88e9FZYz7xlx49bh1os1jc7jeSA6xG/1O\n" +
"48ZQiPrLkVZp/62j0GvFEZzOj0CVb+/J2gsQ32SYkKeiZfXIdodReQMYAiXHeEj2\n" +
"mtuOFO8yVqWUwnlUwQoVAnr9zMulZB2Np29wvevU\n" +
"=kusD\n" +
"-----END PGP SIGNATURE-----\n";
String keyBSigT3_now = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJeAeXyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmcElcHwXV0gKjafJ0j2dKF+EeukF5ywMBZMMkEyyjG4\n" +
"jhYhBNGmbhojsYLJmA94jPv8yCoBXnMwAAASuAwAnu1KFMNci1CEkzJb5fkVZRGz\n" +
"Cvo2wC0HXhwMoGm/icuw3qTNWpj3wCA6tOTgIGT6FwfYV42mNkFYpiUSelpIdTP7\n" +
"R5wf7cvu2wS5sZo+q9a3K4T2gWu+hlLO00/q8LJYTAG3dQZd6Mhk3gPUh3qNWHuR\n" +
"zi3gXajxaQ1yJrFHjRt86DBks5vCBWeFkcNQcuIZgoKlHsGxEgfQo0Yej6v4FBrQ\n" +
"xr3iU4GhSAQOFmZQPL2AVOfE8if9CqNRNLGpkloEDAhoSf+TxRyWXFfvXZQGKgSA\n" +
"oKbgQFyUgdybPFXiQa8ezZaO23risIG/7oe+rAM0vOWMA0f2F0d2W5t4UeZLLxsu\n" +
"Gh+7ZYK/MDF1HgFHjYefoW7pSPoNzaSIFv6goCtTr1O2c7BnO9QxU1H1rWgkFUd0\n" +
"NWHrk3H89te7fP94GtBskR1OnT8zxWVMtFx8NEDicrSw/sKqmxkxh0xW434ZtXgi\n" +
"FT2kVzTaUKN+UQ7UIs9wgtqb+s7Dvb7b1bO8wvLg\n" +
"=DeXH\n" +
"-----END PGP SIGNATURE-----\n";
String keyCSigT0 = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJdkyfyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmfAtB+VtWWsZc4DiK/QK7LEDG+KAl+ORwXnUahXErz3\n" +
"GhYhBNGmbhojsYLJmA94jPv8yCoBXnMwAABlEAv/fe0No+TMQTq5xkyv2xNgzibB\n" +
"sqeOBbmZL82PfGJTthEtZ+eKi0pNnGPlFH0VIkRskNRKEZqLGJh2d/xDstiPBTfc\n" +
"TzTn66f43h+WnGRqGLYbKHfrJ+Mn/wHub9zxauDvpjcIqOLYscuZ+rvp/OyExoST\n" +
"lOmfLsrpGgS//eMDchgeFTybZy3UP7dw+BHHSlMW/s4QvgqqS8v5x2bNgMcairzN\n" +
"BMxafx6Mp4RSk46tF+INzPgV8W+ImyGXtkZcBmiv9/u36X6GESSyHl/DVf+ZlHm9\n" +
"u35dGn8S2PhyE12eQnLZJoorqcIOtwx1sAD+317Dprv8fwcHBhgyKLVsx2O5NTWn\n" +
"fZNRtdjQiUBt03D4Qdxoru/UzpGZWq4OLLZVB7u2B4tRQohkBCH96s5hvY2GHXSN\n" +
"Md3FCvms+lCEFi70Ae1KZCpD1/DHCFQcT5fYMYVNU1HFB8eQoKMM3kmv0VpJ31CB\n" +
"bJ0esmX6JDukiepzcr09w7bbkhGvKnDgUM3dNxhv\n" +
"=PfHW\n" +
"-----END PGP SIGNATURE-----\n";
String keyCSigT1_T2 = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJduBHyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmcglTWhGNT4tUfWuGHHpZUQZGDvZ4AKjIM/B97lFgac\n" +
"XBYhBNGmbhojsYLJmA94jPv8yCoBXnMwAADPmAv9EZlRAp65+JLsABQa8sk0YgRU\n" +
"28n6/Wcv2nj0iZMtbnXu2hLJqPj62JihCNbElEgJb7NIYbTPEAiyUisq8sa+E12F\n" +
"PvBsqcNAdLxlDRyPcwlDrbl0fRqLt/fiItMp6lHnfl2SfrSkzWv8t2DswPS+LXpt\n" +
"k5GBWxnJMRQ2Lf1L8rriFY1p6D9XtO8n9wGWMzCoxp3q+diQa8YJbhppPPskU5rT\n" +
"bPYH7f1FnU2OzzxgeqlAjtpjkTmzy3RNRlzGEYk6NnNbHQN0sQoiQdOaHMJ/qKMF\n" +
"wanYX2iatYCCYJGMDv3Ysw6nXLyiZ6dbqFEJwzRCiZQ2ZBYvzRyEnMojIZE3CXOv\n" +
"a+h5qm8Ffc+ZPc0spBoTxFCz8+Rmp5qNT9kFOIQUF9YOs/fo8sCr32ZbLu/bBsy9\n" +
"RhswX42fnAZ4DZJKlAORbtYmM52WsPxArGLnpOpgD8aT4Mt7SsVpAJXnjn43NKTS\n" +
"Qu+KulEt+Sn2/ioiQoKknxJWDkBZxHLkgRC3ejTO\n" +
"=et/I\n" +
"-----END PGP SIGNATURE-----\n";
String keyCSigT2_T3 = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJd3PvyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmexsHg/HXrdneCOLkWkDj95sRwrSkFKyzFUJtY+9xLv\n" +
"1RYhBNGmbhojsYLJmA94jPv8yCoBXnMwAAAqEQv+NdTRkL4vJA1Gst/LK7f3ytjF\n" +
"H7kkMI9aTQVxnscsNMGZYBjzaT410if/axqCyAmJX3lPWfHIsIZWmglxEPK04K2b\n" +
"Ql04JEpTzEVKIKGLBPhfLT/QamtZJmGpoGw7ba8lZ8Xrarb1Lf9srRBF+WKIzuwd\n" +
"FQAGsPw/57Q4YXNwPnPJwQbOrfuZLLGGZLczGiBW8900NH0Rg82fcMdO2XmuXhMb\n" +
"NnwYoXH7vV+i2uodfdmNhts9ENeiPmPF7DPiKDQtSQ6LLspVE/RoP/lXdd7cGSQR\n" +
"J1IaWX1rN598wBz1wNVwBpxucxxIjm9JYER9+eV3oo08b0+DF4OppDcrJvGnQcdE\n" +
"QuEOAqNeSrFGqXglfZ/Cep5ZkIVPtJA88e9FZYz7xlx49bh1os1jc7jeSA6xG/1O\n" +
"48ZQiPrLkVZp/62j0GvFEZzOj0CVb+/J2gsQ32SYkKeiZfXIdodReQMYAiXHeEj2\n" +
"mtuOFO8yVqWUwnlUwQoVAnr9zMulZB2Np29wvevU\n" +
"=kusD\n" +
"-----END PGP SIGNATURE-----\n";
String keyCSigT3_now = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsE7BAABCgBvBYJeAeXyCRD7/MgqAV5zMEcUAAAAAAAeACBzYWx0QG5vdGF0aW9u\n" +
"cy5zZXF1b2lhLXBncC5vcmcElcHwXV0gKjafJ0j2dKF+EeukF5ywMBZMMkEyyjG4\n" +
"jhYhBNGmbhojsYLJmA94jPv8yCoBXnMwAAASuAwAnu1KFMNci1CEkzJb5fkVZRGz\n" +
"Cvo2wC0HXhwMoGm/icuw3qTNWpj3wCA6tOTgIGT6FwfYV42mNkFYpiUSelpIdTP7\n" +
"R5wf7cvu2wS5sZo+q9a3K4T2gWu+hlLO00/q8LJYTAG3dQZd6Mhk3gPUh3qNWHuR\n" +
"zi3gXajxaQ1yJrFHjRt86DBks5vCBWeFkcNQcuIZgoKlHsGxEgfQo0Yej6v4FBrQ\n" +
"xr3iU4GhSAQOFmZQPL2AVOfE8if9CqNRNLGpkloEDAhoSf+TxRyWXFfvXZQGKgSA\n" +
"oKbgQFyUgdybPFXiQa8ezZaO23risIG/7oe+rAM0vOWMA0f2F0d2W5t4UeZLLxsu\n" +
"Gh+7ZYK/MDF1HgFHjYefoW7pSPoNzaSIFv6goCtTr1O2c7BnO9QxU1H1rWgkFUd0\n" +
"NWHrk3H89te7fP94GtBskR1OnT8zxWVMtFx8NEDicrSw/sKqmxkxh0xW434ZtXgi\n" +
"FT2kVzTaUKN+UQ7UIs9wgtqb+s7Dvb7b1bO8wvLg\n" +
"=DeXH\n" +
"-----END PGP SIGNATURE-----\n";
PGPPublicKeyRing keysA = PGPainless.readKeyRing().publicKeyRing(keyA);
PGPPublicKeyRing keysB = PGPainless.readKeyRing().publicKeyRing(keyB);
PGPPublicKeyRing keysC = PGPainless.readKeyRing().publicKeyRing(keyC);
PGPSignature sigAT0 = SignatureUtils.readSignatures(keyASigT0).get(0);
PGPSignature sigAT1_T2 = SignatureUtils.readSignatures(keyASigT1_T2).get(0);
PGPSignature sigAT2_T3 = SignatureUtils.readSignatures(keyASigT2_T3).get(0);
PGPSignature sigAT3_now = SignatureUtils.readSignatures(keyASigT3_now).get(0);
PGPSignature sigBT0 = SignatureUtils.readSignatures(keyBSigT0).get(0);
PGPSignature sigBT1_T2 = SignatureUtils.readSignatures(keyBSigT1_T2).get(0);
PGPSignature sigBT2_T3 = SignatureUtils.readSignatures(keyBSigT2_T3).get(0);
PGPSignature sigBT3_now = SignatureUtils.readSignatures(keyBSigT3_now).get(0);
PGPSignature sigCT0 = SignatureUtils.readSignatures(keyCSigT0).get(0);
PGPSignature sigCT1_T2 = SignatureUtils.readSignatures(keyCSigT1_T2).get(0);
PGPSignature sigCT2_T3 = SignatureUtils.readSignatures(keyCSigT2_T3).get(0);
PGPSignature sigCT3_now = SignatureUtils.readSignatures(keyCSigT3_now).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello World :)";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigAT0, getSignedData(data), keysA, policy, validationDate),
"Signature predates key creation time");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigAT1_T2, getSignedData(data), keysA, policy, validationDate),
"Key valid");
assertThrows(SignatureValidationException.class, () ->
CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigAT2_T3, getSignedData(data), keysA, policy, validationDate),
"Key is not valid, as subkey binding expired");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigAT3_now, getSignedData(data), keysA, policy, validationDate),
"Key is valid again");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigBT0, getSignedData(data), keysB, policy, validationDate),
"Signature predates key creation time");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigBT1_T2, getSignedData(data), keysB, policy, validationDate),
"Key is valid");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigBT2_T3, getSignedData(data), keysB, policy, validationDate),
"Primary key is not signing-capable");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigBT3_now, getSignedData(data), keysB, policy, validationDate),
"Key is valid again");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigCT0, getSignedData(data), keysC, policy, validationDate),
"Signature predates key creation time");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigCT1_T2, getSignedData(data), keysC, policy, validationDate),
"Key is valid");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigCT2_T3, getSignedData(data), keysC, policy, validationDate),
"Key is revoked");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
sigCT3_now, getSignedData(data), keysC, policy, validationDate),
"Key is valid again");
}
private static InputStream getSignedData(String data) {
return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
}
@Test
public void testNoIssuer() throws IOException, PGPException {
String SIG = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"wsExBAABCABlBYJhBZl3RxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEt\n" +
"cGdwLm9yZ6u++H3Om9Z3+mn7nyt3TSxs4o/D4fHi+e+X+/7jEj3dFiEE0aZuGiOx\n" +
"gsmYD3iM+/zIKgFeczAAAOQKDACD4krXC/9GQQcl+waBglgmQaUWd+YEpXlPDQc3\n" +
"dPF7kkc/pRmmGVur8kk8rWmuQwNvQt7vGD2YJzcWBFvSSZlbYa89Gd3L5H2keTYC\n" +
"0Q/VbZqBp9ONtK3D9Yrti2jMYdcb30LZQnsSUsB0mwX41AxjPLx0FAcVMAEADjq/\n" +
"zLkJ1y+vXCko653qS/um6VQGK8JeNHRz8ghrc4k0E2yYadWWO07wxuoTAlwskf32\n" +
"MdSVeIUQIEZqEgWMbqtqglqL3eNWk56IonCePtulkQSN6qi4JpqTeudlOm+Zp/IN\n" +
"Tk+vrdS8PyQ0CiM794t/iHZDK5Jyz4ccFhTLPbF58xnwkwqdWPdf8WjCzaLfZcuN\n" +
"zajVdDXOBjNC1s10voENZhChsZYc9BfHqVMrOe8ngLKCCzqlJ/E930OJiZX5pc+H\n" +
"mHaHdn0m6lrhM5JX6RT9TNS/yrjdpkScb68Rcf+rXdeSoCE/aDOCVXhIhVTMQ9di\n" +
"Ch80fhwtYYjAM9G0/AEs7uBCGQQ=\n" +
"=NDO/\n" +
"-----END PGP SIGNATURE-----\n";
String CERT = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"Comment: Bob's OpenPGP certificate\n" +
"\n" +
"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\n" +
"NEJd3XZRzaXZE2aAMQ==\n" +
"=NXei\n" +
"-----END PGP PUBLIC KEY BLOCK-----\n";
String DATA = "Hello World :)";
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(DATA.getBytes(StandardCharsets.UTF_8)))
.withOptions(new ConsumerOptions()
.addVerificationCert(PGPainless.readKeyRing().publicKeyRing(CERT))
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(SIG.getBytes(StandardCharsets.UTF_8))));
Streams.drain(decryptionStream);
decryptionStream.close();
OpenPgpMetadata metadata = decryptionStream.getResult();
assertFalse(metadata.getVerifiedSignatures().isEmpty());
}
}