You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2019/08/26 08:38:54 UTC

[sling-org-apache-sling-committer-cli] branch bouncycastle-pgp created (now 1c6ea56)

This is an automated email from the ASF dual-hosted git repository.

radu pushed a change to branch bouncycastle-pgp
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-committer-cli.git.


      at 1c6ea56  experiment with bouncycastle for release signature check

This branch includes the following new commits:

     new 1c6ea56  experiment with bouncycastle for release signature check

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-org-apache-sling-committer-cli] 01/01: experiment with bouncycastle for release signature check

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch bouncycastle-pgp
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-committer-cli.git

commit 1c6ea560ddd03947c0fd0b4e14104a1db13b55d6
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Aug 26 10:38:11 2019 +0200

    experiment with bouncycastle for release signature check
---
 pom.xml                                            |  12 +++
 .../sling/cli/impl/pgp/PGPSignaturesValidator.java | 104 +++++++++++++++++++++
 .../cli/impl/pgp/SignatureVerificationResult.java  |  42 +++++++++
 3 files changed, 158 insertions(+)

diff --git a/pom.xml b/pom.xml
index 4a00263..5fc6e33 100644
--- a/pom.xml
+++ b/pom.xml
@@ -251,6 +251,18 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpg-jdk15on</artifactId>
+            <version>1.62</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <version>1.62</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
         </dependency>
diff --git a/src/main/java/org/apache/sling/cli/impl/pgp/PGPSignaturesValidator.java b/src/main/java/org/apache/sling/cli/impl/pgp/PGPSignaturesValidator.java
new file mode 100644
index 0000000..43db756
--- /dev/null
+++ b/src/main/java/org/apache/sling/cli/impl/pgp/PGPSignaturesValidator.java
@@ -0,0 +1,104 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements.  See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership.  The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License.  You may obtain a copy of the License at
+ ~
+ ~   http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied.  See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.cli.impl.pgp;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.bouncycastle.bcpg.ArmoredInputStream;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPObjectFactory;
+import org.bouncycastle.openpgp.PGPPublicKey;
+import org.bouncycastle.openpgp.PGPPublicKeyRing;
+import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.PGPSignatureList;
+import org.bouncycastle.openpgp.PGPUtil;
+import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
+import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
+import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
+import org.osgi.service.component.annotations.Component;
+
+@Component(service = PGPSignaturesValidator.class)
+public class PGPSignaturesValidator {
+
+    private static final String KEYS_FILE = "/tmp/sling-keys.asc";
+
+    public SignatureVerificationResult verify(File artifact, File signatureFile) {
+        PGPPublicKeyRingCollection keyRing = readKeyRing();
+        try (
+                InputStream file = new FileInputStream(artifact);
+                InputStream signature = new FileInputStream(signatureFile)
+        ) {
+            InputStream sigInputStream = PGPUtil.getDecoderStream(signature);
+            PGPObjectFactory pgpObjectFactory = new PGPObjectFactory(sigInputStream, new BcKeyFingerprintCalculator());
+            PGPSignatureList sigList = (PGPSignatureList) pgpObjectFactory.nextObject();
+            PGPSignature pgpSignature = sigList.get(0);
+            PGPPublicKey key = keyRing.getPublicKey(pgpSignature.getKeyID());
+            if (key == null) {
+                throw new IllegalStateException(String.format("Signature %s was not generated with any of the known keys.",
+                        signatureFile.getName()));
+            }
+            pgpSignature.init(new BcPGPContentVerifierBuilderProvider(), key);
+            try (InputStream inArtifact = new BufferedInputStream(file)) {
+                int t;
+                while ((t = inArtifact.read()) >= 0) {
+                    pgpSignature.update((byte) t);
+                }
+            }
+            return new SignatureVerificationResult(pgpSignature.verify(), key);
+        } catch (PGPException | IOException e) {
+            throw new IllegalStateException(String.format("Unable to verify signature %s.", signatureFile.getName()), e);
+        }
+    }
+
+    private PGPPublicKeyRingCollection readKeyRing() {
+        File keysFile = new File(KEYS_FILE);
+        if (!keysFile.exists()) {
+            throw new IllegalStateException(String.format("Sling keys file does not exist at %s.", KEYS_FILE));
+        }
+        try (InputStream in = new FileInputStream(keysFile)) {
+            InputStream bouncyIn = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in);
+            if (bouncyIn instanceof ArmoredInputStream) {
+                ArmoredInputStream as = (ArmoredInputStream) bouncyIn;
+                List<PGPPublicKeyRing> keyRings = new ArrayList<>();
+                while (!as.isEndOfStream()) {
+                    PGPPublicKeyRingCollection collection = new PGPPublicKeyRingCollection(as, new JcaKeyFingerprintCalculator());
+                    Iterator<PGPPublicKeyRing> readKeyRings = collection.getKeyRings();
+                    while (readKeyRings.hasNext()) {
+                        PGPPublicKeyRing keyRing = readKeyRings.next();
+                        keyRings.add(keyRing);
+                    }
+                }
+                if (!keyRings.isEmpty()) {
+                    return new PGPPublicKeyRingCollection(keyRings);
+                }
+            }
+            throw new IllegalStateException(String.format("Sling keys file from %s does not contain any keys.", KEYS_FILE));
+        } catch (IOException | PGPException e) {
+            throw new IllegalStateException(String.format("Cannot read Sling keys file at %s.", KEYS_FILE), e);
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/cli/impl/pgp/SignatureVerificationResult.java b/src/main/java/org/apache/sling/cli/impl/pgp/SignatureVerificationResult.java
new file mode 100644
index 0000000..d724596
--- /dev/null
+++ b/src/main/java/org/apache/sling/cli/impl/pgp/SignatureVerificationResult.java
@@ -0,0 +1,42 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements.  See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership.  The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License.  You may obtain a copy of the License at
+ ~
+ ~   http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied.  See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.cli.impl.pgp;
+
+import org.bouncycastle.openpgp.PGPPublicKey;
+import org.jetbrains.annotations.NotNull;
+
+public class SignatureVerificationResult {
+
+    private boolean valid;
+    private PGPPublicKey key;
+
+    public SignatureVerificationResult(boolean valid, @NotNull PGPPublicKey key) {
+        this.key = key;
+        this.valid = valid;
+    }
+
+    public boolean isValid() {
+        return valid;
+    }
+
+    @NotNull
+    public PGPPublicKey getKey() {
+        return key;
+    }
+}