/*
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.security.jarsigner;

import com.sun.jarsigner.ContentSigner;
import com.sun.jarsigner.ContentSignerParameters;
import sun.security.tools.PathList;
import sun.security.tools.jarsigner.TimestampedSigner;
import sun.security.util.ManifestDigester;
import sun.security.util.SignatureFileVerifier;
import sun.security.x509.AlgorithmId;

import java.io.*;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.*;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * An immutable utility class to sign a jar file.
 * <p>
 * A caller creates a {@code JarSigner.Builder} object, (optionally) sets
 * some parameters, and calls {@link JarSigner.Builder#build build} to create
 * a {@code JarSigner} object. This {@code JarSigner} object can then
 * be used to sign a jar file.
 * <p>
 * Unless otherwise stated, calling a method of {@code JarSigner} or
 * {@code JarSigner.Builder} with a null argument will throw
 * a {@link NullPointerException}.
 * <p>
 * Example:
 * <pre>
 * JarSigner signer = new JarSigner.Builder(key, certPath)
 *         .digestAlgorithm("SHA-1")
 *         .signatureAlgorithm("SHA1withDSA")
 *         .build();
 * try (ZipFile in = new ZipFile(inputFile);
 *         FileOutputStream out = new FileOutputStream(outputFile)) {
 *     signer.sign(in, out);
 * }
 * </pre>
 *
 * @since 1.9
 */
public final class JarSigner {

    /**
     * A mutable builder class that can create an immutable {@code JarSigner}
     * from various signing-related parameters.
     *
     * @since 1.9
     */
    public static class Builder {

        // Signer materials:
        final PrivateKey privateKey;
        final X509Certificate[] certChain;

        // JarSigner options:
        // Support multiple digestalg internally. Can be null, but not empty
        String[] digestalg;
        String sigalg;
        // Precisely should be one provider for each digestalg, maybe later
        Provider digestProvider;
        Provider sigProvider;
        URI tsaUrl;
        String signerName;
        BiConsumer<String,String> handler;

        // Implementation-specific properties:
        String tSAPolicyID;
        String tSADigestAlg;
        boolean signManifest = true;
        boolean externalSF = true;
        String altSignerPath;
        String altSigner;

        /**
         * Creates a {@code JarSigner.Builder} object with
         * a {@link KeyStore.PrivateKeyEntry} object.
         *
         * @param entry the {@link KeyStore.PrivateKeyEntry} of the signer.
         */
        public Builder(KeyStore.PrivateKeyEntry entry) {
            this.privateKey = entry.getPrivateKey();
            try {
                // called internally, no need to clone
                Certificate[] certs = entry.getCertificateChain();
                this.certChain = Arrays.copyOf(certs, certs.length,
                        X509Certificate[].class);
            } catch (ArrayStoreException ase) {
                // Wrong type, not X509Certificate. Won't document.
                throw new IllegalArgumentException(
                        "Entry does not contain X509Certificate");
            }
        }

        /**
         * Creates a {@code JarSigner.Builder} object with a private key and
         * a certification path.
         *
         * @param privateKey the private key of the signer.
         * @param certPath the certification path of the signer.
         * @throws IllegalArgumentException if {@code certPath} is empty, or
         *      the {@code privateKey} algorithm does not match the algorithm
         *      of the {@code PublicKey} in the end entity certificate
         *      (the first certificate in {@code certPath}).
         */
        public Builder(PrivateKey privateKey, CertPath certPath) {
            List<? extends Certificate> certs = certPath.getCertificates();
            if (certs.isEmpty()) {
                throw new IllegalArgumentException("certPath cannot be empty");
            }
            if (!privateKey.getAlgorithm().equals
                    (certs.get(0).getPublicKey().getAlgorithm())) {
                throw new IllegalArgumentException
                        ("private key algorithm does not match " +
                                "algorithm of public key in end entity " +
                                "certificate (the 1st in certPath)");
            }
            this.privateKey = privateKey;
            try {
                this.certChain = certs.toArray(new X509Certificate[certs.size()]);
            } catch (ArrayStoreException ase) {
                // Wrong type, not X509Certificate.
                throw new IllegalArgumentException(
                        "Entry does not contain X509Certificate");
            }
        }

        /**
         * Sets the digest algorithm. If no digest algorithm is specified,
         * the default algorithm returned by {@link #getDefaultDigestAlgorithm}
         * will be used.
         *
         * @param algorithm the standard name of the algorithm. See
         *      the {@code MessageDigest} section in the <a href=
         *      "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
         *      Java Cryptography Architecture Standard Algorithm Name
         *      Documentation</a> for information about standard algorithm names.
         * @return the {@code JarSigner.Builder} itself.
         * @throws NoSuchAlgorithmException if {@code algorithm} is not available.
         */
        public Builder digestAlgorithm(String algorithm) throws NoSuchAlgorithmException {
            MessageDigest.getInstance(Objects.requireNonNull(algorithm));
            this.digestalg = new String[]{algorithm};
            this.digestProvider = null;
            return this;
        }

        /**
         * Sets the digest algorithm from the specified provider.
         * If no digest algorithm is specified, the default algorithm
         * returned by {@link #getDefaultDigestAlgorithm} will be used.
         *
         * @param algorithm the standard name of the algorithm. See
         *      the {@code MessageDigest} section in the <a href=
         *      "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
         *      Java Cryptography Architecture Standard Algorithm Name
         *      Documentation</a> for information about standard algorithm names.
         * @param provider the provider.
         * @return the {@code JarSigner.Builder} itself.
         * @throws NoSuchAlgorithmException if {@code algorithm} is not
         *      available in the specified provider.
         */
        public Builder digestAlgorithm(String algorithm, Provider provider)
                throws NoSuchAlgorithmException {
            MessageDigest.getInstance(
                    Objects.requireNonNull(algorithm),
                    Objects.requireNonNull(provider));
            this.digestalg = new String[]{algorithm};
            this.digestProvider = provider;
            return this;
        }

        /**
         * Sets the signature algorithm. If no signature algorithm
         * is specified, the default signature algorithm returned by
         * {@link #getDefaultSignatureAlgorithm} for the private key
         * will be used.
         *
         * @param algorithm the standard name of the algorithm. See
         *      the {@code Signature} section in the <a href=
         *      "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
         *      Java Cryptography Architecture Standard Algorithm Name
         *      Documentation</a> for information about standard algorithm names.
         * @return the {@code JarSigner.Builder} itself.
         * @throws NoSuchAlgorithmException if {@code algorithm} is not available.
         * @throws IllegalArgumentException if {@code algorithm} is not
         *      compatible with the algorithm of the signer's private key.
         */
        public Builder signatureAlgorithm(String algorithm)
                throws NoSuchAlgorithmException {
            // Check availability
            Signature.getInstance(Objects.requireNonNull(algorithm));
            AlgorithmId.checkKeyAndSigAlgMatch(
                    privateKey.getAlgorithm(), algorithm);
            this.sigalg = algorithm;
            this.sigProvider = null;
            return this;
        }

        /**
         * Sets the signature algorithm from the specified provider. If no
         * signature algorithm is specified, the default signature algorithm
         * returned by {@link #getDefaultSignatureAlgorithm} for the private
         * key will be used.
         *
         * @param algorithm the standard name of the algorithm. See
         *      the {@code Signature} section in the <a href=
         *      "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
         *      Java Cryptography Architecture Standard Algorithm Name
         *      Documentation</a> for information about standard algorithm names.
         * @param provider  the provider.
         * @return the {@code JarSigner.Builder} itself.
         * @throws NoSuchAlgorithmException if {@code algorithm} is not
         *      available in the specified provider.
         * @throws IllegalArgumentException if {@code algorithm} is not
         *      compatible with the algorithm of the signer's private key.
         */
        public Builder signatureAlgorithm(String algorithm, Provider provider)
                throws NoSuchAlgorithmException {
            // Check availability
            Signature.getInstance(
                    Objects.requireNonNull(algorithm),
                    Objects.requireNonNull(provider));
            AlgorithmId.checkKeyAndSigAlgMatch(
                    privateKey.getAlgorithm(), algorithm);
            this.sigalg = algorithm;
            this.sigProvider = provider;
            return this;
        }

        /**
         * Sets the URI of the Time Stamping Authority (TSA).
         *
         * @param uri the URI.
         * @return the {@code JarSigner.Builder} itself.
         */
        public Builder tsa(URI uri) {
            this.tsaUrl = Objects.requireNonNull(uri);
            return this;
        }

        /**
         * Sets the signer name. The name will be used as the base name for
         * the signature files. All lowercase characters will be converted to
         * uppercase for signature file names. If a signer name is not
         * specified, the string "SIGNER" will be used.
         *
         * @param name the signer name.
         * @return the {@code JarSigner.Builder} itself.
         * @throws IllegalArgumentException if {@code name} is empty or has
         *      a size bigger than 8, or it contains characters not from the
         *      set "a-zA-Z0-9_-".
         */
        public Builder signerName(String name) {
            if (name.isEmpty() || name.length() > 8) {
                throw new IllegalArgumentException("Name too long");
            }

            name = name.toUpperCase(Locale.ENGLISH);

            for (int j = 0; j < name.length(); j++) {
                char c = name.charAt(j);
                if (!
                        ((c >= 'A' && c <= 'Z') ||
                                (c >= '0' && c <= '9') ||
                                (c == '-') ||
                                (c == '_'))) {
                    throw new IllegalArgumentException(
                            "Invalid characters in name");
                }
            }
            this.signerName = name;
            return this;
        }

        /**
         * Sets en event handler that will be triggered when a {@link JarEntry}
         * is to be added, signed, or updated during the signing process.
         * <p>
         * The handler can be used to display signing progress. The first
         * argument of the handler can be "adding", "signing", or "updating",
         * and the second argument is the name of the {@link JarEntry}
         * being processed.
         *
         * @param handler the event handler.
         * @return the {@code JarSigner.Builder} itself.
         */
        public Builder eventHandler(BiConsumer<String,String> handler) {
            this.handler = Objects.requireNonNull(handler);
            return this;
        }

        /**
         * Sets an additional implementation-specific property indicated by
         * the specified key.
         *
         * @implNote This implementation supports the following properties:
         * <ul>
         * <li>"tsaDigestAlg": algorithm of digest data in the timestamping
         * request. The default value is the same as the result of
         * {@link #getDefaultDigestAlgorithm}.
         * <li>"tsaPolicyId": TSAPolicyID for Timestamping Authority.
         * No default value.
         * <li>"internalsf": "true" if the .SF file is included inside the
         * signature block, "false" otherwise. Default "false".
         * <li>"sectionsonly": "true" if the .SF file only contains the hash
         * value for each section of the manifest and not for the whole
         * manifest, "false" otherwise. Default "false".
         * </ul>
         * All property names are case-insensitive.
         *
         * @param key the name of the property.
         * @param value the value of the property.
         * @return the {@code JarSigner.Builder} itself.
         * @throws UnsupportedOperationException if the key is not supported
         *      by this implementation.
         * @throws IllegalArgumentException if the value is not accepted as
         *      a legal value for this key.
         */
        public Builder setProperty(String key, String value) {
            Objects.requireNonNull(key);
            Objects.requireNonNull(value);
            switch (key.toLowerCase(Locale.US)) {
                case "tsadigestalg":
                    try {
                        MessageDigest.getInstance(value);
                    } catch (NoSuchAlgorithmException nsae) {
                        throw new IllegalArgumentException(
                                "Invalid tsadigestalg", nsae);
                    }
                    this.tSADigestAlg = value;
                    break;
                case "tsapolicyid":
                    this.tSAPolicyID = value;
                    break;
                case "internalsf":
                    switch (value) {
                        case "true":
                            externalSF = false;
                            break;
                        case "false":
                            externalSF = true;
                            break;
                        default:
                            throw new IllegalArgumentException(
                                "Invalid internalsf value");
                    }
                    break;
                case "sectionsonly":
                    switch (value) {
                        case "true":
                            signManifest = false;
                            break;
                        case "false":
                            signManifest = true;
                            break;
                        default:
                            throw new IllegalArgumentException(
                                "Invalid signManifest value");
                    }
                    break;
                case "altsignerpath":
                    altSignerPath = value;
                    break;
                case "altsigner":
                    altSigner = value;
                    break;
                default:
                    throw new UnsupportedOperationException(
                            "Unsupported key " + key);
            }
            return this;
        }

        /**
         * Gets the default digest algorithm.
         *
         * @implNote This implementation returns "SHA-256". The value may
         * change in the future.
         *
         * @return the default digest algorithm.
         */
        public static String getDefaultDigestAlgorithm() {
            return "SHA-256";
        }

        /**
         * Gets the default signature algorithm for a private key.
         * For example, SHA256withRSA for a 2048-bit RSA key, and
         * SHA384withECDSA for a 384-bit EC key.
         *
         * @implNote This implementation makes use of comparable strengths
         * as defined in Tables 2 and 3 of NIST SP 800-57 Part 1-Rev.3.
         * Specifically, if a DSA or RSA key with a key size greater than 7680
         * bits, or an EC key with a key size greater than or equal to 512 bits,
         * SHA-512 will be used as the hash function for the signature.
         * If a DSA or RSA key has a key size greater than 3072 bits, or an
         * EC key has a key size greater than or equal to 384 bits, SHA-384 will
         * be used. Otherwise, SHA-256 will be used. The value may
         * change in the future.
         *
         * @param key the private key.
         * @return the default signature algorithm. Returns null if a default
         *      signature algorithm cannot be found. In this case,
         *      {@link #signatureAlgorithm} must be called to specify a
         *      signature algorithm. Otherwise, the {@link #build} method
         *      will throw an {@link IllegalArgumentException}.
         */
        public static String getDefaultSignatureAlgorithm(PrivateKey key) {
            return AlgorithmId.getDefaultSigAlgForKey(Objects.requireNonNull(key));
        }

        /**
         * Builds a {@code JarSigner} object from the parameters set by the
         * setter methods.
         * <p>
         * This method does not modify internal state of this {@code Builder}
         * object and can be called multiple times to generate multiple
         * {@code JarSigner} objects. After this method is called, calling
         * any method on this {@code Builder} will have no effect on
         * the newly built {@code JarSigner} object.
         *
         * @return the {@code JarSigner} object.
         * @throws IllegalArgumentException if a signature algorithm is not
         *      set and cannot be derived from the private key using the
         *      {@link #getDefaultSignatureAlgorithm} method.
         */
        public JarSigner build() {
            return new JarSigner(this);
        }
    }

    private static final String META_INF = "META-INF/";

    // All fields in Builder are duplicated here as final. Those not
    // provided but has a default value will be filled with default value.

    // Precisely, a final array field can still be modified if only
    // reference is copied, no clone is done because we are concerned about
    // casual change instead of malicious attack.

    // Signer materials:
    private final PrivateKey privateKey;
    private final X509Certificate[] certChain;

    // JarSigner options:
    private final String[] digestalg;
    private final String sigalg;
    private final Provider digestProvider;
    private final Provider sigProvider;
    private final URI tsaUrl;
    private final String signerName;
    private final BiConsumer<String,String> handler;

    // Implementation-specific properties:
    private final String tSAPolicyID;
    private final String tSADigestAlg;
    private final boolean signManifest; // "sign" the whole manifest
    private final boolean externalSF; // leave the .SF out of the PKCS7 block
    private final String altSignerPath;
    private final String altSigner;

    private JarSigner(JarSigner.Builder builder) {

        this.privateKey = builder.privateKey;
        this.certChain = builder.certChain;
        if (builder.digestalg != null) {
            // No need to clone because builder only accepts one alg now
            this.digestalg = builder.digestalg;
        } else {
            this.digestalg = new String[] {
                    Builder.getDefaultDigestAlgorithm() };
        }
        this.digestProvider = builder.digestProvider;
        if (builder.sigalg != null) {
            this.sigalg = builder.sigalg;
        } else {
            this.sigalg = JarSigner.Builder
                    .getDefaultSignatureAlgorithm(privateKey);
            if (this.sigalg == null) {
                throw new IllegalArgumentException(
                        "No signature alg for " + privateKey.getAlgorithm());
            }
        }
        this.sigProvider = builder.sigProvider;
        this.tsaUrl = builder.tsaUrl;

        if (builder.signerName == null) {
            this.signerName = "SIGNER";
        } else {
            this.signerName = builder.signerName;
        }
        this.handler = builder.handler;

        if (builder.tSADigestAlg != null) {
            this.tSADigestAlg = builder.tSADigestAlg;
        } else {
            this.tSADigestAlg = Builder.getDefaultDigestAlgorithm();
        }
        this.tSAPolicyID = builder.tSAPolicyID;
        this.signManifest = builder.signManifest;
        this.externalSF = builder.externalSF;
        this.altSigner = builder.altSigner;
        this.altSignerPath = builder.altSignerPath;
    }

    /**
     * Signs a file into an {@link OutputStream}. This method will not close
     * {@code file} or {@code os}.
     *
     * @param file the file to sign.
     * @param os the output stream.
     * @throws JarSignerException if the signing fails.
     */
    public void sign(ZipFile file, OutputStream os) {
        try {
            sign0(Objects.requireNonNull(file),
                    Objects.requireNonNull(os));
        } catch (SocketTimeoutException | CertificateException e) {
            // CertificateException is thrown when the received cert from TSA
            // has no id-kp-timeStamping in its Extended Key Usages extension.
            throw new JarSignerException("Error applying timestamp", e);
        } catch (IOException ioe) {
            throw new JarSignerException("I/O error", ioe);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new JarSignerException("Error in signer materials", e);
        } catch (SignatureException se) {
            throw new JarSignerException("Error creating signature", se);
        }
    }

    /**
     * Returns the digest algorithm for this {@code JarSigner}.
     * <p>
     * The return value is never null.
     *
     * @return the digest algorithm.
     */
    public String getDigestAlgorithm() {
        return digestalg[0];
    }

    /**
     * Returns the signature algorithm for this {@code JarSigner}.
     * <p>
     * The return value is never null.
     *
     * @return the signature algorithm.
     */
    public String getSignatureAlgorithm() {
        return sigalg;
    }

    /**
     * Returns the URI of the Time Stamping Authority (TSA).
     *
     * @return the URI of the TSA.
     */
    public URI getTsa() {
        return tsaUrl;
    }

    /**
     * Returns the signer name of this {@code JarSigner}.
     * <p>
     * The return value is never null.
     *
     * @return the signer name.
     */
    public String getSignerName() {
        return signerName;
    }

    /**
     * Returns the value of an additional implementation-specific property
     * indicated by the specified key. If a property is not set but has a
     * default value, the default value will be returned.
     *
     * @implNote See {@link JarSigner.Builder#setProperty} for a list of
     * properties this implementation supports. All property names are
     * case-insensitive.
     *
     * @param key the name of the property.
     * @return the value for the property.
     * @throws UnsupportedOperationException if the key is not supported
     *      by this implementation.
     */
    public String getProperty(String key) {
        Objects.requireNonNull(key);
        switch (key.toLowerCase(Locale.US)) {
            case "tsadigestalg":
                return tSADigestAlg;
            case "tsapolicyid":
                return tSAPolicyID;
            case "internalsf":
                return Boolean.toString(!externalSF);
            case "sectionsonly":
                return Boolean.toString(!signManifest);
            case "altsignerpath":
                return altSignerPath;
            case "altsigner":
                return altSigner;
            default:
                throw new UnsupportedOperationException(
                        "Unsupported key " + key);
        }
    }

    private void sign0(ZipFile zipFile, OutputStream os)
            throws IOException, CertificateException, NoSuchAlgorithmException,
            SignatureException, InvalidKeyException {
        MessageDigest[] digests;
        try {
            digests = new MessageDigest[digestalg.length];
            for (int i = 0; i < digestalg.length; i++) {
                if (digestProvider == null) {
                    digests[i] = MessageDigest.getInstance(digestalg[i]);
                } else {
                    digests[i] = MessageDigest.getInstance(
                            digestalg[i], digestProvider);
                }
            }
        } catch (NoSuchAlgorithmException asae) {
            // Should not happen. User provided alg were checked, and default
            // alg should always be available.
            throw new AssertionError(asae);
        }

        PrintStream ps = new PrintStream(os);
        ZipOutputStream zos = new ZipOutputStream(ps);

        Manifest manifest = new Manifest();
        Map<String, Attributes> mfEntries = manifest.getEntries();

        // The Attributes of manifest before updating
        Attributes oldAttr = null;

        boolean mfModified = false;
        boolean mfCreated = false;
        byte[] mfRawBytes = null;

        // Check if manifest exists
        ZipEntry mfFile;
        if ((mfFile = getManifestFile(zipFile)) != null) {
            // Manifest exists. Read its raw bytes.
            mfRawBytes = zipFile.getInputStream(mfFile).readAllBytes();
            manifest.read(new ByteArrayInputStream(mfRawBytes));
            oldAttr = (Attributes) (manifest.getMainAttributes().clone());
        } else {
            // Create new manifest
            Attributes mattr = manifest.getMainAttributes();
            mattr.putValue(Attributes.Name.MANIFEST_VERSION.toString(),
                    "1.0");
            String javaVendor = System.getProperty("java.vendor");
            String jdkVersion = System.getProperty("java.version");
            mattr.putValue("Created-By", jdkVersion + " (" + javaVendor
                    + ")");
            mfFile = new ZipEntry(JarFile.MANIFEST_NAME);
            mfCreated = true;
        }

        /*
         * For each entry in jar
         * (except for signature-related META-INF entries),
         * do the following:
         *
         * - if entry is not contained in manifest, add it to manifest;
         * - if entry is contained in manifest, calculate its hash and
         *   compare it with the one in the manifest; if they are
         *   different, replace the hash in the manifest with the newly
         *   generated one. (This may invalidate existing signatures!)
         */
        Vector<ZipEntry> mfFiles = new Vector<>();

        boolean wasSigned = false;

        for (Enumeration<? extends ZipEntry> enum_ = zipFile.entries();
             enum_.hasMoreElements(); ) {
            ZipEntry ze = enum_.nextElement();

            if (ze.getName().startsWith(META_INF)) {
                // Store META-INF files in vector, so they can be written
                // out first
                mfFiles.addElement(ze);

                if (SignatureFileVerifier.isBlockOrSF(
                        ze.getName().toUpperCase(Locale.ENGLISH))) {
                    wasSigned = true;
                }

                if (SignatureFileVerifier.isSigningRelated(ze.getName())) {
                    // ignore signature-related and manifest files
                    continue;
                }
            }

            if (manifest.getAttributes(ze.getName()) != null) {
                // jar entry is contained in manifest, check and
                // possibly update its digest attributes
                if (updateDigests(ze, zipFile, digests,
                        manifest)) {
                    mfModified = true;
                }
            } else if (!ze.isDirectory()) {
                // Add entry to manifest
                Attributes attrs = getDigestAttributes(ze, zipFile, digests);
                mfEntries.put(ze.getName(), attrs);
                mfModified = true;
            }
        }

        // Recalculate the manifest raw bytes if necessary
        if (mfModified) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            manifest.write(baos);
            if (wasSigned) {
                byte[] newBytes = baos.toByteArray();
                if (mfRawBytes != null
                        && oldAttr.equals(manifest.getMainAttributes())) {

                    /*
                     * Note:
                     *
                     * The Attributes object is based on HashMap and can handle
                     * continuation columns. Therefore, even if the contents are
                     * not changed (in a Map view), the bytes that it write()
                     * may be different from the original bytes that it read()
                     * from. Since the signature on the main attributes is based
                     * on raw bytes, we must retain the exact bytes.
                     */

                    int newPos = findHeaderEnd(newBytes);
                    int oldPos = findHeaderEnd(mfRawBytes);

                    if (newPos == oldPos) {
                        System.arraycopy(mfRawBytes, 0, newBytes, 0, oldPos);
                    } else {
                        // cat oldHead newTail > newBytes
                        byte[] lastBytes = new byte[oldPos +
                                newBytes.length - newPos];
                        System.arraycopy(mfRawBytes, 0, lastBytes, 0, oldPos);
                        System.arraycopy(newBytes, newPos, lastBytes, oldPos,
                                newBytes.length - newPos);
                        newBytes = lastBytes;
                    }
                }
                mfRawBytes = newBytes;
            } else {
                mfRawBytes = baos.toByteArray();
            }
        }

        // Write out the manifest
        if (mfModified) {
            // manifest file has new length
            mfFile = new ZipEntry(JarFile.MANIFEST_NAME);
        }
        if (handler != null) {
            if (mfCreated) {
                handler.accept("adding", mfFile.getName());
            } else if (mfModified) {
                handler.accept("updating", mfFile.getName());
            }
        }

        zos.putNextEntry(mfFile);
        zos.write(mfRawBytes);

        // Calculate SignatureFile (".SF") and SignatureBlockFile
        ManifestDigester manDig = new ManifestDigester(mfRawBytes);
        SignatureFile sf = new SignatureFile(digests, manifest, manDig,
                signerName, signManifest);

        byte[] block;

        Signature signer;
        if (sigProvider == null ) {
            signer = Signature.getInstance(sigalg);
        } else {
            signer = Signature.getInstance(sigalg, sigProvider);
        }
        signer.initSign(privateKey);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        sf.write(baos);

        byte[] content = baos.toByteArray();

        signer.update(content);
        byte[] signature = signer.sign();

        @SuppressWarnings("deprecation")
        ContentSigner signingMechanism = null;
        if (altSigner != null) {
            signingMechanism = loadSigningMechanism(altSigner,
                    altSignerPath);
        }

        @SuppressWarnings("deprecation")
        ContentSignerParameters params =
                new JarSignerParameters(null, tsaUrl, tSAPolicyID,
                        tSADigestAlg, signature,
                        signer.getAlgorithm(), certChain, content, zipFile);
        block = sf.generateBlock(params, externalSF, signingMechanism);

        String sfFilename = sf.getMetaName();
        String bkFilename = sf.getBlockName(privateKey);

        ZipEntry sfFile = new ZipEntry(sfFilename);
        ZipEntry bkFile = new ZipEntry(bkFilename);

        long time = System.currentTimeMillis();
        sfFile.setTime(time);
        bkFile.setTime(time);

        // signature file
        zos.putNextEntry(sfFile);
        sf.write(zos);

        if (handler != null) {
            if (zipFile.getEntry(sfFilename) != null) {
                handler.accept("updating", sfFilename);
            } else {
                handler.accept("adding", sfFilename);
            }
        }

        // signature block file
        zos.putNextEntry(bkFile);
        zos.write(block);

        if (handler != null) {
            if (zipFile.getEntry(bkFilename) != null) {
                handler.accept("updating", bkFilename);
            } else {
                handler.accept("adding", bkFilename);
            }
        }

        // Write out all other META-INF files that we stored in the
        // vector
        for (int i = 0; i < mfFiles.size(); i++) {
            ZipEntry ze = mfFiles.elementAt(i);
            if (!ze.getName().equalsIgnoreCase(JarFile.MANIFEST_NAME)
                    && !ze.getName().equalsIgnoreCase(sfFilename)
                    && !ze.getName().equalsIgnoreCase(bkFilename)) {
                if (handler != null) {
                    if (manifest.getAttributes(ze.getName()) != null) {
                        handler.accept("signing", ze.getName());
                    } else if (!ze.isDirectory()) {
                        handler.accept("adding", ze.getName());
                    }
                }
                writeEntry(zipFile, zos, ze);
            }
        }

        // Write out all other files
        for (Enumeration<? extends ZipEntry> enum_ = zipFile.entries();
             enum_.hasMoreElements(); ) {
            ZipEntry ze = enum_.nextElement();

            if (!ze.getName().startsWith(META_INF)) {
                if (handler != null) {
                    if (manifest.getAttributes(ze.getName()) != null) {
                        handler.accept("signing", ze.getName());
                    } else {
                        handler.accept("adding", ze.getName());
                    }
                }
                writeEntry(zipFile, zos, ze);
            }
        }
        zipFile.close();
        zos.close();
    }

    private void writeEntry(ZipFile zf, ZipOutputStream os, ZipEntry ze)
            throws IOException {
        ZipEntry ze2 = new ZipEntry(ze.getName());
        ze2.setMethod(ze.getMethod());
        ze2.setTime(ze.getTime());
        ze2.setComment(ze.getComment());
        ze2.setExtra(ze.getExtra());
        if (ze.getMethod() == ZipEntry.STORED) {
            ze2.setSize(ze.getSize());
            ze2.setCrc(ze.getCrc());
        }
        os.putNextEntry(ze2);
        writeBytes(zf, ze, os);
    }

    private void writeBytes
            (ZipFile zf, ZipEntry ze, ZipOutputStream os) throws IOException {
        try (InputStream is = zf.getInputStream(ze)) {
            is.transferTo(os);
        }
    }

    private boolean updateDigests(ZipEntry ze, ZipFile zf,
                                  MessageDigest[] digests,
                                  Manifest mf) throws IOException {
        boolean update = false;

        Attributes attrs = mf.getAttributes(ze.getName());
        String[] base64Digests = getDigests(ze, zf, digests);

        for (int i = 0; i < digests.length; i++) {
            // The entry name to be written into attrs
            String name = null;
            try {
                // Find if the digest already exists. An algorithm could have
                // different names. For example, last time it was SHA, and this
                // time it's SHA-1.
                AlgorithmId aid = AlgorithmId.get(digests[i].getAlgorithm());
                for (Object key : attrs.keySet()) {
                    if (key instanceof Attributes.Name) {
                        String n = key.toString();
                        if (n.toUpperCase(Locale.ENGLISH).endsWith("-DIGEST")) {
                            String tmp = n.substring(0, n.length() - 7);
                            if (AlgorithmId.get(tmp).equals(aid)) {
                                name = n;
                                break;
                            }
                        }
                    }
                }
            } catch (NoSuchAlgorithmException nsae) {
                // Ignored. Writing new digest entry.
            }

            if (name == null) {
                name = digests[i].getAlgorithm() + "-Digest";
                attrs.putValue(name, base64Digests[i]);
                update = true;
            } else {
                // compare digests, and replace the one in the manifest
                // if they are different
                String mfDigest = attrs.getValue(name);
                if (!mfDigest.equalsIgnoreCase(base64Digests[i])) {
                    attrs.putValue(name, base64Digests[i]);
                    update = true;
                }
            }
        }
        return update;
    }

    private Attributes getDigestAttributes(
            ZipEntry ze, ZipFile zf, MessageDigest[] digests)
            throws IOException {

        String[] base64Digests = getDigests(ze, zf, digests);
        Attributes attrs = new Attributes();

        for (int i = 0; i < digests.length; i++) {
            attrs.putValue(digests[i].getAlgorithm() + "-Digest",
                    base64Digests[i]);
        }
        return attrs;
    }

    /*
     * Returns manifest entry from given jar file, or null if given jar file
     * does not have a manifest entry.
     */
    private ZipEntry getManifestFile(ZipFile zf) {
        ZipEntry ze = zf.getEntry(JarFile.MANIFEST_NAME);
        if (ze == null) {
            // Check all entries for matching name
            Enumeration<? extends ZipEntry> enum_ = zf.entries();
            while (enum_.hasMoreElements() && ze == null) {
                ze = enum_.nextElement();
                if (!JarFile.MANIFEST_NAME.equalsIgnoreCase
                        (ze.getName())) {
                    ze = null;
                }
            }
        }
        return ze;
    }

    private String[] getDigests(
            ZipEntry ze, ZipFile zf, MessageDigest[] digests)
            throws IOException {

        int n, i;
        try (InputStream is = zf.getInputStream(ze)) {
            long left = ze.getSize();
            byte[] buffer = new byte[8192];
            while ((left > 0)
                    && (n = is.read(buffer, 0, buffer.length)) != -1) {
                for (i = 0; i < digests.length; i++) {
                    digests[i].update(buffer, 0, n);
                }
                left -= n;
            }
        }

        // complete the digests
        String[] base64Digests = new String[digests.length];
        for (i = 0; i < digests.length; i++) {
            base64Digests[i] = Base64.getEncoder()
                    .encodeToString(digests[i].digest());
        }
        return base64Digests;
    }

    @SuppressWarnings("fallthrough")
    private int findHeaderEnd(byte[] bs) {
        // Initial state true to deal with empty header
        boolean newline = true;     // just met a newline
        int len = bs.length;
        for (int i = 0; i < len; i++) {
            switch (bs[i]) {
                case '\r':
                    if (i < len - 1 && bs[i + 1] == '\n') i++;
                    // fallthrough
                case '\n':
                    if (newline) return i + 1;    //+1 to get length
                    newline = true;
                    break;
                default:
                    newline = false;
            }
        }
        // If header end is not found, it means the MANIFEST.MF has only
        // the main attributes section and it does not end with 2 newlines.
        // Returns the whole length so that it can be completely replaced.
        return len;
    }

    /*
     * Try to load the specified signing mechanism.
     * The URL class loader is used.
     */
    @SuppressWarnings("deprecation")
    private ContentSigner loadSigningMechanism(String signerClassName,
                                               String signerClassPath) {

        // construct class loader
        String cpString;   // make sure env.class.path defaults to dot

        // do prepends to get correct ordering
        cpString = PathList.appendPath(
                System.getProperty("env.class.path"), null);
        cpString = PathList.appendPath(
                System.getProperty("java.class.path"), cpString);
        cpString = PathList.appendPath(signerClassPath, cpString);
        URL[] urls = PathList.pathToURLs(cpString);
        ClassLoader appClassLoader = new URLClassLoader(urls);

        try {
            // attempt to find signer
            Class<?> signerClass = appClassLoader.loadClass(signerClassName);
            Object signer = signerClass.newInstance();
            return (ContentSigner) signer;
        } catch (ClassNotFoundException|InstantiationException|
                IllegalAccessException|ClassCastException e) {
            throw new IllegalArgumentException(
                    "Invalid altSigner or altSignerPath", e);
        }
    }

    static class SignatureFile {

        /**
         * SignatureFile
         */
        Manifest sf;

        /**
         * .SF base name
         */
        String baseName;

        public SignatureFile(MessageDigest digests[],
                             Manifest mf,
                             ManifestDigester md,
                             String baseName,
                             boolean signManifest) {

            this.baseName = baseName;

            String version = System.getProperty("java.version");
            String javaVendor = System.getProperty("java.vendor");

            sf = new Manifest();
            Attributes mattr = sf.getMainAttributes();

            mattr.putValue(Attributes.Name.SIGNATURE_VERSION.toString(), "1.0");
            mattr.putValue("Created-By", version + " (" + javaVendor + ")");

            if (signManifest) {
                for (MessageDigest digest: digests) {
                    mattr.putValue(digest.getAlgorithm() + "-Digest-Manifest",
                            Base64.getEncoder().encodeToString(
                                    md.manifestDigest(digest)));
                }
            }

            // create digest of the manifest main attributes
            ManifestDigester.Entry mde =
                    md.get(ManifestDigester.MF_MAIN_ATTRS, false);
            if (mde != null) {
                for (MessageDigest digest: digests) {
                    mattr.putValue(digest.getAlgorithm() +
                                    "-Digest-" + ManifestDigester.MF_MAIN_ATTRS,
                            Base64.getEncoder().encodeToString(
                                    mde.digest(digest)));
                }
            } else {
                throw new IllegalStateException
                        ("ManifestDigester failed to create " +
                                "Manifest-Main-Attribute entry");
            }

            // go through the manifest entries and create the digests
            Map<String, Attributes> entries = sf.getEntries();
            for (String name: mf.getEntries().keySet()) {
                mde = md.get(name, false);
                if (mde != null) {
                    Attributes attr = new Attributes();
                    for (MessageDigest digest: digests) {
                        attr.putValue(digest.getAlgorithm() + "-Digest",
                                Base64.getEncoder().encodeToString(
                                        mde.digest(digest)));
                    }
                    entries.put(name, attr);
                }
            }
        }

        // Write .SF file
        public void write(OutputStream out) throws IOException {
            sf.write(out);
        }

        // get .SF file name
        public String getMetaName() {
            return "META-INF/" + baseName + ".SF";
        }

        // get .DSA (or .DSA, .EC) file name
        public String getBlockName(PrivateKey privateKey) {
            String keyAlgorithm = privateKey.getAlgorithm();
            return "META-INF/" + baseName + "." + keyAlgorithm;
        }

        // Generates the PKCS#7 content of block file
        @SuppressWarnings("deprecation")
        public byte[] generateBlock(ContentSignerParameters params,
                                    boolean externalSF,
                                    ContentSigner signingMechanism)
                throws NoSuchAlgorithmException,
                       IOException, CertificateException {

            if (signingMechanism == null) {
                signingMechanism = new TimestampedSigner();
            }
            return signingMechanism.generateSignedData(
                    params,
                    externalSF,
                    params.getTimestampingAuthority() != null
                        || params.getTimestampingAuthorityCertificate() != null);
        }
    }

    @SuppressWarnings("deprecation")
    class JarSignerParameters implements ContentSignerParameters {

        private String[] args;
        private URI tsa;
        private byte[] signature;
        private String signatureAlgorithm;
        private X509Certificate[] signerCertificateChain;
        private byte[] content;
        private ZipFile source;
        private String tSAPolicyID;
        private String tSADigestAlg;

        JarSignerParameters(String[] args, URI tsa,
                            String tSAPolicyID, String tSADigestAlg,
                            byte[] signature, String signatureAlgorithm,
                            X509Certificate[] signerCertificateChain,
                            byte[] content, ZipFile source) {

            Objects.requireNonNull(signature);
            Objects.requireNonNull(signatureAlgorithm);
            Objects.requireNonNull(signerCertificateChain);

            this.args = args;
            this.tsa = tsa;
            this.tSAPolicyID = tSAPolicyID;
            this.tSADigestAlg = tSADigestAlg;
            this.signature = signature;
            this.signatureAlgorithm = signatureAlgorithm;
            this.signerCertificateChain = signerCertificateChain;
            this.content = content;
            this.source = source;
        }

        public String[] getCommandLine() {
            return args;
        }

        public URI getTimestampingAuthority() {
            return tsa;
        }

        public X509Certificate getTimestampingAuthorityCertificate() {
            // We don't use this param. Always provide tsaURI.
            return null;
        }

        public String getTSAPolicyID() {
            return tSAPolicyID;
        }

        public String getTSADigestAlg() {
            return tSADigestAlg;
        }

        public byte[] getSignature() {
            return signature;
        }

        public String getSignatureAlgorithm() {
            return signatureAlgorithm;
        }

        public X509Certificate[] getSignerCertificateChain() {
            return signerCertificateChain;
        }

        public byte[] getContent() {
            return content;
        }

        public ZipFile getSource() {
            return source;
        }
    }
}
