1 /** 2 * Copyright (c) 2015, 2018, 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 import java.security.Signature; 25 import java.security.SignedObject; 26 import java.security.KeyPairGenerator; 27 import java.security.KeyPair; 28 import java.security.NoSuchProviderException; 29 import java.security.PrivateKey; 30 import java.security.PublicKey; 31 import java.security.spec.*; 32 import java.util.*; 33 import jdk.test.lib.SigTestUtil; 34 import static jdk.test.lib.SigTestUtil.SignatureType; 35 36 /* 37 * @test 38 * @bug 8050374 8181048 8146293 39 * @summary Verify a chain of signed objects 40 * @library /test/lib 41 * @build jdk.test.lib.SigTestUtil 42 * @run main Chain 43 */ 44 public class Chain { 45 46 static enum KeyAlg { 47 RSA("RSA"), 48 DSA("DSA"), 49 EC("EC"); 50 51 final String name; 52 53 KeyAlg(String alg) { 54 this.name = alg; 55 } 56 } 57 58 static enum Provider { 59 Default("default"), 60 SunRsaSign("SunRsaSign"), 61 Sun("SUN"), 62 SunEC("SunEC"), 63 SunJSSE("SunJSSE"), 64 SunMSCAPI("SunMSCAPI"); 65 66 final String name; 67 68 Provider(String name) { 69 this.name = name; 70 } 71 } 72 73 static enum SigAlg { 74 MD2withRSA("MD2withRSA"), 75 MD5withRSA("md5withRSA"), 76 77 SHA1withDSA("SHA1withDSA"), 78 SHA224withDSA("SHA224withDSA"), 79 SHA256withDSA("SHA256withDSA"), 80 81 SHA1withRSA("Sha1withrSA"), 82 SHA224withRSA("SHA224withRSA"), 83 SHA256withRSA("SHA256withRSA"), 84 SHA384withRSA("SHA384withRSA"), 85 SHA512withRSA("SHA512withRSA"), 86 SHA512_224withRSA("SHA512/224withRSA"), 87 SHA512_256withRSA("SHA512/256withRSA"), 88 89 SHA1withECDSA("SHA1withECDSA"), 90 SHA256withECDSA("SHA256withECDSA"), 91 SHA224withECDSA("SHA224withECDSA"), 92 SHA384withECDSA("SHA384withECDSA"), 93 SHA512withECDSA("SHA512withECDSA"), 94 95 MD5andSHA1withRSA("MD5andSHA1withRSA"), 96 97 RSASSA_PSS("RSASSA-PSS"); 98 99 final String name; 100 101 SigAlg(String name) { 102 this.name = name; 103 } 104 } 105 106 static class Test { 107 final Provider provider; 108 final KeyAlg keyAlg; 109 final SigAlg sigAlg; 110 final int keySize; 111 final AlgorithmParameterSpec sigParams; 112 113 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider) { 114 this(sigAlg, keyAlg, provider, -1, null); 115 } 116 117 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize) { 118 this(sigAlg, keyAlg, provider, keySize, null); 119 } 120 121 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize, 122 AlgorithmParameterSpec sigParams) { 123 this.provider = provider; 124 this.keyAlg = keyAlg; 125 this.sigAlg = sigAlg; 126 this.keySize = keySize; 127 this.sigParams = sigParams; 128 } 129 130 private static String formatParams(AlgorithmParameterSpec aps) { 131 if (aps == null) return "null"; 132 if (aps instanceof PSSParameterSpec) { 133 PSSParameterSpec p = (PSSParameterSpec) aps; 134 return String.format("PSSParameterSpec (%s, %s, %s, %s)", 135 p.getDigestAlgorithm(), formatParams(p.getMGFParameters()), 136 p.getSaltLength(), p.getTrailerField()); 137 } else if (aps instanceof MGF1ParameterSpec) { 138 return "MGF1" + 139 ((MGF1ParameterSpec)aps).getDigestAlgorithm(); 140 } else { 141 return aps.toString(); 142 } 143 } 144 145 public String toString() { 146 return String.format("Test: provider = %s, signature alg = %s, " 147 + " w/ %s, key alg = %s", provider, sigAlg, 148 formatParams(sigParams), keyAlg); 149 } 150 } 151 152 private static final Test[] tests = { 153 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Default, 1024), 154 new Test(SigAlg.MD2withRSA, KeyAlg.RSA, Provider.Default), 155 new Test(SigAlg.MD5withRSA, KeyAlg.RSA, Provider.Default), 156 new Test(SigAlg.SHA1withRSA, KeyAlg.RSA, Provider.Default), 157 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Sun, 1024), 158 new Test(SigAlg.SHA224withDSA, KeyAlg.DSA, Provider.Sun, 2048), 159 new Test(SigAlg.SHA256withDSA, KeyAlg.DSA, Provider.Sun, 2048), 160 }; 161 162 private static final String str = "to-be-signed"; 163 private static final int N = 3; 164 165 public static void main(String argv[]) { 166 boolean result = Arrays.stream(tests).allMatch((test) -> runTest(test)); 167 result &= runTestPSS(2048); 168 if (result) { 169 System.out.println("All tests passed"); 170 } else { 171 throw new RuntimeException("Some tests failed"); 172 } 173 } 174 175 private static boolean runTestPSS(int keysize) { 176 boolean result = true; 177 SigAlg pss = SigAlg.RSASSA_PSS; 178 Iterator<String> mdAlgs = SigTestUtil.getDigestAlgorithms 179 (SignatureType.RSASSA_PSS, keysize).iterator(); 180 while (mdAlgs.hasNext()) { 181 result &= runTest(new Test(pss, KeyAlg.RSA, Provider.SunRsaSign, 182 keysize, SigTestUtil.generateDefaultParameter 183 (SignatureType.RSASSA_PSS, mdAlgs.next()))); 184 } 185 return result; 186 } 187 188 static boolean runTest(Test test) { 189 System.out.println(test); 190 try { 191 // Generate all private/public key pairs 192 PrivateKey[] privKeys = new PrivateKey[N]; 193 PublicKey[] pubKeys = new PublicKey[N]; 194 PublicKey[] anotherPubKeys = new PublicKey[N]; 195 Signature signature; 196 KeyPairGenerator kpg; 197 if (test.provider != Provider.Default) { 198 signature = Signature.getInstance(test.sigAlg.name, 199 test.provider.name); 200 kpg = KeyPairGenerator.getInstance( 201 test.keyAlg.name, test.provider.name); 202 } else { 203 signature = Signature.getInstance(test.sigAlg.name); 204 kpg = KeyPairGenerator.getInstance(test.keyAlg.name); 205 } 206 207 signature.setParameter(test.sigParams); 208 209 for (int j=0; j < N; j++) { 210 if (test.keySize != -1) { 211 kpg.initialize(test.keySize); 212 } 213 KeyPair kp = kpg.genKeyPair(); 214 KeyPair anotherKp = kpg.genKeyPair(); 215 privKeys[j] = kp.getPrivate(); 216 pubKeys[j] = kp.getPublic(); 217 anotherPubKeys[j] = anotherKp.getPublic(); 218 219 if (Arrays.equals(pubKeys[j].getEncoded(), 220 anotherPubKeys[j].getEncoded())) { 221 System.out.println("Failed: it should not get " 222 + "the same pair of public key"); 223 return false; 224 } 225 } 226 227 // Create a chain of signed objects 228 SignedObject[] objects = new SignedObject[N]; 229 objects[0] = new SignedObject(str, privKeys[0], signature); 230 for (int j = 1; j < N; j++) { 231 objects[j] = new SignedObject(objects[j - 1], privKeys[j], 232 signature); 233 } 234 235 // Verify the chain 236 int n = objects.length - 1; 237 SignedObject object = objects[n]; 238 do { 239 if (!object.verify(pubKeys[n], signature)) { 240 System.out.println("Failed: verification failed, n = " + n); 241 return false; 242 } 243 if (object.verify(anotherPubKeys[n], signature)) { 244 System.out.println("Failed: verification should not " 245 + "succeed with wrong public key, n = " + n); 246 return false; 247 } 248 249 object = (SignedObject) object.getObject(); 250 n--; 251 } while (n > 0); 252 253 System.out.println("signed data: " + object.getObject()); 254 if (!str.equals(object.getObject())) { 255 System.out.println("Failed: signed data is not equal to " 256 + "original one"); 257 return false; 258 } 259 260 System.out.println("Test passed"); 261 return true; 262 } catch (NoSuchProviderException nspe) { 263 if (test.provider == Provider.SunMSCAPI 264 && !System.getProperty("os.name").startsWith("Windows")) { 265 System.out.println("SunMSCAPI is available only on Windows: " 266 + nspe); 267 return true; 268 } 269 System.out.println("Unexpected exception: " + nspe); 270 return false; 271 } catch (Exception e) { 272 System.out.println("Unexpected exception: " + e); 273 e.printStackTrace(System.out); 274 return false; 275 } 276 } 277 } 278