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 }