1 /* 2 * Copyright (c) 2018, 2020, 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/othervm -Djdk.sunec.disableNative=false KeySizeTest ECDH SunEC EC 128 41 * @run main/othervm -Djdk.sunec.disableNative=false KeySizeTest ECDH SunEC EC 192 42 * @run main/othervm 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 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 */ 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 */ 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 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 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 }