Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMickael Istria2021-04-13 20:41:15 +0000
committerMickael Istria2021-04-16 12:40:11 +0000
commitd92c82f87cef36cc6840b14b6d8e85be55f9f335 (patch)
treee2d6f34597d02e34b74e533fc08b61ea74eb1aa6
parent08e7a7205f06c10ad9dfc9cfe2244cd781bb1d5d (diff)
downloadrt.equinox.p2-d92c82f87cef36cc6840b14b6d8e85be55f9f335.tar.gz
rt.equinox.p2-d92c82f87cef36cc6840b14b6d8e85be55f9f335.tar.xz
rt.equinox.p2-d92c82f87cef36cc6840b14b6d8e85be55f9f335.zip
Bug 570907 - A processingStep to verify PGP signatures in artifactI20210416-1800
metadata Change-Id: I2300bce7861e59f5851c81a5b0204da9bfa111d0 Signed-off-by: Mickael Istria <mistria@redhat.com> Reviewed-on: https://git.eclipse.org/r/c/equinox/rt.equinox.p2/+/175851 Tested-by: Equinox Bot <equinox-bot@eclipse.org>
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF9
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml6
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/Messages.java32
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPSignatureVerifier.java203
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/messages.properties14
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java14
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/PGPSignatureVerifierTest.java111
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/private_signer1.pgp84
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/private_signer2.pgp84
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/public_signer1.pgp41
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/public_signer2.pgp41
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_114
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1_otherArtifact14
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1_tampered14
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_214
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/testArtifact1
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/PGPTest.java61
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/artifacts.xml36
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/content.xml49
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/META-INF/MANIFEST.MF4
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/blah_1.0.0.123456.jarbin0 -> 408 bytes
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/blah_1.0.0.123456.jar.asc14
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/artifacts.xml16
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/content.xml49
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/META-INF/MANIFEST.MF4
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/blah_1.0.0.123456.jarbin0 -> 408 bytes
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/blah_1.0.0.123456.jar.asc14
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/artifacts.xml78
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/content.xml49
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/META-INF/MANIFEST.MF4
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/blah_1.0.0.123456.jarbin0 -> 408 bytes
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/blah_1.0.0.123456.jar.asc14
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/artifacts.xml78
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/content.xml49
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/META-INF/MANIFEST.MF4
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/blah_1.0.0.123456.jarbin0 -> 408 bytes
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/blah_1.0.0.123456.jar.asc14
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/artifacts.xml78
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/content.xml49
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/META-INF/MANIFEST.MF4
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/blah_1.0.0.123456.jarbin0 -> 408 bytes
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/blah_1.0.0.123456.jar.asc14
44 files changed, 1378 insertions, 4 deletions
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF
index 201993516..6c49a76b0 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF
@@ -10,6 +10,7 @@ Export-Package: org.eclipse.equinox.internal.p2.artifact.processing;x-friends:="
org.eclipse.equinox.internal.p2.artifact.processors.checksum;x-friends:="org.eclipse.equinox.p2.publisher",
org.eclipse.equinox.internal.p2.artifact.processors.md5;x-internal:=true,
org.eclipse.equinox.internal.p2.artifact.processors.pack200;x-friends:="org.eclipse.equinox.p2.artifact.processors,org.eclipse.equinox.p2.artifact.optimizers",
+ org.eclipse.equinox.internal.p2.artifact.processors.pgp;x-internal:=true,
org.eclipse.equinox.internal.p2.artifact.repository;
x-friends:="org.eclipse.equinox.p2.publisher,
org.eclipse.equinox.p2.reconciler.dropins,
@@ -37,6 +38,14 @@ Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.7.0,4.0.0)",
org.eclipse.equinox.p2.metadata,
org.tukaani.xz;bundle-version="1.3.0"
Import-Package: javax.xml.parsers,
+ org.bouncycastle.bcpg;version="1.65.0",
+ org.bouncycastle.jce.provider;version="1.65.1",
+ org.bouncycastle.openpgp;version="1.65.0",
+ org.bouncycastle.openpgp.bc;version="1.65.0",
+ org.bouncycastle.openpgp.jcajce;version="1.65.0",
+ org.bouncycastle.openpgp.operator;version="1.65.0",
+ org.bouncycastle.openpgp.operator.bc;version="1.65.0",
+ org.bouncycastle.openpgp.operator.jcajce;version="1.65.0",
org.eclipse.core.runtime.jobs,
org.eclipse.equinox.internal.p2.core.helpers,
org.eclipse.equinox.internal.p2.jarprocessor,
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml b/bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml
index bf5778333..879eace3b 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml
@@ -52,4 +52,10 @@
id="sha-256">
</artifactChecksum>
</extension>
+
+ <extension
+ id="org.eclipse.equinox.p2.processing.PGPSignatureCheck"
+ point="org.eclipse.equinox.p2.artifact.repository.processingSteps">
+ <step class="org.eclipse.equinox.internal.p2.artifact.processors.pgp.PGPSignatureVerifier"/>
+ </extension>
</plugin>
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/Messages.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/Messages.java
new file mode 100644
index 000000000..4ae7cc402
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/Messages.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2021 Red Hat Inc. and others
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.artifact.processors.pgp;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.p2.artifact.processors.pgp.messages"; //$NON-NLS-1$
+
+ public static String Error_SignatureAndFileDontMatch;
+
+ public static String Error_CouldNotLoadSignature;
+
+ public static String Error_publicKeyNotFound;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ //empty
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPSignatureVerifier.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPSignatureVerifier.java
new file mode 100644
index 000000000..e81fc0e43
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPSignatureVerifier.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2021 Red Hat Inc. and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.artifact.processors.pgp;
+
+import java.io.*;
+import java.util.*;
+import org.bouncycastle.bcpg.ArmoredInputStream;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openpgp.*;
+import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
+import org.bouncycastle.openpgp.jcajce.JcaPGPPublicKeyRingCollection;
+import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.artifact.repository.Activator;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStep;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.repository.artifact.*;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * This processing step verifies PGP signatures are correct (ie artifact was not
+ * tampered during fetch). Note that is does <b>not</b> deal with trust. Dealing
+ * with trusted signers is done as part of CheckTrust touchpoint and phase.
+ */
+public final class PGPSignatureVerifier extends ProcessingStep {
+
+ /**
+ * ID of the registering
+ * <code>org.eclipse.equinox.p2.artifact.repository.processingSteps</tt>
+ * extension.
+ */
+ public static final String ID = "org.eclipse.equinox.p2.processing.PGPSignatureCheck"; //$NON-NLS-1$
+
+ public static final String PGP_SIGNER_KEYS_PROPERTY_NAME = "pgp.publicKeys"; //$NON-NLS-1$
+ public static final String PGP_SIGNATURES_PROPERTY_NAME = "pgp.signatures"; //$NON-NLS-1$
+ private List<PGPSignature> signaturesToVerify;
+
+ public PGPSignatureVerifier() {
+ super();
+ link(nullOutputStream(), new NullProgressMonitor()); // this is convenience for tests
+ }
+
+ @Override
+ public void initialize(IProvisioningAgent agent, IProcessingStepDescriptor descriptor,
+ IArtifactDescriptor context) {
+ super.initialize(agent, descriptor, context);
+// 1. verify declared public keys have signature from a trusted key, if so, add to KeyStore
+// 2. verify artifact signature matches signture of given keys, and at least 1 of this key is trusted
+ String signatureText = unnormalizedPGPProperty(context.getProperty(PGP_SIGNATURES_PROPERTY_NAME));
+ if (signatureText == null) {
+ setStatus(Status.OK_STATUS);
+ return;
+ }
+ signaturesToVerify = new ArrayList<>();
+ try (InputStream in = new ArmoredInputStream(new ByteArrayInputStream(signatureText.getBytes()))) {
+ JcaPGPObjectFactory pgpFactory = new JcaPGPObjectFactory(in);
+ Object o = pgpFactory.nextObject();
+ PGPSignatureList signatureList;
+ if (o instanceof PGPCompressedData) {
+ PGPCompressedData pgpCompressData = (PGPCompressedData) o;
+ pgpFactory = new JcaPGPObjectFactory(pgpCompressData.getDataStream());
+ signatureList = (PGPSignatureList) pgpFactory.nextObject();
+ } else if (o instanceof PGPSignatureList) {
+ signatureList = (PGPSignatureList) o;
+ } else {
+ setStatus(new Status(IStatus.ERROR, Activator.ID,
+ Messages.Error_CouldNotLoadSignature));
+ return;
+ }
+ signatureList.iterator().forEachRemaining(signaturesToVerify::add);
+ } catch (Exception ex) {
+ setStatus(new Status(IStatus.ERROR, Activator.ID, Messages.Error_CouldNotLoadSignature, ex));
+ return;
+ }
+ if (signaturesToVerify.isEmpty()) {
+ setStatus(Status.OK_STATUS);
+ return;
+ }
+
+ IArtifactRepository repository = context.getRepository();
+ Map<Long, PGPPublicKey> signerKeys = readPublicKeys(context.getProperty(PGP_SIGNER_KEYS_PROPERTY_NAME),
+ repository != null ? repository.getProperty(PGP_SIGNER_KEYS_PROPERTY_NAME) : null);
+ for (PGPSignature signature : signaturesToVerify) {
+ PGPPublicKey publicKey = signerKeys.get(signature.getKeyID());
+ if (publicKey == null) {
+ setStatus(new Status(IStatus.ERROR, Activator.ID,
+ NLS.bind(Messages.Error_publicKeyNotFound, signature.getKeyID())));
+ return;
+ }
+ try {
+ signature.init(new JcaPGPContentVerifierBuilderProvider().setProvider(new BouncyCastleProvider()),
+ publicKey);
+ } catch (PGPException ex) {
+ setStatus(new Status(IStatus.ERROR, Activator.ID, ex.getMessage(), ex));
+ return;
+ }
+ }
+ }
+
+ /**
+ * See // https://www.w3.org/TR/1998/REC-xml-19980210#AVNormalize, newlines
+ * replaced by spaces by parser, needs to be restored
+ *
+ * @param context
+ * @param pgpSignaturesPropertyName
+ * @return fixed PGP armored blocks
+ */
+ private String unnormalizedPGPProperty(String value) {
+ if (value == null) {
+ return null;
+ }
+ return value.replace(' ', '\n').replace("-----BEGIN\nPGP\nSIGNATURE-----", "-----BEGIN PGP SIGNATURE-----") //$NON-NLS-1$ //$NON-NLS-2$
+ .replace("-----END\nPGP\nSIGNATURE-----", "-----END PGP SIGNATURE-----") //$NON-NLS-1$ //$NON-NLS-2$
+ .replace("-----BEGIN\nPGP\nPUBLIC\nKEY\nBLOCK-----", "-----BEGIN PGP PUBLIC KEY BLOCK-----") //$NON-NLS-1$ //$NON-NLS-2$
+ .replace("-----END\nPGP\nPUBLIC\nKEY\nBLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ private Map<Long, PGPPublicKey> readPublicKeys(String armoredPublicKeyring) {
+ if (armoredPublicKeyring == null) {
+ return Collections.emptyMap();
+ }
+ Map<Long, PGPPublicKey> res = new HashMap<>();
+ try (InputStream stream = PGPUtil
+ .getDecoderStream(new ByteArrayInputStream(unnormalizedPGPProperty(armoredPublicKeyring).getBytes()))) {
+ PGPPublicKeyRingCollection pgpPub = new JcaPGPPublicKeyRingCollection(stream);
+
+ pgpPub.getKeyRings().forEachRemaining(kRing ->
+ kRing.getPublicKeys().forEachRemaining(key -> res.put(key.getKeyID(), key))
+ );
+ } catch (IOException | PGPException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e));
+ }
+ return res;
+
+ }
+
+ private Map<Long, PGPPublicKey> readPublicKeys(String... armoredPublicKeys) {
+ Map<Long, PGPPublicKey> keys = new HashMap<>();
+ for (String armoredKey : armoredPublicKeys) {
+ if (armoredKey != null) {
+ keys.putAll(readPublicKeys(armoredKey));
+ }
+ }
+ return keys;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ if (signaturesToVerify != null) {
+ signaturesToVerify.iterator().forEachRemaining(signature -> signature.update((byte) b));
+ }
+
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ getDestination().write(b);
+ if (signaturesToVerify != null) {
+ signaturesToVerify.iterator().forEachRemaining(signature -> signature.update(b));
+ }
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ getDestination().write(b, off, len);
+ if (signaturesToVerify != null) {
+ signaturesToVerify.iterator().forEachRemaining(signature -> signature.update(b, off, len));
+ }
+ }
+
+ @Override
+ public void close() {
+ if (!getStatus().isOK()) {
+ return;
+ }
+ if (signaturesToVerify == null || signaturesToVerify.isEmpty()) {
+ return;
+ }
+ Iterator<PGPSignature> iterator = signaturesToVerify.iterator();
+ while (iterator.hasNext()) {
+ PGPSignature signature = iterator.next();
+ try {
+ if (!signature.verify()) {
+ setStatus(new Status(IStatus.ERROR, Activator.ID, Messages.Error_SignatureAndFileDontMatch));
+ return;
+ }
+ } catch (PGPException ex) {
+ setStatus(new Status(IStatus.ERROR, Activator.ID, ex.getMessage(), ex));
+ return;
+ }
+ }
+ setStatus(Status.OK_STATUS);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/messages.properties b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/messages.properties
new file mode 100644
index 000000000..90d95f756
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/messages.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2021 Red Hat Inc. and others
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+###############################################################################
+
+Error_SignatureAndFileDontMatch=Signature is invalid for current content.
+Error_CouldNotLoadSignature=Could not load signature
+Error_publicKeyNotFound=Public key not found for {0}.
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java
index 73cf82456..e58c5c6da 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java
@@ -29,6 +29,7 @@ import java.util.jar.JarOutputStream;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.p2.artifact.processors.checksum.ChecksumUtilities;
+import org.eclipse.equinox.internal.p2.artifact.processors.pgp.PGPSignatureVerifier;
import org.eclipse.equinox.internal.p2.artifact.repository.*;
import org.eclipse.equinox.internal.p2.artifact.repository.Messages;
import org.eclipse.equinox.internal.p2.core.helpers.FileUtils;
@@ -48,8 +49,7 @@ import org.eclipse.equinox.p2.metadata.index.IIndexProvider;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.*;
import org.eclipse.equinox.p2.repository.artifact.*;
-import org.eclipse.equinox.p2.repository.artifact.spi.AbstractArtifactRepository;
-import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor;
+import org.eclipse.equinox.p2.repository.artifact.spi.*;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.util.NLS;
@@ -478,6 +478,7 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
Set<String> skipChecksums = ARTIFACT_MD5_CHECKSUM_ENABLED ? Collections.emptySet() : Collections.singleton(ChecksumHelper.MD5);
addChecksumVerifiers(descriptor, steps, skipChecksums, IArtifactDescriptor.ARTIFACT_CHECKSUM);
+ addPGPSignatureVerifier(descriptor, steps);
if (steps.isEmpty())
return destination;
@@ -486,6 +487,15 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
return handler.link(stepArray, destination, monitor);
}
+ private void addPGPSignatureVerifier(IArtifactDescriptor descriptor, ArrayList<ProcessingStep> steps) {
+ if (descriptor.getProperties().containsKey(PGPSignatureVerifier.PGP_SIGNATURES_PROPERTY_NAME)) {
+ PGPSignatureVerifier step = new PGPSignatureVerifier();
+ ProcessingStepDescriptor stepDescriptor = new ProcessingStepDescriptor(PGPSignatureVerifier.ID, null, true);
+ step.initialize(getProvisioningAgent(), stepDescriptor, descriptor);
+ steps.add(step);
+ }
+ }
+
private OutputStream addPreSteps(ProcessingStepHandler handler, IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
ArrayList<ProcessingStep> steps = new ArrayList<>();
if (IArtifactDescriptor.TYPE_ZIP.equals(descriptor.getProperty(IArtifactDescriptor.DOWNLOAD_CONTENTTYPE)))
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java
index ac40ea25b..01422270a 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java
@@ -22,7 +22,7 @@ import org.junit.runners.Suite;
@SuppressWarnings("removal")
@RunWith(Suite.class)
@Suite.SuiteClasses({ Pack200ProcessorTest.class, ZipVerifierProcessorTest.class, ChecksumVerifierTest.class,
- ChecksumUtilitiesTest.class })
+ ChecksumUtilitiesTest.class, PGPSignatureVerifierTest.class })
public class AllTests {
// test suite
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/PGPSignatureVerifierTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/PGPSignatureVerifierTest.java
new file mode 100644
index 000000000..36b50a545
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/PGPSignatureVerifierTest.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2021 Red Hat Inc. and others
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.artifact.processors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.equinox.internal.p2.artifact.processors.pgp.Messages;
+import org.eclipse.equinox.internal.p2.artifact.processors.pgp.PGPSignatureVerifier;
+import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
+import org.eclipse.equinox.p2.metadata.Version;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
+import org.eclipse.equinox.p2.repository.artifact.IProcessingStepDescriptor;
+import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor;
+import org.eclipse.equinox.p2.repository.artifact.spi.ProcessingStepDescriptor;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PGPSignatureVerifierTest {
+
+ // @formatter:off
+ /*
+ * About test keys:
+ * * Install the public&private keys locally
+ * * then generate signatures with eg `gpg -u signer2@fakeuser.eclipse.org -a --output signed_by_signer_2 --detach-sig testArtifact`
+ */
+ // @formatter:on
+
+ private IArtifactDescriptor createArtifact(String signaturesResourcePath, String publicKeyResourcePath)
+ throws IOException, URISyntaxException {
+ ArtifactDescriptor res = new ArtifactDescriptor(
+ new ArtifactKey("whatever", "whatever", Version.parseVersion("1.0.0")));
+ res.setProperty(PGPSignatureVerifier.PGP_SIGNATURES_PROPERTY_NAME, read(signaturesResourcePath));
+ res.setProperty(PGPSignatureVerifier.PGP_SIGNER_KEYS_PROPERTY_NAME, read(publicKeyResourcePath));
+ return res;
+ }
+
+ private String read(String resource) throws IOException, URISyntaxException {
+ return Files.readString(new File(FileLocator.toFileURL(getClass().getResource(resource)).toURI()).toPath());
+ }
+
+ @Test
+ public void testOK() throws Exception {
+ IProcessingStepDescriptor processingStepDescriptor = new ProcessingStepDescriptor(null, null, false);
+ IArtifactDescriptor artifact = createArtifact("signed_by_signer_1", "public_signer1.pgp");
+ PGPSignatureVerifier verifier = new PGPSignatureVerifier();
+ verifier.initialize(null, processingStepDescriptor, artifact);
+ Assert.assertTrue(verifier.getStatus().toString(), verifier.getStatus().isOK());
+ try (InputStream bytes = getClass().getResourceAsStream("testArtifact")) {
+ bytes.transferTo(verifier);
+ }
+ Assert.assertTrue(verifier.getStatus().isOK());
+ verifier.close();
+ Assert.assertTrue(verifier.getStatus().isOK());
+ }
+
+ @Test
+ public void testNoPublicKeyFound() throws Exception {
+ IProcessingStepDescriptor processingStepDescriptor = new ProcessingStepDescriptor(null, null, false);
+ IArtifactDescriptor artifact = createArtifact("signed_by_signer_1", "public_signer2.pgp");
+ try (PGPSignatureVerifier verifier = new PGPSignatureVerifier()) {
+ verifier.initialize(null, processingStepDescriptor, artifact);
+ IStatus status = verifier.getStatus();
+ assertEquals(IStatus.ERROR, status.getSeverity());
+ assertTrue(status.getMessage().contains("Public key not found for"));
+ }
+ }
+
+ @Test
+ public void testTamperedSignature() throws Exception {
+ IProcessingStepDescriptor processingStepDescriptor = new ProcessingStepDescriptor(null, null, false);
+ IArtifactDescriptor artifact = createArtifact("signed_by_signer_1_tampered", "public_signer1.pgp");
+ try (PGPSignatureVerifier verifier = new PGPSignatureVerifier()) {
+ verifier.initialize(null, processingStepDescriptor, artifact);
+ // signature has random modification, making it invalid by itself
+ Assert.assertFalse(verifier.getStatus().isOK());
+ }
+ }
+
+ @Test
+ public void testSignatureForAnotherArtifact() throws Exception {
+ IProcessingStepDescriptor processingStepDescriptor = new ProcessingStepDescriptor(null, null, false);
+ IArtifactDescriptor artifact = createArtifact("signed_by_signer_1_otherArtifact", "public_signer1.pgp");
+ PGPSignatureVerifier verifier = new PGPSignatureVerifier();
+ verifier.initialize(null, processingStepDescriptor, artifact);
+ Assert.assertTrue(verifier.getStatus().isOK());
+ try (InputStream bytes = getClass().getResourceAsStream("testArtifact")) {
+ bytes.transferTo(verifier);
+ }
+ Assert.assertTrue(verifier.getStatus().isOK());
+ verifier.close();
+ IStatus status = verifier.getStatus();
+ assertEquals(IStatus.ERROR, status.getSeverity());
+ assertTrue(status.getMessage().contains(Messages.Error_SignatureAndFileDontMatch));
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/private_signer1.pgp b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/private_signer1.pgp
new file mode 100644
index 000000000..33d2c2f5f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/private_signer1.pgp
@@ -0,0 +1,84 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+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
+TJJnGnssYADXMioK7p6Y
+=P53y
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/private_signer2.pgp b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/private_signer2.pgp
new file mode 100644
index 000000000..c54415f0c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/private_signer2.pgp
@@ -0,0 +1,84 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+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
+dhlWIjDhIRD9JBC+M657iNc=
+=OHTb
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/public_signer1.pgp b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/public_signer1.pgp
new file mode 100644
index 000000000..485e0bb6f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/public_signer1.pgp
@@ -0,0 +1,41 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=JYpC
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/public_signer2.pgp b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/public_signer2.pgp
new file mode 100644
index 000000000..0beadf637
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/public_signer2.pgp
@@ -0,0 +1,41 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=Kto/
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1 b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1
new file mode 100644
index 000000000..a001778a4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB1jSEdHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfDElAv/YEgAwby4DXD3J0ZX
+6iAU2nRjpaUqZ7SAVkOiueeuuxlDw9HnVpIEp/nAOM0OiJrY5h9jQwpLY+p7QmL/
+hWows1fX1PKzpJNATS3bHr+B7qxPkM2N2LKK/ipkknjBXeQIOZyn47nT1nI8/UbA
+UePb5PXDZdIraP6trf5WcsMPxncPntFA4hnPzoVSgvfIYw+Rnjnbsva67grJAe0s
+RJLQatTtPM35n7g3UiNwd09lADPz6u9Ka63GFIf1Prt/mZxsihYq+oJ3xwTudxin
+n2KFCVIw6pCfpXAdYp5CkpbLCBUxyM0TjwphpiVjpa3haqay6iOYcYTubpTcS60S
+Dmz0PE9RCyQq5ycXFPD1UGQKe4C3J/0PzUciT/WzDlxWhM0Wglgez+tYphwDyYHA
+4Q+aSv4FMtKJ/I+RVpgOeF+XApEFwPXB5gw9VtjP9e9uu2T3qEnllrzhfPnNzgY9
+km2tk2WYL2hFdRolQnSfzcimTBaa6GI7dWhMCYe0z1Q0xa1i
+=0YYr
+-----END PGP SIGNATURE-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1_otherArtifact b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1_otherArtifact
new file mode 100644
index 000000000..f8c604147
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1_otherArtifact
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB1+EodHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfD5LAwAyPl8TBsC0bYZAsRX
+BSGXjlJ+oBKci5VH6bgM/ldnZD5SsYv6PVoxxdOJA2R6S88xxd0DuWivYuG+9aiZ
+w98hx6g0vNH8AWL+yd+l+2yIS8i/MJ57MCvVztexq935fIYU5KGdUNNEjDIrGHQQ
+AR5QWfTiy9EGracG4W6F9twmMOfDlCJ3eRCetp5OTvqBzS2gLom8ECaw7tezYvA/
+09Ok88j7vMI5kL3FO3WzzR+obeYUc19F6602h4cEJs/yOTOj/gz6GCXsAnuYQs1L
+yhjv4Cp4sBnMw+zPX0jFeNHu35mPt8oOFz1NLN85GHO7v3FFXmtwxj8bVBWBQR3R
+Vfi+n8SfR3WO5pYpsqPHZgP95K+W53ere1BZd67cT6uuJDtoDWC6TYPjndm5tnN1
++AzDQO12cC4w2cgIt3ElNYK0T8ADvrmCMPZPRPJ+GeZb0jb871SLDU1MPGZ9NHUl
+hiuiOU3vTN/X/SbZM/Zcz2eahRAOBOc8sXzqcbjQHN/Akzbg
+=acJE
+-----END PGP SIGNATURE-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1_tampered b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1_tampered
new file mode 100644
index 000000000..d165ca5a4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_1_tampered
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB1jSEdHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfDElAv/YEgAwby4DXD3J0ZX
+6iAU2nRjpaUqZ7SAVkOiueeuuxlDw9HnVpIEp/nAOM0OiJrY5h9jQwpLY+p7QmL/
+hWows1fX1PKzpJNATS3bHr+B7qxPkM2N2LKK/ipkknjBXeQIOZyn47nT1nI8/UbA
+UePb5PXDZdIraP6trf5WcsMPxncPntFA4hnPzoVSgvfIYw+Rnjnbsva67grJAe0s
+RJLQatTtPM35n7g3UiNwd09lADPz6u9Ka63GFIf1Prt/mZxsihYq+oJ3xwTudxin
+n2KFCVIw6pCfpXAdYp5CkpbLCBUxyM0TjwphpiVjpa3haqay6iOYcYTubpTcS60S
+Dmz0PE9RCyQq5ycXFPD1UGQKe4C3J/0PzUciT/WzDlxWhM0Wglgez+tYphwDyYHA
+5Q+aSv4FMtKJ/I+RVpgOeF+XApEFwPXB5gw9VtjP9e9uu2T3qEnllrzhfPnNzgY9
+km2tk2WYL2hFdRolQnSfzcimTBaa6GI7dWhMCYe0z1Q0xa1i
+=0YYr
+-----END PGP SIGNATURE-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_2 b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_2
new file mode 100644
index 000000000..056858dbd
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/signed_by_signer_2
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEEVOgKTl31uRUdwFzO+RIKjdyTm/QFAmB1jTEdHHNpZ25lcjJA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQ+RIKjdyTm/REpQv8DJeanIGgPjvV09sP
+BCBTSbHjoV6b5N6vjc15yZhBcWLJe0PAvApdCt0t7E4kTIKOqAz1sABB6YmJjGOZ
+SLL3AToVPk30b07Eq4qgOjEkb3pGlpVFshxEmtrLpbVy068774wacW+PLpvgP0FN
+7v0MlCbdcTBA18MVE3eraA14KL+yfLFkEgdtHSpZ6jzhRcQZexKJRpnS7/Bcah80
+RMZ69/N4HPWTo3ys7ELyeDC80P8B35fcayPLJVsFUgrUQ74UsIUwsaUQwoRNuZYR
+RSizHrJxkLhfYY5CMFTh9Bl1odY/kiXdBGw2Cqk02K3BlwFMsw5mK4CRtoagpGRO
+l1mX58sWjrE+J0tla6MG9aDZiUBdQzFoDGIppex5Bq9ePDcB6CCjR5HO4t7xIg5d
+1/pZly/T0kACgzrbfY3IkBVtL0Fv+PCOJRkmTqw2Lvo3Nhq18TTyZWQLqaZQt/Tc
+dmZVisxh4YbI8wpTRYh3jSlKJ1YYwlj6/QMG7t2UI9B2jg+7
+=8i0n
+-----END PGP SIGNATURE-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/testArtifact b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/testArtifact
new file mode 100644
index 000000000..fd80c131c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/testArtifact
@@ -0,0 +1 @@
+Hello! Please don't modify me because I'm signed for tests and modifying me in any way would make tests fail \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java
index fac04a26a..0b23efdfc 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java
@@ -26,7 +26,7 @@ import org.junit.runners.Suite;
BatchExecuteArtifactRepositoryTest.class, Bug252308.class, Bug265577.class, Bug351944.class,
CompositeArtifactRepositoryTest.class, CorruptedJar.class, FoldersRepositoryTest.class,
JarURLArtifactRepositoryTest.class, LocationTest.class, MD5Tests.class, MirrorSelectorTest.class,
- MirrorRequestTest.class, SimpleArtifactRepositoryTest.class, TransferTest.class
+ MirrorRequestTest.class, SimpleArtifactRepositoryTest.class, TransferTest.class, PGPTest.class
})
public class AllTests {
// test suite
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/PGPTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/PGPTest.java
new file mode 100644
index 000000000..bd2e3e2ad
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/PGPTest.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2021 Red Hat Inc. and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.artifact.repository;
+
+import java.nio.file.Files;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.artifact.repository.MirrorRequest;
+import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
+import org.eclipse.equinox.p2.metadata.Version;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
+import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
+import org.junit.Test;
+
+public class PGPTest extends AbstractProvisioningTest {
+ IArtifactRepository targetRepo = null;
+ IArtifactRepository sourceRepo = null;
+
+ private void loadPGPTestRepo(String repoName) throws Exception {
+ sourceRepo = getArtifactRepositoryManager().loadRepository(
+ getTestData("Test repository for PGP", "testData/pgp/" + repoName).toURI(), new NullProgressMonitor());
+ targetRepo = createArtifactRepository(Files.createTempDirectory(PGPTest.class.getSimpleName()).toUri(),
+ NO_PROPERTIES);
+ }
+
+ @Test
+ public void testAllGood() throws Exception {
+ IStatus mirrorStatus = performMirrorFrom("repoPGPOK");
+ assertOK(mirrorStatus);
+ }
+
+ private IStatus performMirrorFrom(String repoName) throws Exception {
+ loadPGPTestRepo(repoName);
+ ArtifactKey key = new ArtifactKey("osgi.bundle", "blah", Version.create("1.0.0.123456"));
+ MirrorRequest mirrorRequest = new MirrorRequest(key, targetRepo, NO_PROPERTIES, NO_PROPERTIES, getTransport());
+ mirrorRequest.perform(sourceRepo, getMonitor());
+ return mirrorRequest.getResult();
+ }
+
+ @Test
+ public void testMissingPublicKey() throws Exception {
+ IStatus mirrorStatus = performMirrorFrom("repoMissingPublicKey");
+ assertNotOK(mirrorStatus);
+ assertTrue(mirrorStatus.toString().contains("Public key not found"));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ getArtifactRepositoryManager().removeRepository(sourceRepo.getLocation());
+ getArtifactRepositoryManager().removeRepository(targetRepo.getLocation());
+ super.tearDown();
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/artifacts.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/artifacts.xml
new file mode 100644
index 000000000..2ffef6a9f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/artifacts.xml
@@ -0,0 +1,36 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?artifactRepository version='1.1.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - artifacts' type='org.eclipse.equinox.p2.artifact.repository.simpleRepository' version='1'>
+ <properties size='2'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ <!-- See PGPSignatureVerifierTest about this public key-->
+ </properties>
+ <mappings size='3'>
+ <rule filter='(&amp; (classifier=osgi.bundle))' output='${repoUrl}/plugins/${id}_${version}.jar'/>
+ <rule filter='(&amp; (classifier=binary))' output='${repoUrl}/binary/${id}_${version}'/>
+ <rule filter='(&amp; (classifier=org.eclipse.update.feature))' output='${repoUrl}/features/${id}_${version}.jar'/>
+ </mappings>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'>
+ <properties size='1'>
+ <!-- gpg -u signer1@fakeuser.eclipse.org -a -detach-sig plugins/blah_1.0.0.123456.jar -->
+ <property name='pgp.signatures' value='-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB4Bf8dHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfBPuAwAhE4zA7BswKFhEtzm
+DS3EbyRr/U13sV01YxqGtxYDCfrOt8TGVPXJSvo0AVP4vLFc5b+0jtVFoarFJNBu
+xhbVuyC72YdqudNbncSlW6KG5SgeWIM//ThKfl95pOWRWvJEoKJhmDwbDqhZYtL5
+SECegnWGtGx/klFtZihzHYJE/nfSnhySDaz5lCvXFFYRhIbNmNm2Yq7ztCOsN4Ys
+3uN+GEdoXGvv1DFg/xZPvwCOhZGsSQfkl1jmUwVltgKrw9OCFbdfYz7H6dbGWhRu
+2XpuKxPXGavKfpSvssVQIZ6aWi5W6wp5lZAQQddZvYAv3Gi5CZZcUT7ayFJYdD23
+p9jz76G7MXm0f0uNT9B57T72QryokUIEIJYsCb6lNjWUQB4cd0+JesM7sHwweOQ3
+7iTFc+WgVJkP0e695mm1tcvtQHUPbIItYJUsndyLgGInzglxN8+F4U4k8uapydI9
+RmV2NVAifYp8z95Am5AnlG8lqjwrWk5bMbJH82QsQESrNT/h
+=8Vrn
+-----END PGP SIGNATURE-----
+'/>
+ </properties>
+ </artifact>
+ </artifacts>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/content.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/content.xml
new file mode 100644
index 000000000..db8f67ba2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/content.xml
@@ -0,0 +1,49 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?metadataRepository version='1.2.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - metadata' type='org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository' version='1'>
+ <properties size='2'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ </properties>
+ <units size='2'>
+ <unit id='blah' version='1.0.0.123456' singleton='false'>
+ <update id='blah' range='[0.0.0,1.0.0.123456)' severity='0'/>
+ <provides size='4'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.bundle' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.identity' name='blah' version='1.0.0.123456'>
+ <properties size='1'>
+ <property name='type' value='osgi.bundle'/>
+ </properties>
+ </provided>
+ <provided namespace='org.eclipse.equinox.p2.eclipse.type' name='bundle' version='1.0.0'/>
+ </provides>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'/>
+ </artifacts>
+ <touchpoint id='org.eclipse.equinox.p2.osgi' version='1.0.0'/>
+ <touchpointData size='1'>
+ <instructions size='2'>
+ <instruction key='zipped'>
+ true
+ </instruction>
+ <instruction key='manifest'>
+ Bundle-SymbolicName: blah&#xA;Bundle-Version: 1.0.0.qualifier&#xA;
+ </instruction>
+ </instructions>
+ </touchpointData>
+ </unit>
+ <unit id='Category' version='0.0.0'>
+ <properties size='3'>
+ <property name='org.eclipse.equinox.p2.type.category' value='true'/>
+ </properties>
+ <provides size='1'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='Category' version='0.0.0'/>
+ </provides>
+ <requires size='1'>
+ <required namespace='org.eclipse.equinox.p2.iu' name='blah' range='[1.0.0.123456,1.0.0.123456]'/>
+ </requires>
+ <touchpoint id='null' version='0.0.0'/>
+ </unit>
+ </units>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..b9fdcbf2f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/META-INF/MANIFEST.MF
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: blah
+Bundle-Version: 1.0.0.qualifier
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/blah_1.0.0.123456.jar b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/blah_1.0.0.123456.jar
new file mode 100644
index 000000000..9cc7b8da0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/blah_1.0.0.123456.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/blah_1.0.0.123456.jar.asc b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/blah_1.0.0.123456.jar.asc
new file mode 100644
index 000000000..1489f2552
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoMissingPublicKey/plugins/blah_1.0.0.123456.jar.asc
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB4Bf8dHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfBPuAwAhE4zA7BswKFhEtzm
+DS3EbyRr/U13sV01YxqGtxYDCfrOt8TGVPXJSvo0AVP4vLFc5b+0jtVFoarFJNBu
+xhbVuyC72YdqudNbncSlW6KG5SgeWIM//ThKfl95pOWRWvJEoKJhmDwbDqhZYtL5
+SECegnWGtGx/klFtZihzHYJE/nfSnhySDaz5lCvXFFYRhIbNmNm2Yq7ztCOsN4Ys
+3uN+GEdoXGvv1DFg/xZPvwCOhZGsSQfkl1jmUwVltgKrw9OCFbdfYz7H6dbGWhRu
+2XpuKxPXGavKfpSvssVQIZ6aWi5W6wp5lZAQQddZvYAv3Gi5CZZcUT7ayFJYdD23
+p9jz76G7MXm0f0uNT9B57T72QryokUIEIJYsCb6lNjWUQB4cd0+JesM7sHwweOQ3
+7iTFc+WgVJkP0e695mm1tcvtQHUPbIItYJUsndyLgGInzglxN8+F4U4k8uapydI9
+RmV2NVAifYp8z95Am5AnlG8lqjwrWk5bMbJH82QsQESrNT/h
+=8Vrn
+-----END PGP SIGNATURE-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/artifacts.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/artifacts.xml
new file mode 100644
index 000000000..68b911bfa
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/artifacts.xml
@@ -0,0 +1,16 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?artifactRepository version='1.1.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - artifacts' type='org.eclipse.equinox.p2.artifact.repository.simpleRepository' version='1'>
+ <properties size='2'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ </properties>
+ <mappings size='3'>
+ <rule filter='(&amp; (classifier=osgi.bundle))' output='${repoUrl}/plugins/${id}_${version}.jar'/>
+ <rule filter='(&amp; (classifier=binary))' output='${repoUrl}/binary/${id}_${version}'/>
+ <rule filter='(&amp; (classifier=org.eclipse.update.feature))' output='${repoUrl}/features/${id}_${version}.jar'/>
+ </mappings>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'/>
+ </artifacts>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/content.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/content.xml
new file mode 100644
index 000000000..db8f67ba2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/content.xml
@@ -0,0 +1,49 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?metadataRepository version='1.2.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - metadata' type='org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository' version='1'>
+ <properties size='2'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ </properties>
+ <units size='2'>
+ <unit id='blah' version='1.0.0.123456' singleton='false'>
+ <update id='blah' range='[0.0.0,1.0.0.123456)' severity='0'/>
+ <provides size='4'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.bundle' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.identity' name='blah' version='1.0.0.123456'>
+ <properties size='1'>
+ <property name='type' value='osgi.bundle'/>
+ </properties>
+ </provided>
+ <provided namespace='org.eclipse.equinox.p2.eclipse.type' name='bundle' version='1.0.0'/>
+ </provides>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'/>
+ </artifacts>
+ <touchpoint id='org.eclipse.equinox.p2.osgi' version='1.0.0'/>
+ <touchpointData size='1'>
+ <instructions size='2'>
+ <instruction key='zipped'>
+ true
+ </instruction>
+ <instruction key='manifest'>
+ Bundle-SymbolicName: blah&#xA;Bundle-Version: 1.0.0.qualifier&#xA;
+ </instruction>
+ </instructions>
+ </touchpointData>
+ </unit>
+ <unit id='Category' version='0.0.0'>
+ <properties size='3'>
+ <property name='org.eclipse.equinox.p2.type.category' value='true'/>
+ </properties>
+ <provides size='1'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='Category' version='0.0.0'/>
+ </provides>
+ <requires size='1'>
+ <required namespace='org.eclipse.equinox.p2.iu' name='blah' range='[1.0.0.123456,1.0.0.123456]'/>
+ </requires>
+ <touchpoint id='null' version='0.0.0'/>
+ </unit>
+ </units>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..b9fdcbf2f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/META-INF/MANIFEST.MF
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: blah
+Bundle-Version: 1.0.0.qualifier
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/blah_1.0.0.123456.jar b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/blah_1.0.0.123456.jar
new file mode 100644
index 000000000..9cc7b8da0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/blah_1.0.0.123456.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/blah_1.0.0.123456.jar.asc b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/blah_1.0.0.123456.jar.asc
new file mode 100644
index 000000000..1489f2552
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoNoPGP/plugins/blah_1.0.0.123456.jar.asc
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB4Bf8dHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfBPuAwAhE4zA7BswKFhEtzm
+DS3EbyRr/U13sV01YxqGtxYDCfrOt8TGVPXJSvo0AVP4vLFc5b+0jtVFoarFJNBu
+xhbVuyC72YdqudNbncSlW6KG5SgeWIM//ThKfl95pOWRWvJEoKJhmDwbDqhZYtL5
+SECegnWGtGx/klFtZihzHYJE/nfSnhySDaz5lCvXFFYRhIbNmNm2Yq7ztCOsN4Ys
+3uN+GEdoXGvv1DFg/xZPvwCOhZGsSQfkl1jmUwVltgKrw9OCFbdfYz7H6dbGWhRu
+2XpuKxPXGavKfpSvssVQIZ6aWi5W6wp5lZAQQddZvYAv3Gi5CZZcUT7ayFJYdD23
+p9jz76G7MXm0f0uNT9B57T72QryokUIEIJYsCb6lNjWUQB4cd0+JesM7sHwweOQ3
+7iTFc+WgVJkP0e695mm1tcvtQHUPbIItYJUsndyLgGInzglxN8+F4U4k8uapydI9
+RmV2NVAifYp8z95Am5AnlG8lqjwrWk5bMbJH82QsQESrNT/h
+=8Vrn
+-----END PGP SIGNATURE-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/artifacts.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/artifacts.xml
new file mode 100644
index 000000000..4ddbddbb3
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/artifacts.xml
@@ -0,0 +1,78 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?artifactRepository version='1.1.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - artifacts' type='org.eclipse.equinox.p2.artifact.repository.simpleRepository' version='1'>
+ <properties size='3'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ <!-- See PGPSignatureVerifierTest about this public key-->
+ <property name='pgp.publicKeys' value='-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=JYpC
+-----END PGP PUBLIC KEY BLOCK-----
+'/>
+ </properties>
+ <mappings size='3'>
+ <rule filter='(&amp; (classifier=osgi.bundle))' output='${repoUrl}/plugins/${id}_${version}.jar'/>
+ <rule filter='(&amp; (classifier=binary))' output='${repoUrl}/binary/${id}_${version}'/>
+ <rule filter='(&amp; (classifier=org.eclipse.update.feature))' output='${repoUrl}/features/${id}_${version}.jar'/>
+ </mappings>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'>
+ <properties size='1'>
+ <!-- gpg -u signer1@fakeuser.eclipse.org -a -detach-sig plugins/blah_1.0.0.123456.jar -->
+ <property name='pgp.signatures' value='-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB4Bf8dHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfBPuAwAhE4zA7BswKFhEtzm
+DS3EbyRr/U13sV01YxqGtxYDCfrOt8TGVPXJSvo0AVP4vLFc5b+0jtVFoarFJNBu
+xhbVuyC72YdqudNbncSlW6KG5SgeWIM//ThKfl95pOWRWvJEoKJhmDwbDqhZYtL5
+SECegnWGtGx/klFtZihzHYJE/nfSnhySDaz5lCvXFFYRhIbNmNm2Yq7ztCOsN4Ys
+3uN+GEdoXGvv1DFg/xZPvwCOhZGsSQfkl1jmUwVltgKrw9OCFbdfYz7H6dbGWhRu
+2XpuKxPXGavKfpSvssVQIZ6aWi5W6wp5lZAQQddZvYAv3Gi5CZZcUT7ayFJYdD23
+p9jz76G7MXm0f0uNT9B57T72QryokUIEIJYsCb6lNjWUQB4cd0+JesM7sHwweOQ3
+7iTFc+WgVJkP0e695mm1tcvtQHUPbIItYJUsndyLgGInzglxN8+F4U4k8uapydI9
+RmV2NVAifYp8z95Am5AnlG8lqjwrWk5bMbJH82QsQESrNT/h
+=8Vrn
+-----END PGP SIGNATURE-----
+'/>
+ </properties>
+ </artifact>
+ </artifacts>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/content.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/content.xml
new file mode 100644
index 000000000..db8f67ba2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/content.xml
@@ -0,0 +1,49 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?metadataRepository version='1.2.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - metadata' type='org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository' version='1'>
+ <properties size='2'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ </properties>
+ <units size='2'>
+ <unit id='blah' version='1.0.0.123456' singleton='false'>
+ <update id='blah' range='[0.0.0,1.0.0.123456)' severity='0'/>
+ <provides size='4'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.bundle' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.identity' name='blah' version='1.0.0.123456'>
+ <properties size='1'>
+ <property name='type' value='osgi.bundle'/>
+ </properties>
+ </provided>
+ <provided namespace='org.eclipse.equinox.p2.eclipse.type' name='bundle' version='1.0.0'/>
+ </provides>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'/>
+ </artifacts>
+ <touchpoint id='org.eclipse.equinox.p2.osgi' version='1.0.0'/>
+ <touchpointData size='1'>
+ <instructions size='2'>
+ <instruction key='zipped'>
+ true
+ </instruction>
+ <instruction key='manifest'>
+ Bundle-SymbolicName: blah&#xA;Bundle-Version: 1.0.0.qualifier&#xA;
+ </instruction>
+ </instructions>
+ </touchpointData>
+ </unit>
+ <unit id='Category' version='0.0.0'>
+ <properties size='3'>
+ <property name='org.eclipse.equinox.p2.type.category' value='true'/>
+ </properties>
+ <provides size='1'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='Category' version='0.0.0'/>
+ </provides>
+ <requires size='1'>
+ <required namespace='org.eclipse.equinox.p2.iu' name='blah' range='[1.0.0.123456,1.0.0.123456]'/>
+ </requires>
+ <touchpoint id='null' version='0.0.0'/>
+ </unit>
+ </units>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..b9fdcbf2f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/META-INF/MANIFEST.MF
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: blah
+Bundle-Version: 1.0.0.qualifier
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/blah_1.0.0.123456.jar b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/blah_1.0.0.123456.jar
new file mode 100644
index 000000000..9cc7b8da0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/blah_1.0.0.123456.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/blah_1.0.0.123456.jar.asc b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/blah_1.0.0.123456.jar.asc
new file mode 100644
index 000000000..1489f2552
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoPGPOK/plugins/blah_1.0.0.123456.jar.asc
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB4Bf8dHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfBPuAwAhE4zA7BswKFhEtzm
+DS3EbyRr/U13sV01YxqGtxYDCfrOt8TGVPXJSvo0AVP4vLFc5b+0jtVFoarFJNBu
+xhbVuyC72YdqudNbncSlW6KG5SgeWIM//ThKfl95pOWRWvJEoKJhmDwbDqhZYtL5
+SECegnWGtGx/klFtZihzHYJE/nfSnhySDaz5lCvXFFYRhIbNmNm2Yq7ztCOsN4Ys
+3uN+GEdoXGvv1DFg/xZPvwCOhZGsSQfkl1jmUwVltgKrw9OCFbdfYz7H6dbGWhRu
+2XpuKxPXGavKfpSvssVQIZ6aWi5W6wp5lZAQQddZvYAv3Gi5CZZcUT7ayFJYdD23
+p9jz76G7MXm0f0uNT9B57T72QryokUIEIJYsCb6lNjWUQB4cd0+JesM7sHwweOQ3
+7iTFc+WgVJkP0e695mm1tcvtQHUPbIItYJUsndyLgGInzglxN8+F4U4k8uapydI9
+RmV2NVAifYp8z95Am5AnlG8lqjwrWk5bMbJH82QsQESrNT/h
+=8Vrn
+-----END PGP SIGNATURE-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/artifacts.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/artifacts.xml
new file mode 100644
index 000000000..67aec85fb
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/artifacts.xml
@@ -0,0 +1,78 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?artifactRepository version='1.1.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - artifacts' type='org.eclipse.equinox.p2.artifact.repository.simpleRepository' version='1'>
+ <properties size='3'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ <!-- See PGPSignatureVerifierTest about this public key-->
+ <property name='pgp.publicKeys' value='-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=JYpC
+-----END PGP PUBLIC KEY BLOCK-----
+'/>
+ </properties>
+ <mappings size='3'>
+ <rule filter='(&amp; (classifier=osgi.bundle))' output='${repoUrl}/plugins/${id}_${version}.jar'/>
+ <rule filter='(&amp; (classifier=binary))' output='${repoUrl}/binary/${id}_${version}'/>
+ <rule filter='(&amp; (classifier=org.eclipse.update.feature))' output='${repoUrl}/features/${id}_${version}.jar'/>
+ </mappings>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'>
+ <properties size='1'>
+ <!-- gpg -u signer1@fakeuser.eclipse.org -a -detach-sig plugins/blah_1.0.0.123456.jar -->
+ <property name='pgp.signatures' value='-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB1+EodHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfD5LAwAyPl8TBsC0bYZAsRX
+BSGXjlJ+oBKci5VH6bgM/ldnZD5SsYv6PVoxxdOJA2R6S88xxd0DuWivYuG+9aiZ
+w98hx6g0vNH8AWL+yd+l+2yIS8i/MJ57MCvVztexq935fIYU5KGdUNNEjDIrGHQQ
+AR5QWfTiy9EGracG4W6F9twmMOfDlCJ3eRCetp5OTvqBzS2gLom8ECaw7tezYvA/
+09Ok88j7vMI5kL3FO3WzzR+obeYUc19F6602h4cEJs/yOTOj/gz6GCXsAnuYQs1L
+yhjv4Cp4sBnMw+zPX0jFeNHu35mPt8oOFz1NLN85GHO7v3FFXmtwxj8bVBWBQR3R
+Vfi+n8SfR3WO5pYpsqPHZgP95K+W53ere1BZd67cT6uuJDtoDWC6TYPjndm5tnN1
++AzDQO12cC4w2cgIt3ElNYK0T8ADvrmCMPZPRPJ+GeZb0jb871SLDU1MPGZ9NHUl
+hiuiOU3vTN/X/SbZM/Zcz2eahRAOBOc8sXzqcbjQHN/Akzbg
+=acJE
+-----END PGP SIGNATURE-----
+'/>
+ </properties>
+ </artifact>
+ </artifacts>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/content.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/content.xml
new file mode 100644
index 000000000..db8f67ba2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/content.xml
@@ -0,0 +1,49 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?metadataRepository version='1.2.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - metadata' type='org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository' version='1'>
+ <properties size='2'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ </properties>
+ <units size='2'>
+ <unit id='blah' version='1.0.0.123456' singleton='false'>
+ <update id='blah' range='[0.0.0,1.0.0.123456)' severity='0'/>
+ <provides size='4'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.bundle' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.identity' name='blah' version='1.0.0.123456'>
+ <properties size='1'>
+ <property name='type' value='osgi.bundle'/>
+ </properties>
+ </provided>
+ <provided namespace='org.eclipse.equinox.p2.eclipse.type' name='bundle' version='1.0.0'/>
+ </provides>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'/>
+ </artifacts>
+ <touchpoint id='org.eclipse.equinox.p2.osgi' version='1.0.0'/>
+ <touchpointData size='1'>
+ <instructions size='2'>
+ <instruction key='zipped'>
+ true
+ </instruction>
+ <instruction key='manifest'>
+ Bundle-SymbolicName: blah&#xA;Bundle-Version: 1.0.0.qualifier&#xA;
+ </instruction>
+ </instructions>
+ </touchpointData>
+ </unit>
+ <unit id='Category' version='0.0.0'>
+ <properties size='3'>
+ <property name='org.eclipse.equinox.p2.type.category' value='true'/>
+ </properties>
+ <provides size='1'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='Category' version='0.0.0'/>
+ </provides>
+ <requires size='1'>
+ <required namespace='org.eclipse.equinox.p2.iu' name='blah' range='[1.0.0.123456,1.0.0.123456]'/>
+ </requires>
+ <touchpoint id='null' version='0.0.0'/>
+ </unit>
+ </units>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..b9fdcbf2f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/META-INF/MANIFEST.MF
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: blah
+Bundle-Version: 1.0.0.qualifier
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/blah_1.0.0.123456.jar b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/blah_1.0.0.123456.jar
new file mode 100644
index 000000000..9cc7b8da0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/blah_1.0.0.123456.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/blah_1.0.0.123456.jar.asc b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/blah_1.0.0.123456.jar.asc
new file mode 100644
index 000000000..1489f2552
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoSignatureDoesntMatchContent/plugins/blah_1.0.0.123456.jar.asc
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB4Bf8dHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfBPuAwAhE4zA7BswKFhEtzm
+DS3EbyRr/U13sV01YxqGtxYDCfrOt8TGVPXJSvo0AVP4vLFc5b+0jtVFoarFJNBu
+xhbVuyC72YdqudNbncSlW6KG5SgeWIM//ThKfl95pOWRWvJEoKJhmDwbDqhZYtL5
+SECegnWGtGx/klFtZihzHYJE/nfSnhySDaz5lCvXFFYRhIbNmNm2Yq7ztCOsN4Ys
+3uN+GEdoXGvv1DFg/xZPvwCOhZGsSQfkl1jmUwVltgKrw9OCFbdfYz7H6dbGWhRu
+2XpuKxPXGavKfpSvssVQIZ6aWi5W6wp5lZAQQddZvYAv3Gi5CZZcUT7ayFJYdD23
+p9jz76G7MXm0f0uNT9B57T72QryokUIEIJYsCb6lNjWUQB4cd0+JesM7sHwweOQ3
+7iTFc+WgVJkP0e695mm1tcvtQHUPbIItYJUsndyLgGInzglxN8+F4U4k8uapydI9
+RmV2NVAifYp8z95Am5AnlG8lqjwrWk5bMbJH82QsQESrNT/h
+=8Vrn
+-----END PGP SIGNATURE-----
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/artifacts.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/artifacts.xml
new file mode 100644
index 000000000..0d7b0204e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/artifacts.xml
@@ -0,0 +1,78 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?artifactRepository version='1.1.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - artifacts' type='org.eclipse.equinox.p2.artifact.repository.simpleRepository' version='1'>
+ <properties size='3'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ <!-- See PGPSignatureVerifierTest about this public key-->
+ <property name='pgp.publicKeys' value='-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=JYpC
+-----END PGP PUBLIC KEY BLOCK-----
+'/>
+ </properties>
+ <mappings size='3'>
+ <rule filter='(&amp; (classifier=osgi.bundle))' output='${repoUrl}/plugins/${id}_${version}.jar'/>
+ <rule filter='(&amp; (classifier=binary))' output='${repoUrl}/binary/${id}_${version}'/>
+ <rule filter='(&amp; (classifier=org.eclipse.update.feature))' output='${repoUrl}/features/${id}_${version}.jar'/>
+ </mappings>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'>
+ <properties size='1'>
+ <!-- gpg -u signer1@fakeuser.eclipse.org -a -detach-sig plugins/blah_1.0.0.123456.jar -->
+ <property name='pgp.signatures' value='-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB4Bf8dHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfBPuAwAhE4zA7BswKFhEtzm
+DS3EbyRr/U13sV01YxqGtxYDCfrOt8TGVPXJSvo0AVP4vLFc5b+0jtVFoarFJNBu
+xhbVuyC72YdqudNbncSlW6KG5SgeWIM//ThKfl95pOWRWvJEoKJhmDwbDqhZYtL5
+SECegnWG____TAMPERED_____________________________________COsN4Ys
+3uN+GEdoXGvv1DFg/xZPvwCOhZGsSQfkl1jmUwVltgKrw9OCFbdfYz7H6dbGWhRu
+2XpuKxPXGavKfpSvssVQIZ6aWi5W6wp5lZAQQddZvYAv3Gi5CZZcUT7ayFJYdD23
+p9jz76G7MXm0f0uNT9B57T72QryokUIEIJYsCb6lNjWUQB4cd0+JesM7sHwweOQ3
+7iTFc+WgVJkP0e695mm1tcvtQHUPbIItYJUsndyLgGInzglxN8+F4U4k8uapydI9
+RmV2NVAifYp8z95Am5AnlG8lqjwrWk5bMbJH82QsQESrNT/h
+=8Vrn
+-----END PGP SIGNATURE-----
+'/>
+ </properties>
+ </artifact>
+ </artifacts>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/content.xml b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/content.xml
new file mode 100644
index 000000000..db8f67ba2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/content.xml
@@ -0,0 +1,49 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<?metadataRepository version='1.2.0'?>
+<repository name='file:/home/mistria/sandbox/repo/ - metadata' type='org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository' version='1'>
+ <properties size='2'>
+ <property name='p2.timestamp' value='1618433231272'/>
+ <property name='p2.compressed' value='false'/>
+ </properties>
+ <units size='2'>
+ <unit id='blah' version='1.0.0.123456' singleton='false'>
+ <update id='blah' range='[0.0.0,1.0.0.123456)' severity='0'/>
+ <provides size='4'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.bundle' name='blah' version='1.0.0.123456'/>
+ <provided namespace='osgi.identity' name='blah' version='1.0.0.123456'>
+ <properties size='1'>
+ <property name='type' value='osgi.bundle'/>
+ </properties>
+ </provided>
+ <provided namespace='org.eclipse.equinox.p2.eclipse.type' name='bundle' version='1.0.0'/>
+ </provides>
+ <artifacts size='1'>
+ <artifact classifier='osgi.bundle' id='blah' version='1.0.0.123456'/>
+ </artifacts>
+ <touchpoint id='org.eclipse.equinox.p2.osgi' version='1.0.0'/>
+ <touchpointData size='1'>
+ <instructions size='2'>
+ <instruction key='zipped'>
+ true
+ </instruction>
+ <instruction key='manifest'>
+ Bundle-SymbolicName: blah&#xA;Bundle-Version: 1.0.0.qualifier&#xA;
+ </instruction>
+ </instructions>
+ </touchpointData>
+ </unit>
+ <unit id='Category' version='0.0.0'>
+ <properties size='3'>
+ <property name='org.eclipse.equinox.p2.type.category' value='true'/>
+ </properties>
+ <provides size='1'>
+ <provided namespace='org.eclipse.equinox.p2.iu' name='Category' version='0.0.0'/>
+ </provides>
+ <requires size='1'>
+ <required namespace='org.eclipse.equinox.p2.iu' name='blah' range='[1.0.0.123456,1.0.0.123456]'/>
+ </requires>
+ <touchpoint id='null' version='0.0.0'/>
+ </unit>
+ </units>
+</repository>
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..b9fdcbf2f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/META-INF/MANIFEST.MF
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: blah
+Bundle-Version: 1.0.0.qualifier
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/blah_1.0.0.123456.jar b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/blah_1.0.0.123456.jar
new file mode 100644
index 000000000..9cc7b8da0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/blah_1.0.0.123456.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/blah_1.0.0.123456.jar.asc b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/blah_1.0.0.123456.jar.asc
new file mode 100644
index 000000000..1489f2552
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/pgp/repoTamperedInvalidSignature/plugins/blah_1.0.0.123456.jar.asc
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHRBAABCAA7FiEE6ZbGcKp/ZUCb9dtWE5442Q3tEfAFAmB4Bf8dHHNpZ25lcjFA
+ZmFrZXVzZXIuZWNsaXBzZS5vcmcACgkQE5442Q3tEfBPuAwAhE4zA7BswKFhEtzm
+DS3EbyRr/U13sV01YxqGtxYDCfrOt8TGVPXJSvo0AVP4vLFc5b+0jtVFoarFJNBu
+xhbVuyC72YdqudNbncSlW6KG5SgeWIM//ThKfl95pOWRWvJEoKJhmDwbDqhZYtL5
+SECegnWGtGx/klFtZihzHYJE/nfSnhySDaz5lCvXFFYRhIbNmNm2Yq7ztCOsN4Ys
+3uN+GEdoXGvv1DFg/xZPvwCOhZGsSQfkl1jmUwVltgKrw9OCFbdfYz7H6dbGWhRu
+2XpuKxPXGavKfpSvssVQIZ6aWi5W6wp5lZAQQddZvYAv3Gi5CZZcUT7ayFJYdD23
+p9jz76G7MXm0f0uNT9B57T72QryokUIEIJYsCb6lNjWUQB4cd0+JesM7sHwweOQ3
+7iTFc+WgVJkP0e695mm1tcvtQHUPbIItYJUsndyLgGInzglxN8+F4U4k8uapydI9
+RmV2NVAifYp8z95Am5AnlG8lqjwrWk5bMbJH82QsQESrNT/h
+=8Vrn
+-----END PGP SIGNATURE-----

Back to the top