1 /*
2  * Copyright (c) 2021, 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 javax.crypto.SecretKey;
25 import javax.crypto.spec.SecretKeySpec;
26 import java.security.Key;
27 import java.security.KeyFactory;
28 import java.security.KeyPair;
29 import java.security.KeyPairGenerator;
30 import java.security.Provider;
31 import java.security.Security;
32 import java.security.spec.PKCS8EncodedKeySpec;
33 import java.security.spec.X509EncodedKeySpec;
34 import java.util.Arrays;
35 import java.util.LinkedList;
36 import java.util.List;
37 import javax.crypto.KeyGenerator;
38 
39 /*
40  * @test
41  * @bug 8185127
42  * @summary Test key comparison for the Keys generated through KeyGenerator
43  * @run main CompareKeys
44  */
45 public class CompareKeys {
46 
main(String[] args)47     public static void main(String[] args) throws Exception {
48 
49         for (KeygenAlgo alg : getSupportedAlgo("KeyGenerator")) {
50             System.out.printf("Verifying provider %s and algorithm %s%n",
51                     alg.provider().getName(), alg.algoName());
52             SecretKey k = genSecretKey(alg.algoName(), alg.provider());
53             checkKeyEquality(k, copy(alg.algoName(), k));
54         }
55 
56         for (KeygenAlgo alg : getSupportedAlgo("KeyPairGenerator")) {
57             System.out.printf("Verifying provider %s and algorithm %s%n",
58                     alg.provider().getName(), alg.algoName());
59             KeyPair kp = genKeyPair(alg.algoName(), alg.provider());
60             checkKeyPairEquality(kp, copy(alg.algoName(), kp));
61         }
62         System.out.println("Done!");
63     }
64 
65     @SuppressWarnings("preview")
KeygenAlgo(String algoName, Provider provider)66     private record KeygenAlgo(String algoName, Provider provider) {
67 
68     }
69 
checkKeyPairEquality(KeyPair origkp, KeyPair copykp)70     private static void checkKeyPairEquality(KeyPair origkp, KeyPair copykp)
71             throws Exception {
72 
73         checkKeyEquality(origkp.getPrivate(), copykp.getPrivate());
74         checkKeyEquality(origkp.getPublic(), copykp.getPublic());
75     }
76 
77     /**
78      * Compare original Key with another copy.
79      */
checkKeyEquality(Key origKey, Key copyKey)80     private static void checkKeyEquality(Key origKey, Key copyKey) {
81 
82         if ((origKey.equals(copyKey)
83                 && origKey.hashCode() == copyKey.hashCode()
84                 && Arrays.equals(origKey.getEncoded(), copyKey.getEncoded())
85                 && origKey.getFormat().equals(copyKey.getFormat()))) {
86             System.out.printf("%s equality check Passed%n",
87                     origKey.getClass().getName());
88         } else {
89             System.out.println("Result- equals: "
90                     + origKey.equals(copyKey));
91             System.out.println("Result- hashCode: "
92                     + (origKey.hashCode() == copyKey.hashCode()));
93             System.out.println("Result- encoded check: " + Arrays.equals(
94                     origKey.getEncoded(), copyKey.getEncoded()));
95             System.out.println("Result- format check: "
96                     + origKey.getFormat().equals(copyKey.getFormat()));
97             throw new RuntimeException("Key inequality found");
98         }
99     }
100 
copy(String algo, Key key)101     private static Key copy(String algo, Key key) throws Exception {
102 
103         return new SecretKeySpec(key.getEncoded(), algo);
104     }
105 
copy(String algo, KeyPair kp)106     private static KeyPair copy(String algo, KeyPair kp) throws Exception {
107 
108         KeyFactory kf = KeyFactory.getInstance(algo);
109         return new KeyPair(
110                 kf.generatePublic(
111                         new X509EncodedKeySpec(kp.getPublic().getEncoded())),
112                 kf.generatePrivate(
113                         new PKCS8EncodedKeySpec(kp.getPrivate().getEncoded())));
114     }
115 
getSupportedAlgo(String type)116     private static List<KeygenAlgo> getSupportedAlgo(String type)
117             throws Exception {
118 
119         List<KeygenAlgo> kgs = new LinkedList<>();
120         for (Provider p : Security.getProviders()) {
121             for (Provider.Service s : p.getServices()) {
122                 // Ignore the algorithms from the list which require
123                 // pre-initialization to make the Test generic across algorithms.
124                 // SunMSCAPI provider is ignored too because of incompatibilty
125                 // for serialization and with PKCS8EncodedKeySpec for certain
126                 // algorithms like RSA.
127                 if (s.getType().contains(type)
128                         && !((s.getAlgorithm().startsWith("SunTls"))
129                         || s.getProvider().getName().equals("SunMSCAPI"))) {
130                     kgs.add(new KeygenAlgo(s.getAlgorithm(), s.getProvider()));
131                 }
132             }
133         }
134         return kgs;
135     }
136 
genSecretKey(String algoName, Provider provider)137     public static SecretKey genSecretKey(String algoName, Provider provider)
138             throws Exception {
139 
140         return KeyGenerator.getInstance(algoName, provider).generateKey();
141     }
142 
genKeyPair(String algoName, Provider provider)143     public static KeyPair genKeyPair(String algoName, Provider provider)
144             throws Exception {
145 
146         return KeyPairGenerator.getInstance(algoName, provider)
147                 .generateKeyPair();
148     }
149 }
150