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 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 101 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider privider) { 102 this.provider = privider; 103 this.keyAlg = keyAlg; 104 this.sigAlg = sigAlg; 105 } 106 } 107 108 private static final Test[] tests = { 109 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Default), 110 new Test(SigAlg.MD2withRSA, KeyAlg.RSA, Provider.Default), 111 new Test(SigAlg.MD5withRSA, KeyAlg.RSA, Provider.Default), 112 new Test(SigAlg.SHA1withRSA, KeyAlg.RSA, Provider.Default), 113 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Sun), 114 new Test(SigAlg.SHA224withDSA, KeyAlg.DSA, Provider.Sun), 115 new Test(SigAlg.SHA256withDSA, KeyAlg.DSA, Provider.Sun), 116 }; 117 118 private static final String str = "to-be-signed"; 119 private static final int N = 3; 120 121 public static void main(String argv[]) { 122 boolean result = Arrays.stream(tests).allMatch((test) -> runTest(test)); 123 if(result) { 124 System.out.println("All tests passed"); 125 } else { 126 throw new RuntimeException("Some tests failed"); 127 } 128 } 129 130 static boolean runTest(Test test) { 131 System.out.format("Test: provider = %s, signature algorithm = %s, " 132 + "key algorithm = %s\n", 133 test.provider, test.sigAlg, test.keyAlg); 134 try { 135 // Generate all private/public key pairs 136 PrivateKey[] privKeys = new PrivateKey[N]; 137 PublicKey[] pubKeys = new PublicKey[N]; 138 PublicKey[] anotherPubKeys = new PublicKey[N]; 139 KeyPairGenerator kpg = KeyPairGenerator.getInstance( 140 test.keyAlg.name); 141 for (int j=0; j < N; j++) { 142 KeyPair kp = kpg.genKeyPair(); 143 KeyPair anotherKp = kpg.genKeyPair(); 144 privKeys[j] = kp.getPrivate(); 145 pubKeys[j] = kp.getPublic(); 146 anotherPubKeys[j] = anotherKp.getPublic(); 147 148 if (Arrays.equals(pubKeys[j].getEncoded(), 149 anotherPubKeys[j].getEncoded())) { 150 System.out.println("Failed: it should not get " 151 + "the same pair of public key"); 152 return false; 153 } 154 } 155 156 Signature signature; 157 if (test.provider != Provider.Default) { 158 signature = Signature.getInstance(test.sigAlg.name, 159 test.provider.name); 160 } else { 161 signature = Signature.getInstance(test.sigAlg.name); 162 } 163 164 // Create a chain of signed objects 165 SignedObject[] objects = new SignedObject[N]; 166 objects[0] = new SignedObject(str, privKeys[0], signature); 167 for (int j = 1; j < N; j++) { 168 objects[j] = new SignedObject(objects[j - 1], privKeys[j], 169 signature); 170 } 171 172 // Verify the chain 173 int n = objects.length - 1; 174 SignedObject object = objects[n]; 175 do { 176 if (!object.verify(pubKeys[n], signature)) { 177 System.out.println("Failed: verification failed, n = " + n); 178 return false; 179 } 180 181 if (object.verify(anotherPubKeys[n], signature)) { 182 System.out.println("Failed: verification should not " 183 + "succeed with wrong public key, n = " + n); 184 return false; 185 } 186 187 object = (SignedObject) object.getObject(); 188 n--; 189 } while (n > 0); 190 191 System.out.println("signed data: " + object.getObject()); 192 if (!str.equals(object.getObject())) { 193 System.out.println("Failed: signed data is not equal to " 194 + "original one"); 195 return false; 196 } 197 198 System.out.println("Test passed"); 199 return true; 200 } catch (NoSuchProviderException nspe) { 201 if (test.provider == Provider.SunMSCAPI 202 && !System.getProperty("os.name").startsWith("Windows")) { 203 System.out.println("SunMSCAPI is available only on Windows: " 204 + nspe); 205 return true; 206 } 207 System.out.println("Unexpected exception: " + nspe); 208 return false; 209 } catch (Exception e) { 210 System.out.println("Unexpected exception: " + e); 211 e.printStackTrace(System.out); 212 return false; 213 } 214 } 215 } 216