1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 8056174
  27  * @summary Make sure JarSigner impl conforms to spec
  28  * @library /lib/testlibrary
  29  * @modules java.base/sun.security.tools.keytool
  30  *          java.base/sun.security.provider.certpath
  31  *          jdk.jartool
  32  */
  33 
  34 import com.sun.jarsigner.ContentSigner;
  35 import com.sun.jarsigner.ContentSignerParameters;
  36 import jdk.security.jarsigner.JarSigner;
  37 import jdk.testlibrary.JarUtils;
  38 import sun.security.provider.certpath.X509CertPath;
  39 
  40 import java.io.File;
  41 import java.io.IOException;
  42 import java.net.URI;
  43 import java.nio.file.Files;
  44 import java.nio.file.Paths;
  45 import java.security.*;
  46 import java.security.cert.CertPath;
  47 import java.security.cert.CertificateException;
  48 import java.security.cert.CertificateFactory;
  49 import java.util.Arrays;
  50 import java.util.Collections;
  51 import java.util.function.BiConsumer;
  52 
  53 public class Spec {
  54 
  55     public static void main(String[] args) throws Exception {
  56 
  57         // Prepares raw file
  58         Files.write(Paths.get("a"), "a".getBytes());
  59 
  60         // Pack
  61         JarUtils.createJar("a.jar", "a");
  62 
  63         // Prepare a keystore
  64         sun.security.tools.keytool.Main.main(
  65                 ("-keystore ks -storepass changeit -keypass changeit -dname" +
  66                         " CN=RSA -alias r -genkeypair -keyalg rsa").split(" "));
  67         sun.security.tools.keytool.Main.main(
  68                 ("-keystore ks -storepass changeit -keypass changeit -dname" +
  69                         " CN=DSA -alias d -genkeypair -keyalg dsa").split(" "));
  70 
  71         char[] pass = "changeit".toCharArray();
  72 
  73         KeyStore ks = KeyStore.getInstance(
  74                 new File("ks"), pass);
  75         PrivateKey pkr = (PrivateKey)ks.getKey("r", pass);
  76         PrivateKey pkd = (PrivateKey)ks.getKey("d", pass);
  77         CertPath cp = CertificateFactory.getInstance("X.509")
  78                 .generateCertPath(Arrays.asList(ks.getCertificateChain("r")));
  79 
  80         Provider sun = Security.getProvider("SUN");
  81 
  82         // throws
  83         npe(()->new JarSigner.Builder(null));
  84         npe(()->new JarSigner.Builder(null, cp));
  85         iae(()->new JarSigner.Builder(
  86                 pkr, new X509CertPath(Collections.emptyList())));
  87         iae(()->new JarSigner.Builder(pkd, cp));    // unmatched certs alg
  88 
  89         JarSigner.Builder b1 = new JarSigner.Builder(pkr, cp);
  90 
  91         npe(()->b1.digestAlgorithm(null));
  92         nsae(()->b1.digestAlgorithm("HAHA"));
  93         b1.digestAlgorithm("SHA-256");
  94 
  95         npe(()->b1.digestAlgorithm("SHA-256", null));
  96         npe(()->b1.digestAlgorithm(null, sun));
  97         nsae(()->b1.digestAlgorithm("HAHA", sun));
  98         b1.digestAlgorithm("SHA-256", sun);
  99 
 100         npe(()->b1.signatureAlgorithm(null));
 101         nsae(()->b1.signatureAlgorithm("HAHAwithHEHE"));
 102         iae(()->b1.signatureAlgorithm("SHA256withECDSA"));
 103 
 104         npe(()->b1.signatureAlgorithm(null, sun));
 105         npe(()->b1.signatureAlgorithm("SHA256withRSA", null));
 106         nsae(()->b1.signatureAlgorithm("HAHAwithHEHE", sun));
 107         iae(()->b1.signatureAlgorithm("SHA256withDSA", sun));
 108 
 109         npe(()->b1.tsa(null));
 110 
 111         npe(()->b1.signerName(null));
 112         iae(()->b1.signerName(""));
 113         iae(()->b1.signerName("123456789"));
 114         iae(()->b1.signerName("a+b"));
 115 
 116         npe(()->b1.setProperty(null, ""));
 117         uoe(()->b1.setProperty("what", ""));
 118         npe(()->b1.setProperty("tsadigestalg", null));
 119         iae(()->b1.setProperty("tsadigestalg", "HAHA"));
 120         npe(()->b1.setProperty("tsapolicyid", null));
 121         npe(()->b1.setProperty("internalsf", null));
 122         iae(()->b1.setProperty("internalsf", "Hello"));
 123         npe(()->b1.setProperty("sectionsonly", null));
 124         iae(()->b1.setProperty("sectionsonly", "OK"));
 125         npe(()->b1.setProperty("altsigner", null));
 126         npe(()->b1.eventHandler(null));
 127 
 128         // default values
 129         JarSigner.Builder b2 = new JarSigner.Builder(pkr, cp);
 130         JarSigner js2 = b2.build();
 131 
 132         assertTrue(js2.getDigestAlgorithm().equals(
 133                 JarSigner.Builder.getDefaultDigestAlgorithm()));
 134         assertTrue(js2.getSignatureAlgorithm().equals(
 135                 JarSigner.Builder.getDefaultSignatureAlgorithm(pkr)));
 136         assertTrue(js2.getTsa() == null);
 137         assertTrue(js2.getSignerName().equals("SIGNER"));
 138         assertTrue(js2.getProperty("tsadigestalg").equals(
 139                 JarSigner.Builder.getDefaultDigestAlgorithm()));
 140         assertTrue(js2.getProperty("tsapolicyid") == null);
 141         assertTrue(js2.getProperty("internalsf").equals("false"));
 142         assertTrue(js2.getProperty("sectionsonly").equals("false"));
 143         assertTrue(js2.getProperty("altsigner") == null);
 144         uoe(()->js2.getProperty("invalid"));
 145 
 146         // default values
 147         BiConsumer<String,String> myeh = (a,s)->{};
 148         URI tsa = new URI("https://tsa.com");
 149 
 150         JarSigner.Builder b3 = new JarSigner.Builder(pkr, cp)
 151                 .digestAlgorithm("SHA-1")
 152                 .signatureAlgorithm("SHA1withRSA")
 153                 .signerName("Duke")
 154                 .tsa(tsa)
 155                 .setProperty("tsadigestalg", "SHA-512")
 156                 .setProperty("tsapolicyid", "1.2.3.4")
 157                 .setProperty("internalsf", "true")
 158                 .setProperty("sectionsonly", "true")
 159                 .setProperty("altsigner", "MyContentSigner")
 160                 .eventHandler(myeh);
 161         JarSigner js3 = b3.build();
 162 
 163         assertTrue(js3.getDigestAlgorithm().equals("SHA-1"));
 164         assertTrue(js3.getSignatureAlgorithm().equals("SHA1withRSA"));
 165         assertTrue(js3.getTsa().equals(tsa));
 166         assertTrue(js3.getSignerName().equals("DUKE"));
 167         assertTrue(js3.getProperty("tsadigestalg").equals("SHA-512"));
 168         assertTrue(js3.getProperty("tsapolicyid").equals("1.2.3.4"));
 169         assertTrue(js3.getProperty("internalsf").equals("true"));
 170         assertTrue(js3.getProperty("sectionsonly").equals("true"));
 171         assertTrue(js3.getProperty("altsigner").equals("MyContentSigner"));
 172         assertTrue(js3.getProperty("altsignerpath") == null);
 173 
 174         assertTrue(JarSigner.Builder.getDefaultDigestAlgorithm().equals("SHA-256"));
 175 
 176         // Calculating large DSA and RSA keys are too slow.
 177         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
 178         kpg.initialize(1024);
 179         assertTrue(JarSigner.Builder
 180                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 181                     .equals("SHA256withRSA"));
 182 
 183         kpg = KeyPairGenerator.getInstance("DSA");
 184         kpg.initialize(1024);
 185         assertTrue(JarSigner.Builder
 186                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 187                 .equals("SHA256withDSA"));
 188 
 189         kpg = KeyPairGenerator.getInstance("EC");
 190         kpg.initialize(192);
 191         assertTrue(JarSigner.Builder
 192                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 193                 .equals("SHA256withECDSA"));
 194         kpg.initialize(384);
 195         assertTrue(JarSigner.Builder
 196                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 197                 .equals("SHA384withECDSA"));
 198         kpg.initialize(571);
 199         assertTrue(JarSigner.Builder
 200                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 201                 .equals("SHA512withECDSA"));
 202     }
 203 
 204     interface RunnableWithException {
 205         void run() throws Exception;
 206     }
 207 
 208     static void uoe(RunnableWithException r) throws Exception {
 209         checkException(r, UnsupportedOperationException.class);
 210     }
 211 
 212     static void nsae(RunnableWithException r) throws Exception {
 213         checkException(r, NoSuchAlgorithmException.class);
 214     }
 215 
 216     static void npe(RunnableWithException r) throws Exception {
 217         checkException(r, NullPointerException.class);
 218     }
 219 
 220     static void iae(RunnableWithException r) throws Exception {
 221         checkException(r, IllegalArgumentException.class);
 222     }
 223 
 224     static void checkException(RunnableWithException r, Class ex)
 225             throws Exception {
 226         try {
 227             r.run();
 228         } catch (Exception e) {
 229             if (ex.isAssignableFrom(e.getClass())) {
 230                 return;
 231             }
 232             throw e;
 233         }
 234         throw new Exception("No exception thrown");
 235     }
 236 
 237     static void assertTrue(boolean x) throws Exception {
 238         if (!x) throw new Exception("Not true");
 239     }
 240 
 241     static class MyContentSigner extends ContentSigner {
 242         @Override
 243         public byte[] generateSignedData(
 244                 ContentSignerParameters parameters,
 245                 boolean omitContent,
 246                 boolean applyTimestamp) throws NoSuchAlgorithmException,
 247                 CertificateException, IOException {
 248             return new byte[0];
 249         }
 250     }
 251 }