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 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.util.Arrays; 32 33 /* 34 * @test 35 * @bug 8050374 8181048 36 * @summary Verify a chain of signed objects 37 */ 38 public class Chain { 39 40 static enum KeyAlg { 41 RSA("RSA"), 42 DSA("DSA"), 43 EC("EC"); 44 45 final String name; 46 47 KeyAlg(String alg) { 48 this.name = alg; 49 } 50 } 51 52 static enum Provider { 53 Default("default"), 54 SunRsaSign("SunRsaSign"), 55 Sun("SUN"), 56 SunEC("SunEC"), 57 SunJSSE("SunJSSE"), 58 SunMSCAPI("SunMSCAPI"); 59 60 final String name; 61 62 Provider(String name) { 63 this.name = name; 64 } 65 } 66 67 static enum SigAlg { 68 MD2withRSA("MD2withRSA"), 69 MD5withRSA("md5withRSA"), 70 71 SHA1withDSA("SHA1withDSA"), 72 SHA224withDSA("SHA224withDSA"), 73 SHA256withDSA("SHA256withDSA"), 74 75 SHA1withRSA("Sha1withrSA"), 76 SHA224withRSA("SHA224withRSA"), 77 SHA256withRSA("SHA256withRSA"), 78 SHA384withRSA("SHA384withRSA"), 79 SHA512withRSA("SHA512withRSA"), 80 81 SHA1withECDSA("SHA1withECDSA"), 82 SHA256withECDSA("SHA256withECDSA"), 83 SHA224withECDSA("SHA224withECDSA"), 84 SHA384withECDSA("SHA384withECDSA"), 85 SHA512withECDSA("SHA512withECDSA"), 86 87 MD5andSHA1withRSA("MD5andSHA1withRSA"); 88 89 final String name; 90 91 SigAlg(String name) { 92 this.name = name; 93 } 94 } 95 96 static class Test { 97 final Provider provider; 98 final KeyAlg keyAlg; 99 final SigAlg sigAlg; 100 final int keySize; 101 102 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider) { 103 this(sigAlg, keyAlg, provider, -1); 104 } 105 106 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize) { 107 this.provider = provider; 108 this.keyAlg = keyAlg; 109 this.sigAlg = sigAlg; 110 this.keySize = keySize; 111 } 112 } 113 114 private static final Test[] tests = { 115 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Default, 1024), 116 new Test(SigAlg.MD2withRSA, KeyAlg.RSA, Provider.Default), 117 new Test(SigAlg.MD5withRSA, KeyAlg.RSA, Provider.Default), 118 new Test(SigAlg.SHA1withRSA, KeyAlg.RSA, Provider.Default), 119 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Sun, 1024), 120 new Test(SigAlg.SHA224withDSA, KeyAlg.DSA, Provider.Sun, 2048), 121 new Test(SigAlg.SHA256withDSA, KeyAlg.DSA, Provider.Sun, 2048), 122 }; 123 124 private static final String str = "to-be-signed"; 125 private static final int N = 3; 126 127 public static void main(String argv[]) { 128 boolean result = Arrays.stream(tests).allMatch((test) -> runTest(test)); 129 if(result) { 130 System.out.println("All tests passed"); 131 } else { 132 throw new RuntimeException("Some tests failed"); 133 } 134 } 135 136 static boolean runTest(Test test) { 137 System.out.format("Test: provider = %s, signature algorithm = %s, " 138 + "key algorithm = %s\n", 139 test.provider, test.sigAlg, test.keyAlg); 140 try { 141 // Generate all private/public key pairs 142 PrivateKey[] privKeys = new PrivateKey[N]; 143 PublicKey[] pubKeys = new PublicKey[N]; 144 PublicKey[] anotherPubKeys = new PublicKey[N]; 145 KeyPairGenerator kpg = KeyPairGenerator.getInstance( 146 test.keyAlg.name); 147 for (int j=0; j < N; j++) { 148 if (test.keySize != -1) { 149 kpg.initialize(test.keySize); 150 } 151 KeyPair kp = kpg.genKeyPair(); 152 KeyPair anotherKp = kpg.genKeyPair(); 153 privKeys[j] = kp.getPrivate(); 154 pubKeys[j] = kp.getPublic(); 155 anotherPubKeys[j] = anotherKp.getPublic(); 156 157 if (Arrays.equals(pubKeys[j].getEncoded(), 158 anotherPubKeys[j].getEncoded())) { 159 System.out.println("Failed: it should not get " 160 + "the same pair of public key"); 161 return false; 162 } 163 } 164 165 Signature signature; 166 if (test.provider != Provider.Default) { 167 signature = Signature.getInstance(test.sigAlg.name, 168 test.provider.name); 169 } else { 170 signature = Signature.getInstance(test.sigAlg.name); 171 } 172 173 // Create a chain of signed objects 174 SignedObject[] objects = new SignedObject[N]; 175 objects[0] = new SignedObject(str, privKeys[0], signature); 176 for (int j = 1; j < N; j++) { 177 objects[j] = new SignedObject(objects[j - 1], privKeys[j], 178 signature); 179 } 180 181 // Verify the chain 182 int n = objects.length - 1; 183 SignedObject object = objects[n]; 184 do { 185 if (!object.verify(pubKeys[n], signature)) { 186 System.out.println("Failed: verification failed, n = " + n); 187 return false; 188 } 189 190 if (object.verify(anotherPubKeys[n], signature)) { 191 System.out.println("Failed: verification should not " 192 + "succeed with wrong public key, n = " + n); 193 return false; 194 } 195 196 object = (SignedObject) object.getObject(); 197 n--; 198 } while (n > 0); 199 200 System.out.println("signed data: " + object.getObject()); 201 if (!str.equals(object.getObject())) { 202 System.out.println("Failed: signed data is not equal to " 203 + "original one"); 204 return false; 205 } 206 207 System.out.println("Test passed"); 208 return true; 209 } catch (NoSuchProviderException nspe) { 210 if (test.provider == Provider.SunMSCAPI 211 && !System.getProperty("os.name").startsWith("Windows")) { 212 System.out.println("SunMSCAPI is available only on Windows: " 213 + nspe); 214 return true; 215 } 216 System.out.println("Unexpected exception: " + nspe); 217 return false; 218 } catch (Exception e) { 219 System.out.println("Unexpected exception: " + e); 220 e.printStackTrace(System.out); 221 return false; 222 } 223 } 224 } 225