Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / gnu / javax / crypto / key / dh / RFC2631.java
blobd6e30b4bc520995ac1b5102b0b7a978c798208c2
1 /* RFC2631.java --
2 Copyright (C) 2003, 2006 Free Software Foundation, Inc.
4 This file is a part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 USA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.javax.crypto.key.dh;
41 import gnu.java.security.hash.Sha160;
42 import gnu.java.security.util.PRNG;
43 import gnu.java.security.util.Prime2;
45 import java.math.BigInteger;
46 import java.security.SecureRandom;
48 /**
49 * <p>An implementation of the Diffie-Hellman parameter generation as defined in
50 * RFC-2631.</p>
52 * <p>Reference:</p>
53 * <ol>
54 * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
55 * Agreement Method</a><br>
56 * Eric Rescorla.</li>
57 * </ol>
59 public class RFC2631
62 // Constants and variables
63 // -------------------------------------------------------------------------
65 public static final int DH_PARAMS_SEED = 0;
67 public static final int DH_PARAMS_COUNTER = 1;
69 public static final int DH_PARAMS_Q = 2;
71 public static final int DH_PARAMS_P = 3;
73 public static final int DH_PARAMS_J = 4;
75 public static final int DH_PARAMS_G = 5;
77 private static final BigInteger TWO = BigInteger.valueOf(2L);
79 /** The SHA instance to use. */
80 private Sha160 sha = new Sha160();
82 /** Length of private modulus and of q. */
83 private int m;
85 /** Length of public modulus p. */
86 private int L;
88 /** The optional {@link SecureRandom} instance to use. */
89 private SecureRandom rnd = null;
91 /** Our default source of randomness. */
92 private PRNG prng = null;
94 // Constructor(s)
95 // -------------------------------------------------------------------------
97 public RFC2631(int m, int L, SecureRandom rnd)
99 super();
101 this.m = m;
102 this.L = L;
103 this.rnd = rnd;
106 // Class methods
107 // -------------------------------------------------------------------------
109 // Instance methods
110 // -------------------------------------------------------------------------
112 public BigInteger[] generateParameters()
114 int i, j, counter;
115 byte[] u1, u2, v;
116 byte[] seedBytes = new byte[m / 8];
117 BigInteger SEED, U, q, R, V, W, X, p, g;
118 // start by genrating p and q, where q is of length m and p is of length L
119 // 1. Set m' = m/160 where / represents integer division with rounding
120 // upwards. I.e. 200/160 = 2.
121 int m_ = (m + 159) / 160;
122 // 2. Set L'= L/160
123 int L_ = (L + 159) / 160;
124 // 3. Set N'= L/1024
125 int N_ = (L + 1023) / 1024;
126 algorithm: while (true)
128 step4: while (true)
130 // 4. Select an arbitrary bit string SEED such that length of SEED >= m
131 nextRandomBytes(seedBytes);
132 SEED = new BigInteger(1, seedBytes).setBit(m - 1).setBit(0);
133 // 5. Set U = 0
134 U = BigInteger.ZERO;
135 // 6. For i = 0 to m' - 1
136 // U = U + (SHA1[SEED + i] XOR SHA1[(SEED + m' + i)) * 2^(160 * i)
137 // Note that for m=160, this reduces to the algorithm of [FIPS-186]
138 // U = SHA1[SEED] XOR SHA1[(SEED+1) mod 2^160 ].
139 for (i = 0; i < m_; i++)
141 u1 = SEED.add(BigInteger.valueOf(i)).toByteArray();
142 u2 = SEED.add(BigInteger.valueOf(m_ + i)).toByteArray();
143 sha.update(u1, 0, u1.length);
144 u1 = sha.digest();
145 sha.update(u2, 0, u2.length);
146 u2 = sha.digest();
147 for (j = 0; j < u1.length; j++)
149 u1[j] ^= u2[j];
151 U = U.add(new BigInteger(1, u1).multiply(TWO.pow(160 * i)));
153 // 5. Form q from U by computing U mod (2^m) and setting the most
154 // significant bit (the 2^(m-1) bit) and the least significant bit to
155 // 1. In terms of boolean operations, q = U OR 2^(m-1) OR 1. Note
156 // that 2^(m-1) < q < 2^m
157 q = U.setBit(m - 1).setBit(0);
158 // 6. Use a robust primality algorithm to test whether q is prime.
159 // 7. If q is not prime then go to 4.
160 if (Prime2.isProbablePrime(q))
162 break step4;
165 // 8. Let counter = 0
166 counter = 0;
167 step9: while (true)
169 // 9. Set R = seed + 2*m' + (L' * counter)
170 R = SEED.add(BigInteger.valueOf(2 * m_)).add(
171 BigInteger.valueOf(L_
172 * counter));
173 // 10. Set V = 0
174 V = BigInteger.ZERO;
175 // 12. For i = 0 to L'-1 do: V = V + SHA1(R + i) * 2^(160 * i)
176 for (i = 0; i < L_; i++)
178 v = R.toByteArray();
179 sha.update(v, 0, v.length);
180 v = sha.digest();
181 V = V.add(new BigInteger(1, v).multiply(TWO.pow(160 * i)));
183 // 13. Set W = V mod 2^L
184 W = V.mod(TWO.pow(L));
185 // 14. Set X = W OR 2^(L-1)
186 // Note that 0 <= W < 2^(L-1) and hence X >= 2^(L-1)
187 X = W.setBit(L - 1);
188 // 15. Set p = X - (X mod (2*q)) + 1
189 p = X.add(BigInteger.ONE).subtract(X.mod(TWO.multiply(q)));
190 // 16. If p > 2^(L-1) use a robust primality test to test whether p is
191 // prime. Else go to 18.
192 //17. If p is prime output p, q, seed, counter and stop.
193 if (Prime2.isProbablePrime(p))
195 break algorithm;
197 // 18. Set counter = counter + 1
198 counter++;
199 // 19. If counter < (4096 * N) then go to 8.
200 // 20. Output "failure"
201 if (counter >= 4096 * N_)
203 continue algorithm;
208 // compute g. from FIPS-186, Appendix 4:
209 // 1. Generate p and q as specified in Appendix 2.
210 // 2. Let e = (p - 1) / q
211 BigInteger e = p.subtract(BigInteger.ONE).divide(q);
212 BigInteger h = TWO;
213 BigInteger p_minus_1 = p.subtract(BigInteger.ONE);
214 g = TWO;
215 // 3. Set h = any integer, where 1 < h < p - 1 and h differs from any
216 // value previously tried
217 for (; h.compareTo(p_minus_1) < 0; h = h.add(BigInteger.ONE))
219 // 4. Set g = h**e mod p
220 g = h.modPow(e, p);
221 // 5. If g = 1, go to step 3
222 if (!g.equals(BigInteger.ONE))
224 break;
228 return new BigInteger[] { SEED, BigInteger.valueOf(counter), q, p, e, g };
231 // helper methods ----------------------------------------------------------
234 * <p>Fills the designated byte array with random data.</p>
236 * @param buffer the byte array to fill with random data.
238 private void nextRandomBytes(byte[] buffer)
240 if (rnd != null)
242 rnd.nextBytes(buffer);
244 else
245 getDefaultPRNG().nextBytes(buffer);
248 private PRNG getDefaultPRNG()
250 if (prng == null)
251 prng = PRNG.getInstance();
253 return prng;