1 /*
2  * Copyright (c) 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  /*
25  * @test
26  * @bug 8184359
27  * @summary KeyLength support test for DiffieHellman, EC, XDH.
28  *  Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <keyLen>
29  * @library /test/lib
30  * @build jdk.test.lib.Convert
31  * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 512
32  * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 768
33  * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 832
34  * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 1024
35  * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 2048
36  * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 3072
37  * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 4096
38  * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 6144
39  * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 8192
40  * @run main KeySizeTest ECDH SunEC EC 128
41  * @run main KeySizeTest ECDH SunEC EC 192
42  * @run main KeySizeTest ECDH SunEC EC 256
43  * @run main KeySizeTest XDH SunEC XDH 255
44  * @run main KeySizeTest XDH SunEC XDH 448
45  */
46 import java.math.BigInteger;
47 import java.security.KeyFactory;
48 import java.security.KeyPair;
49 import java.security.KeyPairGenerator;
50 import java.security.interfaces.ECPrivateKey;
51 import java.security.interfaces.ECPublicKey;
52 import java.security.interfaces.XECPrivateKey;
53 import java.security.interfaces.XECPublicKey;
54 import java.security.spec.PKCS8EncodedKeySpec;
55 import java.security.spec.X509EncodedKeySpec;
56 import java.security.spec.NamedParameterSpec;
57 import java.util.Arrays;
58 import javax.crypto.KeyAgreement;
59 import javax.crypto.interfaces.DHPrivateKey;
60 import javax.crypto.interfaces.DHPublicKey;
61 import jdk.test.lib.Convert;
62 
63 public class KeySizeTest {
64 
main(String[] args)65     public static void main(String[] args) throws Exception {
66 
67         String kaAlgo = args[0];
68         String provider = args[1];
69         String kpgAlgo = args[2];
70         int keySize = Integer.parseInt(args[3]);
71         testKeyAgreement(provider, kaAlgo, kpgAlgo, keySize);
72     }
73 
74     /**
75      * Perform KeyAgreement operation.
76      */
testKeyAgreement(String provider, String kaAlgo, String kpgAlgo, int keySize)77     private static void testKeyAgreement(String provider, String kaAlgo,
78             String kpgAlgo, int keySize) throws Exception {
79 
80         KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
81         kpg.initialize(keySize);
82         KeyPair kp = kpg.generateKeyPair();
83         // Test standard Key attributes.
84         testKeyAttributes(provider, kpgAlgo, kp, keySize);
85         // Test KeyAgreement.
86         KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider);
87         ka.init(kp.getPrivate());
88         ka.doPhase(kp.getPublic(), true);
89         ka.generateSecret();
90     }
91 
92     /**
93      * Test standard Key attributes.
94      */
testKeyAttributes(String provider, String kpgAlgo, KeyPair kp, int keySize)95     private static void testKeyAttributes(String provider, String kpgAlgo,
96             KeyPair kp, int keySize) throws Exception {
97 
98         KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
99         switch (kpgAlgo) {
100             case "DiffieHellman":
101                 // Verify PrivateKey attributes.
102                 DHPrivateKey dhPri = (DHPrivateKey) kp.getPrivate();
103                 BigInteger p = dhPri.getParams().getP();
104                 if (p.bitLength() != keySize) {
105                     throw new Exception(String.format("Invalid modulus size: "
106                             + "%s/%s", p.bitLength(), keySize));
107                 }
108                 if (!p.isProbablePrime(128)) {
109                     throw new Exception("The modulus is composite!");
110                 }
111                 PKCS8EncodedKeySpec dhPriSpec
112                         = new PKCS8EncodedKeySpec(dhPri.getEncoded());
113                 DHPrivateKey dhPriDecod
114                         = (DHPrivateKey) kf.generatePrivate(dhPriSpec);
115                 equals(dhPri.getX(), dhPriDecod.getX());
116                 equals(dhPri.getFormat(), dhPriDecod.getFormat());
117                 equals(dhPri.getEncoded(), dhPriDecod.getEncoded());
118                 equals(dhPri.getParams().getG(), dhPriDecod.getParams().getG());
119                 equals(dhPri.getParams().getL(), dhPriDecod.getParams().getL());
120                 equals(dhPri.getParams().getP(), dhPriDecod.getParams().getP());
121 
122                 // Verify PublicKey attributes.
123                 DHPublicKey dhPub = (DHPublicKey) kp.getPublic();
124                 p = dhPub.getParams().getP();
125                 if (p.bitLength() != keySize) {
126                     throw new Exception(String.format("Invalid modulus size: "
127                             + "%s/%s", p.bitLength(), keySize));
128                 }
129                 X509EncodedKeySpec dhPubSpec
130                         = new X509EncodedKeySpec(dhPub.getEncoded());
131                 DHPublicKey dhPubDecod
132                         = (DHPublicKey) kf.generatePublic(dhPubSpec);
133                 equals(dhPub.getY(), dhPubDecod.getY());
134                 equals(dhPub.getFormat(), dhPubDecod.getFormat());
135                 equals(dhPub.getEncoded(), dhPubDecod.getEncoded());
136                 equals(dhPub.getParams().getG(), dhPubDecod.getParams().getG());
137                 equals(dhPub.getParams().getL(), dhPubDecod.getParams().getL());
138                 equals(dhPub.getParams().getP(), dhPubDecod.getParams().getP());
139 
140                 BigInteger left = BigInteger.ONE;
141                 BigInteger right = p.subtract(BigInteger.ONE);
142                 BigInteger x = dhPri.getX();
143                 if ((x.compareTo(left) <= 0) || (x.compareTo(right) >= 0)) {
144                     throw new Exception(
145                             "X outside range [2, p - 2]: x: " + x + " p: " + p);
146                 }
147                 BigInteger y = dhPub.getY();
148                 if ((y.compareTo(left) <= 0) || (y.compareTo(right) >= 0)) {
149                     throw new Exception(
150                             "Y outside range [2, p - 2]: x: " + x + " p: " + p);
151                 }
152                 break;
153             case "EC":
154                 // Verify PrivateKey attributes.
155                 ECPrivateKey ecPriv = (ECPrivateKey) kp.getPrivate();
156                 PKCS8EncodedKeySpec ecPriSpec
157                         = new PKCS8EncodedKeySpec(ecPriv.getEncoded());
158                 ECPrivateKey ecPriDecod
159                         = (ECPrivateKey) kf.generatePrivate(ecPriSpec);
160                 equals(ecPriv.getS(), ecPriDecod.getS());
161                 equals(ecPriv.getFormat(), ecPriDecod.getFormat());
162                 equals(ecPriv.getEncoded(), ecPriDecod.getEncoded());
163                 equals(ecPriv.getParams().getCofactor(),
164                         ecPriDecod.getParams().getCofactor());
165                 equals(ecPriv.getParams().getCurve(),
166                         ecPriDecod.getParams().getCurve());
167                 equals(ecPriv.getParams().getGenerator(),
168                         ecPriDecod.getParams().getGenerator());
169                 equals(ecPriv.getParams().getOrder(),
170                         ecPriDecod.getParams().getOrder());
171 
172                 // Verify PublicKey attributes.
173                 ECPublicKey ecPub = (ECPublicKey) kp.getPublic();
174                 X509EncodedKeySpec ecPubSpec
175                         = new X509EncodedKeySpec(ecPub.getEncoded());
176                 ECPublicKey ecPubDecod
177                         = (ECPublicKey) kf.generatePublic(ecPubSpec);
178                 equals(ecPub.getW(), ecPubDecod.getW());
179                 equals(ecPub.getFormat(), ecPubDecod.getFormat());
180                 equals(ecPub.getEncoded(), ecPubDecod.getEncoded());
181                 equals(ecPub.getParams().getCofactor(),
182                         ecPubDecod.getParams().getCofactor());
183                 equals(ecPub.getParams().getCurve(),
184                         ecPubDecod.getParams().getCurve());
185                 equals(ecPub.getParams().getGenerator(),
186                         ecPubDecod.getParams().getGenerator());
187                 equals(ecPub.getParams().getOrder(),
188                         ecPubDecod.getParams().getOrder());
189                 break;
190             case "XDH":
191                 // Verify PrivateKey attributes.
192                 XECPrivateKey xdhPri = (XECPrivateKey) kp.getPrivate();
193                 PKCS8EncodedKeySpec xdhPriSpec
194                         = new PKCS8EncodedKeySpec(xdhPri.getEncoded());
195                 XECPrivateKey xdhPriDec
196                         = (XECPrivateKey) kf.generatePrivate(xdhPriSpec);
197                 equals(xdhPri.getScalar().get(), xdhPriDec.getScalar().get());
198                 equals(xdhPri.getFormat(), xdhPriDec.getFormat());
199                 equals(xdhPri.getEncoded(), xdhPriDec.getEncoded());
200                 equals(((NamedParameterSpec) xdhPri.getParams()).getName(),
201                         ((NamedParameterSpec) xdhPriDec.getParams()).getName());
202 
203                 // Verify PublicKey attributes.
204                 XECPublicKey xdhPub = (XECPublicKey) kp.getPublic();
205                 X509EncodedKeySpec xdhPubSpec
206                         = new X509EncodedKeySpec(xdhPub.getEncoded());
207                 XECPublicKey xdhPubDec
208                         = (XECPublicKey) kf.generatePublic(xdhPubSpec);
209                 equals(xdhPub.getU(), xdhPubDec.getU());
210                 equals(xdhPub.getFormat(), xdhPubDec.getFormat());
211                 equals(xdhPub.getEncoded(), xdhPubDec.getEncoded());
212                 equals(((NamedParameterSpec) xdhPub.getParams()).getName(),
213                         ((NamedParameterSpec) xdhPubDec.getParams()).getName());
214                 break;
215             default:
216                 throw new RuntimeException("Invalid Algo name " + kpgAlgo);
217         }
218     }
219 
equals(Object actual, Object expected)220     private static boolean equals(Object actual, Object expected) {
221         boolean equals = actual.equals(expected);
222         if (!equals) {
223             throw new RuntimeException(String.format("Actual: %s, Expected: %s",
224                     actual, expected));
225         }
226         return equals;
227     }
228 
equals(byte[] actual, byte[] expected)229     private static boolean equals(byte[] actual, byte[] expected) {
230         boolean equals = Arrays.equals(actual, expected);
231         if (!equals) {
232             throw new RuntimeException(String.format("Actual array: %s, "
233                     + "Expected array:%s", Convert.byteArrayToHexString(actual),
234                     Convert.byteArrayToHexString(expected)));
235         }
236         return equals;
237     }
238 }
239