1 /* 2 * Copyright (c) 2005, 2016, 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 6330287 6331386 7044060 27 * @summary verify that DHKeyPairGenerator returns keys of the expected size 28 * (modulus and exponent) 29 * -and- 30 * DHKeyPairGenerator is using BigInteger.setBit 31 * @author Andreas Sterbenz 32 */ 33 34 import java.math.BigInteger; 35 import java.util.Arrays; 36 37 import java.security.*; 38 import javax.crypto.*; 39 import javax.crypto.interfaces.*; 40 import javax.crypto.spec.*; 41 42 /* 43 * NOTE: BigInteger's bitlength() doesn't report leading zeros, only 44 * the number of bits needed to actually represent the number. i.e. 45 * 46 * new BigInteger("4").bitLength() = 3 47 * 48 * Since the private key x can vary 1 <= x <= p-2, we can't do any 49 * bitlength-based calculations here. But we can check that p conforms 50 * as expected. 51 * 52 * If not specified, we're currently using an lsize of Math.max(384, psize/2). 53 */ 54 public class TestExponentSize { 55 56 /* 57 * Sizes and values for various lengths. 58 */ 59 private enum Sizes { 60 two56(256), three84(384), five12(512), seven68(768), ten24(1024), 61 twenty48(2048); 62 63 private final int intSize; 64 private final BigInteger bigIntValue; 65 Sizes(int size)66 Sizes(int size) { 67 intSize = size; 68 byte [] bits = new byte[intSize/8]; 69 Arrays.fill(bits, (byte)0xff); 70 bigIntValue = new BigInteger(1, bits); 71 } 72 getIntSize()73 int getIntSize() { 74 return intSize; 75 } 76 getBigIntValue()77 BigInteger getBigIntValue() { 78 return bigIntValue; 79 } 80 } 81 main(String[] args)82 public static void main(String[] args) throws Exception { 83 KeyPair kp; 84 KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", "SunJCE"); 85 86 // Sun's default uses a default psize of 2048 and 87 // lsize of (pSize / 2) but at least 384 bits 88 kp = kpg.generateKeyPair(); 89 checkKeyPair(kp, Sizes.twenty48, Sizes.ten24); 90 91 DHPublicKey publicKey = (DHPublicKey)kp.getPublic(); 92 BigInteger p = publicKey.getParams().getP(); 93 BigInteger g = publicKey.getParams().getG(); 94 95 kpg.initialize(Sizes.ten24.getIntSize()); 96 kp = kpg.generateKeyPair(); 97 checkKeyPair(kp, Sizes.ten24, Sizes.five12); 98 99 kpg.initialize(new DHParameterSpec(p, g, Sizes.ten24.getIntSize())); 100 kp = kpg.generateKeyPair(); 101 checkKeyPair(kp, Sizes.twenty48, Sizes.ten24); 102 103 kpg.initialize(new DHParameterSpec(p, g, Sizes.five12.getIntSize())); 104 kp = kpg.generateKeyPair(); 105 checkKeyPair(kp, Sizes.twenty48, Sizes.five12); 106 107 kpg.initialize(new DHParameterSpec(p, g, Sizes.two56.getIntSize())); 108 kp = kpg.generateKeyPair(); 109 checkKeyPair(kp, Sizes.twenty48, Sizes.two56); 110 111 kpg.initialize(Sizes.five12.getIntSize()); 112 kp = kpg.generateKeyPair(); 113 checkKeyPair(kp, Sizes.five12, Sizes.three84); 114 115 kpg.initialize(Sizes.seven68.getIntSize()); 116 kp = kpg.generateKeyPair(); 117 checkKeyPair(kp, Sizes.seven68, Sizes.three84); 118 119 // test w/ only pSize 120 kpg.initialize(Sizes.twenty48.getIntSize()); 121 kp = kpg.generateKeyPair(); 122 checkKeyPair(kp, Sizes.twenty48, Sizes.ten24); 123 124 publicKey = (DHPublicKey)kp.getPublic(); 125 p = publicKey.getParams().getP(); 126 g = publicKey.getParams().getG(); 127 128 // test w/ all values specified 129 kpg.initialize(new DHParameterSpec(p, g, Sizes.five12.getIntSize())); 130 kp = kpg.generateKeyPair(); 131 checkKeyPair(kp, Sizes.twenty48, Sizes.five12); 132 133 System.out.println("OK"); 134 } 135 checkKeyPair(KeyPair kp, Sizes modulusSize, Sizes exponentSize)136 private static void checkKeyPair(KeyPair kp, Sizes modulusSize, 137 Sizes exponentSize) throws Exception { 138 139 System.out.println("Checking (" + modulusSize + ", " + 140 exponentSize + ")"); 141 DHPrivateKey privateKey = (DHPrivateKey)kp.getPrivate(); 142 BigInteger p = privateKey.getParams().getP(); 143 BigInteger x = privateKey.getX(); 144 145 if (p.bitLength() != modulusSize.getIntSize()) { 146 throw new Exception("Invalid modulus size: " + p.bitLength()); 147 } 148 149 if (x.bitLength() > exponentSize.getIntSize()) { 150 throw new Exception("X has more bits than expected: " + 151 x.bitLength()); 152 } 153 154 BigInteger pMinus2 = 155 p.subtract(BigInteger.ONE).subtract(BigInteger.ONE); 156 157 if ((x.compareTo(BigInteger.ONE) < 0 || 158 (x.compareTo(pMinus2)) > 0)) { 159 throw new Exception( 160 "X outside range 1<=x<p-2: x: " + x + " p: " + p); 161 } 162 } 163 } 164