/* * 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 sun.security.x509.AlgorithmId; import java.net.URI; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Provider; import java.security.Signature; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.Locale; /** * A utility to build an Action object that contains the actual sign method. * * This class exposes more public methods than JarSigner so that the jarsigner * tool can be based on it. Null check, array cloning, and other checks that * are usually not necessary when called internally are implemented in * JarSigner. Read each method carefully. */ class Builder { // Signer materials final PrivateKey privateKey; final X509Certificate[] certChain; // Below are all option settings // Common: String[] digestalg; String sigalg; Provider digestProvider; Provider sigProvider; URI tsaUrl; String signerName; // Seldom: String tSAPolicyID; String tSADigestAlg; X509Certificate tsaCert; // Useless: boolean signManifest = true; boolean externalSF = true; ContentSigner signingMechanism; EventHandler handler = new EventHandler() {}; interface EventHandler { default public void updating(String s) {} default public void adding(String s) {} default public void signing(String s) {} } public Builder digestAlg(String alg, Provider provider) throws NoSuchAlgorithmException { // Check availability if (provider == null) { MessageDigest.getInstance(alg); } else { MessageDigest.getInstance(alg, provider); } digestalg = new String[]{alg}; digestProvider = provider; return this; } public Builder sigAlg(String signatureAlgorithm, Provider provider) throws NoSuchAlgorithmException, IllegalArgumentException { // Check availability if (provider == null) { Signature.getInstance(signatureAlgorithm); } else { Signature.getInstance(signatureAlgorithm, provider); } AlgorithmId.checKeyAlgSigAlgkMatch( privateKey.getAlgorithm(), signatureAlgorithm); this.sigalg = signatureAlgorithm; this.sigProvider = provider; return this; } public Builder tsa(URI uri) { this.tsaUrl = uri; return this; } 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; } public static String getDefaultDigestAlg() { return "SHA-256"; } // Methods not exposed by JarSigner (yet) public Builder tsaCert(X509Certificate tsaCert) { this.tsaCert = tsaCert; return this; } public Builder tsaPolicyId(String oid) { this.tSAPolicyID = oid; return this; } public Builder tsaDigestAlg(String alg) throws NoSuchAlgorithmException { if (alg != null) { MessageDigest.getInstance(alg); } this.tSADigestAlg = alg; return this; } public Builder altsigner(com.sun.jarsigner.ContentSigner signer) { signingMechanism = signer; return this; } public Builder sectionsOnly(boolean v) { signManifest = !v; return this; } public Builder internalSF(boolean v) { externalSF = !v; return this; } public Builder setEventHandler(EventHandler a) { this.handler = a == null ? new EventHandler() {}: a; return this; } public String getDefaultTsaDigestAlg() { return getDefaultDigestAlg(); } // Constructor public Builder(PrivateKey key, Certificate... certs) { this.privateKey = key; this.certChain = new X509Certificate[certs.length]; for (int i=0; i