1 /* 2 * Copyright (c) 2015, 2017, 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 /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 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 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 74 char[] pass = "changeit".toCharArray(); 75 76 KeyStore ks = KeyStore.getInstance( 77 new File("ks"), pass); 78 PrivateKey pkr = (PrivateKey)ks.getKey("r", pass); 79 PrivateKey pkd = (PrivateKey)ks.getKey("d", pass); 80 CertPath cp = CertificateFactory.getInstance("X.509") 81 .generateCertPath(Arrays.asList(ks.getCertificateChain("r"))); 82 83 Provider sun = Security.getProvider("SUN"); 84 85 // throws 86 npe(()->new JarSigner.Builder(null)); 87 npe(()->new JarSigner.Builder(null, cp)); 88 iae(()->new JarSigner.Builder( 89 pkr, new X509CertPath(Collections.emptyList()))); 90 iae(()->new JarSigner.Builder(pkd, cp)); // unmatched certs alg 91 92 JarSigner.Builder b1 = new JarSigner.Builder(pkr, cp); 93 94 npe(()->b1.digestAlgorithm(null)); 95 nsae(()->b1.digestAlgorithm("HAHA")); 96 b1.digestAlgorithm("SHA-256"); 97 98 npe(()->b1.digestAlgorithm("SHA-256", null)); 99 npe(()->b1.digestAlgorithm(null, sun)); 100 nsae(()->b1.digestAlgorithm("HAHA", sun)); 101 b1.digestAlgorithm("SHA-256", sun); 102 103 npe(()->b1.signatureAlgorithm(null)); 104 nsae(()->b1.signatureAlgorithm("HAHAwithHEHE")); 105 iae(()->b1.signatureAlgorithm("SHA256withECDSA")); 106 107 npe(()->b1.signatureAlgorithm(null, sun)); 108 npe(()->b1.signatureAlgorithm("SHA256withRSA", null)); 109 nsae(()->b1.signatureAlgorithm("HAHAwithHEHE", sun)); 110 iae(()->b1.signatureAlgorithm("SHA256withDSA", sun)); 111 112 npe(()->b1.tsa(null)); 113 114 npe(()->b1.signerName(null)); 115 iae(()->b1.signerName("")); 116 iae(()->b1.signerName("123456789")); 117 iae(()->b1.signerName("a+b")); 118 119 npe(()->b1.setProperty(null, "")); 120 uoe(()->b1.setProperty("what", "")); 121 npe(()->b1.setProperty("tsadigestalg", null)); 122 iae(()->b1.setProperty("tsadigestalg", "HAHA")); 123 npe(()->b1.setProperty("tsapolicyid", null)); 124 npe(()->b1.setProperty("internalsf", null)); 125 iae(()->b1.setProperty("internalsf", "Hello")); 126 npe(()->b1.setProperty("sectionsonly", null)); 127 iae(()->b1.setProperty("sectionsonly", "OK")); 128 npe(()->b1.setProperty("altsigner", null)); 129 npe(()->b1.eventHandler(null)); 130 131 // default values 132 JarSigner.Builder b2 = new JarSigner.Builder(pkr, cp); 133 JarSigner js2 = b2.build(); 134 135 assertTrue(js2.getDigestAlgorithm().equals( 136 JarSigner.Builder.getDefaultDigestAlgorithm())); 137 assertTrue(js2.getSignatureAlgorithm().equals( 138 JarSigner.Builder.getDefaultSignatureAlgorithm(pkr))); 139 assertTrue(js2.getTsa() == null); 140 assertTrue(js2.getSignerName().equals("SIGNER")); 141 assertTrue(js2.getProperty("tsadigestalg").equals( 142 JarSigner.Builder.getDefaultDigestAlgorithm())); 143 assertTrue(js2.getProperty("tsapolicyid") == null); 144 assertTrue(js2.getProperty("internalsf").equals("false")); 145 assertTrue(js2.getProperty("sectionsonly").equals("false")); 146 assertTrue(js2.getProperty("altsigner") == null); 147 uoe(()->js2.getProperty("invalid")); 148 149 // default values 150 BiConsumer<String,String> myeh = (a,s)->{}; 151 URI tsa = new URI("https://tsa.com"); 152 153 JarSigner.Builder b3 = new JarSigner.Builder(pkr, cp) 154 .digestAlgorithm("SHA-1") 155 .signatureAlgorithm("SHA1withRSA") 156 .signerName("Duke") 157 .tsa(tsa) 158 .setProperty("tsadigestalg", "SHA-512") 159 .setProperty("tsapolicyid", "1.2.3.4") 160 .setProperty("internalsf", "true") 161 .setProperty("sectionsonly", "true") 162 .setProperty("altsigner", "MyContentSigner") 163 .eventHandler(myeh); 164 JarSigner js3 = b3.build(); 165 166 assertTrue(js3.getDigestAlgorithm().equals("SHA-1")); 167 assertTrue(js3.getSignatureAlgorithm().equals("SHA1withRSA")); 168 assertTrue(js3.getTsa().equals(tsa)); 169 assertTrue(js3.getSignerName().equals("DUKE")); 170 assertTrue(js3.getProperty("tsadigestalg").equals("SHA-512")); 171 assertTrue(js3.getProperty("tsapolicyid").equals("1.2.3.4")); 172 assertTrue(js3.getProperty("internalsf").equals("true")); 173 assertTrue(js3.getProperty("sectionsonly").equals("true")); 174 assertTrue(js3.getProperty("altsigner").equals("MyContentSigner")); 175 assertTrue(js3.getProperty("altsignerpath") == null); 176 177 assertTrue(JarSigner.Builder.getDefaultDigestAlgorithm().equals("SHA-256")); 178 179 // Calculating large DSA and RSA keys are too slow. 180 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 181 kpg.initialize(1024); 182 assertTrue(JarSigner.Builder 183 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 184 .equals("SHA256withRSA")); 185 186 kpg = KeyPairGenerator.getInstance("DSA"); 187 kpg.initialize(1024); 188 assertTrue(JarSigner.Builder 189 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 190 .equals("SHA256withDSA")); 191 192 kpg = KeyPairGenerator.getInstance("EC"); 193 kpg.initialize(192); 194 assertTrue(JarSigner.Builder 195 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 196 .equals("SHA256withECDSA")); 197 kpg.initialize(384); 198 assertTrue(JarSigner.Builder 199 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 200 .equals("SHA384withECDSA")); 201 kpg.initialize(571); 202 assertTrue(JarSigner.Builder 203 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) 204 .equals("SHA512withECDSA")); 205 } 206 207 interface RunnableWithException { 208 void run() throws Exception; 209 } 210 211 static void uoe(RunnableWithException r) throws Exception { 212 checkException(r, UnsupportedOperationException.class); 213 } 214 215 static void nsae(RunnableWithException r) throws Exception { 216 checkException(r, NoSuchAlgorithmException.class); 217 } 218 219 static void npe(RunnableWithException r) throws Exception { 220 checkException(r, NullPointerException.class); 221 } 222 223 static void iae(RunnableWithException r) throws Exception { 224 checkException(r, IllegalArgumentException.class); 225 } 226 227 static void checkException(RunnableWithException r, Class ex) 228 throws Exception { 229 try { 230 r.run(); 231 } catch (Exception e) { 232 if (ex.isAssignableFrom(e.getClass())) { 233 return; 234 } 235 throw e; 236 } 237 throw new Exception("No exception thrown"); 238 } 239 240 static void assertTrue(boolean x) throws Exception { 241 if (!x) throw new Exception("Not true"); 242 } 243 244 static class MyContentSigner extends ContentSigner { 245 @Override 246 public byte[] generateSignedData( 247 ContentSignerParameters parameters, 248 boolean omitContent, 249 boolean applyTimestamp) throws NoSuchAlgorithmException, 250 CertificateException, IOException { 251 return new byte[0]; 252 } 253 } 254 }