/*
 * Copyright 2019 the original author or authors.
 *
 * Licensed 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.gradle.security.internal;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPObjectFactory;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureList;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider;
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
import org.gradle.api.UncheckedIOException;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;

public class SecuritySupport {
    private static final int BUFFER = 4096;

    static {
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            Security.setProperty("crypto.policy", "unlimited");
            Security.addProvider(new BouncyCastleProvider());
        }
    }

    public static void assertInitialized() {
    }

    public static boolean verify(File file, PGPSignature signature, PGPPublicKey publicKey) throws PGPException {
        signature.init(createContentVerifier(), publicKey);
        byte[] buffer = new byte[BUFFER];
        int len;
        try (InputStream in = new BufferedInputStream(new FileInputStream(file))) {
            while ((len = in.read(buffer)) >= 0) {
                signature.update(buffer, 0, len);
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
        return signature.verify();
    }

    private static PGPContentVerifierBuilderProvider createContentVerifier() {
        return new BcPGPContentVerifierBuilderProvider();
    }

    public static PGPSignatureList readSignatures(File file) {
        try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) {
            return readSignatures(stream);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static PGPSignatureList readSignatures(InputStream source) {
        try (InputStream stream = source;
             InputStream decoderStream = PGPUtil.getDecoderStream(stream)) {
            PGPObjectFactory objectFactory = new PGPObjectFactory(
                decoderStream, new BcKeyFingerprintCalculator());
            return (PGPSignatureList) objectFactory.nextObject();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public static String toHexString(long key) {
        return String.format("%016x", key).trim();
    }

    public static List<PGPPublicKeyRing> loadKeyRingFile(File keyringFile) throws IOException {
        List<PGPPublicKeyRing> existingRings = new ArrayList<>();
        // load existing keys from keyring before
        try (InputStream ins = new BufferedInputStream(new FileInputStream(keyringFile))) {
            PGPObjectFactory objectFactory = new PGPObjectFactory(
                PGPUtil.getDecoderStream(ins), new BcKeyFingerprintCalculator());
            Object o;
            while ((o = objectFactory.nextObject()) != null) {
                if (o instanceof PGPPublicKeyRing) {
                    existingRings.add((PGPPublicKeyRing) o);
                }
            }
        }
        return existingRings;
    }
}

@@ -1308,16 +1308,93 @@
 ception;
+%0Aimport org.gradle.api.logging.Logger;%0Aimport org.gradle.api.logging.Logging;
 %0A%0Aimport
@@ -1646,16 +1646,100 @@
 pport %7B%0A
+    private static final Logger LOGGER = Logging.getLogger(SecuritySupport.class);%0A%0A
     priv
@@ -4134,16 +4134,38 @@
 ject o;%0A
+            try %7B%0A    
         
@@ -4231,24 +4231,28 @@
             
+    
 if (o instan
@@ -4296,16 +4296,20 @@
         
+ 
+   
 existing
@@ -4349,33 +4349,218 @@
                 
-%7D
+    %7D%0A                %7D%0A            %7D catch (IOException e) %7B%0A                LOGGER.warn(%22Error while reading the keyring file. %7B%7D keys read: %7B%7D%22, existingRings.size(), e.getMessage());
 %0A            %7D%0A 

Add safety around reading of keyring file