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