1 /* 2 * Copyright (c) 2015, 2020, 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 8242068 8255536 27 * @summary Make sure JarSigner impl conforms to spec 28 * @library /test/lib 29 * @modules java.base/sun.security.tools.keytool 30 * java.base/sun.security.provider.certpath 31 * jdk.jartool 32 * jdk.crypto.ec 33 * @build jdk.test.lib.util.JarUtils 34 * @run main/othervm Spec 35 */ 36 37 import com.sun.jarsigner.ContentSigner; 38 import com.sun.jarsigner.ContentSignerParameters; 39 import jdk.security.jarsigner.JarSigner; 40 import jdk.test.lib.util.JarUtils; 41 import sun.security.provider.certpath.X509CertPath; 42 43 import java.io.File; 44 import java.io.IOException; 45 import java.net.URI; 46 import java.nio.file.Files; 47 import java.nio.file.Paths; 48 import java.security.*; 49 import java.security.cert.CertPath; 50 import java.security.cert.CertificateException; 51 import java.security.cert.CertificateFactory; 52 import java.util.Arrays; 53 import java.util.Collections; 54 import java.util.function.BiConsumer; 55 56 public class Spec { 57 main(String[] args)58 public static void main(String[] args) throws Exception { 59 60 // Prepares raw file 61 Files.write(Paths.get("a"), "a".getBytes()); 62 63 // Pack 64 JarUtils.createJar("a.jar", "a"); 65 66 // Prepare a keystore 67 sun.security.tools.keytool.Main.main( 68 ("-keystore ks -storepass changeit -keypass changeit -dname" + 69 " CN=RSA -alias r -genkeypair -keyalg rsa").split(" ")); 70 sun.security.tools.keytool.Main.main( 71 ("-keystore ks -storepass changeit -keypass changeit -dname" + 72 " CN=DSA -alias d -genkeypair -keyalg dsa").split(" ")); 73 sun.security.tools.keytool.Main.main( 74 ("-keystore ks -storepass changeit -keypass changeit -dname" + 75 " CN=Ed25519 -alias e -genkeypair -keyalg Ed25519").split(" ")); 76 77 char[] pass = "changeit".toCharArray(); 78 79 KeyStore ks = KeyStore.getInstance( 80 new File("ks"), pass); 81 PrivateKey pkr = (PrivateKey)ks.getKey("r", pass); 82 PrivateKey pkd = (PrivateKey)ks.getKey("d", pass); 83 CertPath cp = CertificateFactory.getInstance("X.509") 84 .generateCertPath(Arrays.asList(ks.getCertificateChain("r"))); 85 86 Provider sun = Security.getProvider("SUN"); 87 88 // throws 89 npe(()->new JarSigner.Builder(null)); 90 npe(()->new JarSigner.Builder(null, cp)); 91 iae(()->new JarSigner.Builder( 92 pkr, new X509CertPath(Collections.emptyList()))); 93 iae(()->new JarSigner.Builder(pkd, cp)); // unmatched certs alg 94 95 JarSigner.Builder b1 = new JarSigner.Builder(pkr, cp); 96 97 npe(()->b1.digestAlgorithm(null)); 98 nsae(()->b1.digestAlgorithm("HAHA")); 99 b1.digestAlgorithm("SHA-256"); 100 101 npe(()->b1.digestAlgorithm("SHA-256", null)); 102 npe(()->b1.digestAlgorithm(null, sun)); 103 nsae(()->b1.digestAlgorithm("HAHA", sun)); 104 b1.digestAlgorithm("SHA-256", sun); 105 106 npe(()->b1.signatureAlgorithm(null)); 107 nsae(()->b1.signatureAlgorithm("HAHAwithHEHE")); 108 iae(()->b1.signatureAlgorithm("SHA256withECDSA")); 109 110 npe(()->b1.signatureAlgorithm(null, sun)); 111 npe(()->b1.signatureAlgorithm("SHA256withRSA", null)); 112 nsae(()->b1.signatureAlgorithm("HAHAwithHEHE", sun)); 113 iae(()->b1.signatureAlgorithm("SHA256withDSA", sun)); 114 115 npe(()->b1.tsa(null)); 116 117 npe(()->b1.signerName(null)); 118 iae(()->b1.signerName("")); 119 iae(()->b1.signerName("123456789")); 120 iae(()->b1.signerName("a+b")); 121 122 npe(()->b1.setProperty(null, "")); 123 uoe(()->b1.setProperty("what", "")); 124 npe(()->b1.setProperty("tsadigestalg", null)); 125 iae(()->b1.setProperty("tsadigestalg", "HAHA")); 126 npe(()->b1.setProperty("tsapolicyid", null)); 127 npe(()->b1.setProperty("internalsf", null)); 128 iae(()->b1.setProperty("internalsf", "Hello")); 129 npe(()->b1.setProperty("sectionsonly", null)); 130 iae(()->b1.setProperty("sectionsonly", "OK")); 131 npe(()->b1.setProperty("sectionsonly", null)); 132 npe(()->b1.setProperty("altsigner", null)); 133 npe(()->b1.eventHandler(null)); 134 135 // default values 136 JarSigner.Builder b2 = new JarSigner.Builder(pkr, cp); 137 JarSigner js2 = b2.build(); 138 139 assertTrue(js2.getDigestAlgorithm().equals( 140 JarSigner.Builder.getDefaultDigestAlgorithm())); 141 assertTrue(js2.getSignatureAlgorithm().equals( 142 JarSigner.Builder.getDefaultSignatureAlgorithm(pkr))); 143 assertTrue(js2.getTsa() == null); 144 assertTrue(js2.getSignerName().equals("SIGNER")); 145 assertTrue(js2.getProperty("tsadigestalg").equals( 146 JarSigner.Builder.getDefaultDigestAlgorithm())); 147 assertTrue(js2.getProperty("tsapolicyid") == null); 148 assertTrue(js2.getProperty("internalsf").equals("false")); 149 assertTrue(js2.getProperty("sectionsonly").equals("false")); 150 assertTrue(js2.getProperty("altsigner") == null); 151 uoe(()->js2.getProperty("invalid")); 152 153 // default values 154 BiConsumer<String,String> myeh = (a,s)->{}; 155 URI tsa = new URI("https://tsa.com"); 156 157 JarSigner.Builder b3 = new JarSigner.Builder(pkr, cp) 158 .digestAlgorithm("SHA-1") 159 .signatureAlgorithm("SHA1withRSA") 160 .signerName("Duke") 161 .tsa(tsa) 162 .setProperty("tsadigestalg", "SHA-512") 163 .setProperty("tsapolicyid", "1.2.3.4") 164 .setProperty("internalsf", "true") 165 .setProperty("sectionsonly", "true") 166 .setProperty("altsigner", "MyContentSigner") 167 .eventHandler(myeh); 168 JarSigner js3 = b3.build(); 169 170 assertTrue(js3.getDigestAlgorithm().equals("SHA-1")); 171 assertTrue(js3.getSignatureAlgorithm().equals("SHA1withRSA")); 172 assertTrue(js3.getTsa().equals(tsa)); 173 assertTrue(js3.getSignerName().equals("DUKE")); 174 assertTrue(js3.getProperty("tsadigestalg").equals("SHA-512")); 175 assertTrue(js3.getProperty("tsapolicyid").equals("1.2.3.4")); 176 assertTrue(js3.getProperty("internalsf").equals("true")); 177 assertTrue(js3.getProperty("sectionsonly").equals("true")); 178 assertTrue(js3.getProperty("altsigner").equals("MyContentSigner")); 179 assertTrue(js3.getProperty("altsignerpath") == null); 180 181 assertTrue(JarSigner.Builder.getDefaultDigestAlgorithm().equals("SHA-256")); 182 183 // Calculating large DSA and RSA keys are too slow. 184 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 185 kpg.initialize(1024); 186 assertTrue(JarSigner.Builder 187 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 188 .equals("SHA256withRSA")); 189 190 kpg = KeyPairGenerator.getInstance("DSA"); 191 kpg.initialize(1024); 192 assertTrue(JarSigner.Builder 193 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 194 .equals("SHA256withDSA")); 195 196 kpg = KeyPairGenerator.getInstance("EC"); 197 kpg.initialize(256); 198 assertTrue(JarSigner.Builder 199 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 200 .equals("SHA256withECDSA")); 201 kpg.initialize(384); 202 assertTrue(JarSigner.Builder 203 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 204 .equals("SHA384withECDSA")); 205 kpg.initialize(521); 206 assertTrue(JarSigner.Builder 207 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 208 .equals("SHA512withECDSA")); 209 210 // altsigner does not support modern algorithms 211 JarSigner.Builder b4 = new JarSigner.Builder( 212 (PrivateKey)ks.getKey("e", pass), 213 CertificateFactory.getInstance("X.509") 214 .generateCertPath(Arrays.asList(ks.getCertificateChain("e")))); 215 b4.setProperty("altsigner", "MyContentSigner"); 216 iae(() -> b4.build()); 217 } 218 219 interface RunnableWithException { run()220 void run() throws Exception; 221 } 222 uoe(RunnableWithException r)223 static void uoe(RunnableWithException r) throws Exception { 224 checkException(r, UnsupportedOperationException.class); 225 } 226 nsae(RunnableWithException r)227 static void nsae(RunnableWithException r) throws Exception { 228 checkException(r, NoSuchAlgorithmException.class); 229 } 230 npe(RunnableWithException r)231 static void npe(RunnableWithException r) throws Exception { 232 checkException(r, NullPointerException.class); 233 } 234 iae(RunnableWithException r)235 static void iae(RunnableWithException r) throws Exception { 236 checkException(r, IllegalArgumentException.class); 237 } 238 checkException(RunnableWithException r, Class ex)239 static void checkException(RunnableWithException r, Class ex) 240 throws Exception { 241 try { 242 r.run(); 243 } catch (Exception e) { 244 if (ex.isAssignableFrom(e.getClass())) { 245 return; 246 } 247 throw e; 248 } 249 throw new Exception("No exception thrown"); 250 } 251 assertTrue(boolean x)252 static void assertTrue(boolean x) throws Exception { 253 if (!x) throw new Exception("Not true"); 254 } 255 256 static class MyContentSigner extends ContentSigner { 257 @Override generateSignedData( ContentSignerParameters parameters, boolean omitContent, boolean applyTimestamp)258 public byte[] generateSignedData( 259 ContentSignerParameters parameters, 260 boolean omitContent, 261 boolean applyTimestamp) throws NoSuchAlgorithmException, 262 CertificateException, IOException { 263 return new byte[0]; 264 } 265 } 266 } 267