1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53:
54: import ;
55: import ;
56:
57:
67: public class GnuDHKeyPairGenerator
68: implements IKeyPairGenerator
69: {
70: private static final Logger log = Configuration.DEBUG ?
71: Logger.getLogger(GnuDHKeyPairGenerator.class.getName()) : null;
72:
73:
77: public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dh.prng";
78:
82: public static final String DH_PARAMETERS = "gnu.crypto.dh.params";
83:
84: public static final String PRIME_SIZE = "gnu.crypto.dh.L";
85:
86: public static final String EXPONENT_SIZE = "gnu.crypto.dh.m";
87:
92: public static final String PREFERRED_ENCODING_FORMAT = "gnu.crypto.dh.encoding";
93:
94: public static final int DEFAULT_PRIME_SIZE = 512;
95:
96: public static final int DEFAULT_EXPONENT_SIZE = 160;
97:
98: private static final int DEFAULT_ENCODING_FORMAT = Registry.RAW_ENCODING_ID;
99:
100: private SecureRandom rnd;
101:
102: private int l;
103:
104: private int m;
105: private BigInteger seed;
106: private BigInteger counter;
107: private BigInteger q;
108: private BigInteger p;
109: private BigInteger j;
110: private BigInteger g;
111:
112: private PRNG prng = null;
113:
114: private int preferredFormat;
115:
116:
117:
118: public String name()
119: {
120: return Registry.DH_KPG;
121: }
122:
123: public void setup(Map attributes)
124: {
125:
126: rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
127:
128:
129: Object params = attributes.get(DH_PARAMETERS);
130:
131: if (params instanceof DHGenParameterSpec)
132: {
133: DHGenParameterSpec jceSpec = (DHGenParameterSpec) params;
134: l = jceSpec.getPrimeSize();
135: m = jceSpec.getExponentSize();
136: }
137: else if (params instanceof DHParameterSpec)
138: {
139:
140:
141:
142: DHParameterSpec jceSpec = (DHParameterSpec) params;
143: p = jceSpec.getP();
144: g = jceSpec.getG();
145: l = p.bitLength();
146: m = jceSpec.getL();
147:
148:
149: if (m == 0)
150: m = l;
151: }
152: else
153: {
154: Integer bi = (Integer) attributes.get(PRIME_SIZE);
155: l = (bi == null ? DEFAULT_PRIME_SIZE : bi.intValue());
156: bi = (Integer) attributes.get(EXPONENT_SIZE);
157: m = (bi == null ? DEFAULT_EXPONENT_SIZE : bi.intValue());
158: }
159: if ((l % 256) != 0 || l < DEFAULT_PRIME_SIZE)
160: throw new IllegalArgumentException("invalid modulus size");
161: if ((m % 8) != 0 || m < DEFAULT_EXPONENT_SIZE)
162: throw new IllegalArgumentException("invalid exponent size");
163: if (m > l)
164: throw new IllegalArgumentException("exponent size > modulus size");
165:
166: Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
167: preferredFormat = formatID == null ? DEFAULT_ENCODING_FORMAT
168: : formatID.intValue();
169: }
170:
171: public KeyPair generate()
172: {
173: if (p == null)
174: {
175: BigInteger[] params = new RFC2631(m, l, rnd).generateParameters();
176: seed = params[RFC2631.DH_PARAMS_SEED];
177: counter = params[RFC2631.DH_PARAMS_COUNTER];
178: q = params[RFC2631.DH_PARAMS_Q];
179: p = params[RFC2631.DH_PARAMS_P];
180: j = params[RFC2631.DH_PARAMS_J];
181: g = params[RFC2631.DH_PARAMS_G];
182: if (Configuration.DEBUG)
183: {
184: log.fine("seed: 0x" + seed.toString(16));
185: log.fine("counter: " + counter.intValue());
186: log.fine("q: 0x" + q.toString(16));
187: log.fine("p: 0x" + p.toString(16));
188: log.fine("j: 0x" + j.toString(16));
189: log.fine("g: 0x" + g.toString(16));
190: }
191: }
192:
193: BigInteger q_minus_1 = null;
194: if (q != null)
195: q_minus_1 = q.subtract(BigInteger.ONE);
196:
197:
198: byte[] mag = new byte[(m + 7) / 8];
199: BigInteger x;
200: while (true)
201: {
202: nextRandomBytes(mag);
203: x = new BigInteger(1, mag);
204: if (x.bitLength() == m && x.compareTo(BigInteger.ONE) > 0
205: && (q_minus_1 == null || x.compareTo(q_minus_1) < 0))
206: break;
207: }
208: BigInteger y = g.modPow(x, p);
209: PrivateKey secK = new GnuDHPrivateKey(preferredFormat, q, p, g, x);
210: PublicKey pubK = new GnuDHPublicKey(preferredFormat, q, p, g, y);
211: return new KeyPair(pubK, secK);
212: }
213:
214:
219: private void nextRandomBytes(byte[] buffer)
220: {
221: if (rnd != null)
222: rnd.nextBytes(buffer);
223: else
224: getDefaultPRNG().nextBytes(buffer);
225: }
226:
227: private PRNG getDefaultPRNG()
228: {
229: if (prng == null)
230: prng = PRNG.getInstance();
231:
232: return prng;
233: }
234: }