~ubuntu-branches/ubuntu/precise/classpath/precise

« back to all changes in this revision

Viewing changes to gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java

  • Committer: Bazaar Package Importer
  • Author(s): Michael Koch
  • Date: 2006-05-27 16:11:15 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060527161115-h6e39eposdt5snb6
Tags: 2:0.91-3
* Install header files to /usr/include/classpath.
* debian/control: classpath: Conflict with jamvm < 1.4.3 and
  cacao < 0.96 (Closes: #368172).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* SRPKeyPairGenerator.java -- 
 
2
   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
 
3
 
 
4
This file is a part of GNU Classpath.
 
5
 
 
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.
 
10
 
 
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.
 
15
 
 
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
 
20
 
 
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.
 
25
 
 
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.  */
 
37
 
 
38
 
 
39
package gnu.javax.crypto.key.srp6;
 
40
 
 
41
import gnu.java.security.Registry;
 
42
import gnu.java.security.key.IKeyPairGenerator;
 
43
import gnu.java.security.util.PRNG;
 
44
import gnu.java.security.util.Prime2;
 
45
 
 
46
import java.io.PrintWriter;
 
47
import java.math.BigInteger;
 
48
import java.security.KeyPair;
 
49
import java.security.SecureRandom;
 
50
import java.util.Map;
 
51
 
 
52
/**
 
53
 *
 
54
 *
 
55
 * <p>Reference:</p>
 
56
 * <ol>
 
57
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
 
58
 *    Thomas J. Wu.</li>
 
59
 * </ol>
 
60
 */
 
61
public class SRPKeyPairGenerator implements IKeyPairGenerator
 
62
{
 
63
 
 
64
  // Debugging methods and variables
 
65
  // -------------------------------------------------------------------------
 
66
 
 
67
  private static final String NAME = "srp";
 
68
 
 
69
  private static final boolean DEBUG = false;
 
70
 
 
71
  private static final int debuglevel = 5;
 
72
 
 
73
  private static final PrintWriter err = new PrintWriter(System.out, true);
 
74
 
 
75
  private static void debug(String s)
 
76
  {
 
77
    err.println(">>> " + NAME + ": " + s);
 
78
  }
 
79
 
 
80
  // Constants and variables
 
81
  // -------------------------------------------------------------------------
 
82
 
 
83
  private static final BigInteger ZERO = BigInteger.ZERO;
 
84
 
 
85
  private static final BigInteger ONE = BigInteger.ONE;
 
86
 
 
87
  private static final BigInteger TWO = BigInteger.valueOf(2L);
 
88
 
 
89
  private static final BigInteger THREE = BigInteger.valueOf(3L);
 
90
 
 
91
  /** Property name of the length (Integer) of the modulus (N) of an SRP key. */
 
92
  public static final String MODULUS_LENGTH = "gnu.crypto.srp.L";
 
93
 
 
94
  /** Property name of the Boolean indicating wether or not to use defaults. */
 
95
  public static final String USE_DEFAULTS = "gnu.crypto.srp.use.defaults";
 
96
 
 
97
  /** Property name of the modulus (N) of an SRP key. */
 
98
  public static final String SHARED_MODULUS = "gnu.crypto.srp.N";
 
99
 
 
100
  /** Property name of the generator (g) of an SRP key. */
 
101
  public static final String GENERATOR = "gnu.crypto.srp.g";
 
102
 
 
103
  /** Property name of the user's verifier (v) for a Server SRP key. */
 
104
  public static final String USER_VERIFIER = "gnu.crypto.srp.v";
 
105
 
 
106
  /**
 
107
   * Property name of an optional {@link SecureRandom} instance to use. The
 
108
   * default is to use a classloader singleton from {@link PRNG}.
 
109
   */
 
110
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp.prng";
 
111
 
 
112
  /** Default value for the modulus length. */
 
113
  private static final int DEFAULT_MODULUS_LENGTH = 1024;
 
114
 
 
115
  /** The optional {@link SecureRandom} instance to use. */
 
116
  private SecureRandom rnd = null;
 
117
 
 
118
  /** Bit length of the shared modulus. */
 
119
  private int l;
 
120
 
 
121
  /** The shared public modulus. */
 
122
  private BigInteger N;
 
123
 
 
124
  /** The Field generator. */
 
125
  private BigInteger g;
 
126
 
 
127
  /** The user's verifier MPI. */
 
128
  private BigInteger v;
 
129
 
 
130
  /** Our default source of randomness. */
 
131
  private PRNG prng = null;
 
132
 
 
133
  // Constructor(s)
 
134
  // -------------------------------------------------------------------------
 
135
 
 
136
  // implicit 0-arguments constructor
 
137
 
 
138
  // Class methods
 
139
  // -------------------------------------------------------------------------
 
140
 
 
141
  // Instance methods
 
142
  // -------------------------------------------------------------------------
 
143
 
 
144
  // gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
 
145
 
 
146
  public String name()
 
147
  {
 
148
    return Registry.SRP_KPG;
 
149
  }
 
150
 
 
151
  public void setup(Map attributes)
 
152
  {
 
153
    // do we have a SecureRandom, or should we use our own?
 
154
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
 
155
 
 
156
    N = (BigInteger) attributes.get(SHARED_MODULUS);
 
157
    if (N != null)
 
158
      {
 
159
        l = N.bitLength();
 
160
        g = (BigInteger) attributes.get(GENERATOR);
 
161
        if (g == null)
 
162
          {
 
163
            g = TWO;
 
164
          }
 
165
        SRPAlgorithm.checkParams(N, g);
 
166
      }
 
167
    else
 
168
      { // generate or use default values for N and g
 
169
        Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS);
 
170
        if (useDefaults == null)
 
171
          {
 
172
            useDefaults = Boolean.TRUE;
 
173
          }
 
174
        Integer L = (Integer) attributes.get(MODULUS_LENGTH);
 
175
        l = DEFAULT_MODULUS_LENGTH;
 
176
        if (useDefaults.equals(Boolean.TRUE))
 
177
          {
 
178
            if (L != null)
 
179
              {
 
180
                l = L.intValue();
 
181
                switch (l)
 
182
                  {
 
183
                  case 512:
 
184
                    N = SRPAlgorithm.N_512;
 
185
                    break;
 
186
                  case 640:
 
187
                    N = SRPAlgorithm.N_640;
 
188
                    break;
 
189
                  case 768:
 
190
                    N = SRPAlgorithm.N_768;
 
191
                    break;
 
192
                  case 1024:
 
193
                    N = SRPAlgorithm.N_1024;
 
194
                    break;
 
195
                  case 1280:
 
196
                    N = SRPAlgorithm.N_1280;
 
197
                    break;
 
198
                  case 1536:
 
199
                    N = SRPAlgorithm.N_1536;
 
200
                    break;
 
201
                  case 2048:
 
202
                    N = SRPAlgorithm.N_2048;
 
203
                    break;
 
204
                  default:
 
205
                    throw new IllegalArgumentException(
 
206
                                                       "unknown default shared modulus bit length");
 
207
                  }
 
208
                g = TWO;
 
209
                l = N.bitLength();
 
210
              }
 
211
          }
 
212
        else
 
213
          { // generate new N and g
 
214
            if (L != null)
 
215
              {
 
216
                l = L.intValue();
 
217
                if ((l % 256) != 0 || l < 512 || l > 2048)
 
218
                  {
 
219
                    throw new IllegalArgumentException(
 
220
                                                       "invalid shared modulus bit length");
 
221
                  }
 
222
              }
 
223
          }
 
224
      }
 
225
 
 
226
    // are we using this generator on the server side, or the client side?
 
227
    v = (BigInteger) attributes.get(USER_VERIFIER);
 
228
  }
 
229
 
 
230
  public KeyPair generate()
 
231
  {
 
232
    if (N == null)
 
233
      {
 
234
        BigInteger[] params = generateParameters();
 
235
        BigInteger q = params[0];
 
236
        N = params[1];
 
237
        g = params[2];
 
238
        if (DEBUG && debuglevel > 0)
 
239
          {
 
240
            debug("q: " + q.toString(16));
 
241
            debug("N: " + N.toString(16));
 
242
            debug("g: " + g.toString(16));
 
243
          }
 
244
      }
 
245
 
 
246
    return (v != null ? hostKeyPair() : userKeyPair());
 
247
  }
 
248
 
 
249
  // helper methods ----------------------------------------------------------
 
250
 
 
251
  private synchronized BigInteger[] generateParameters()
 
252
  {
 
253
    // N    A large safe prime (N = 2q+1, where q is prime)
 
254
    // g    A generator modulo N
 
255
    BigInteger q, p, g;
 
256
    byte[] qBytes = new byte[l / 8];
 
257
    do
 
258
      {
 
259
        do
 
260
          {
 
261
            nextRandomBytes(qBytes);
 
262
            q = new BigInteger(1, qBytes);
 
263
            q = q.setBit(0).setBit(l - 2).clearBit(l - 1);
 
264
          }
 
265
        while (!Prime2.isProbablePrime(q));
 
266
        p = q.multiply(TWO).add(ONE);
 
267
      }
 
268
    while (p.bitLength() != l || !Prime2.isProbablePrime(p));
 
269
 
 
270
    // compute g. from FIPS-186, Appendix 4: e == 2
 
271
    BigInteger p_minus_1 = p.subtract(ONE);
 
272
    g = TWO;
 
273
    // Set h = any integer, where 1 < h < p - 1 and
 
274
    // h differs from any value previously tried
 
275
    for (BigInteger h = TWO; h.compareTo(p_minus_1) < 0; h = h.add(ONE))
 
276
      {
 
277
        // Set g = h**2 mod p
 
278
        g = h.modPow(TWO, p);
 
279
        // If g = 1, go to step 3
 
280
        if (!g.equals(ONE))
 
281
          {
 
282
            break;
 
283
          }
 
284
      }
 
285
 
 
286
    return new BigInteger[] { q, p, g };
 
287
  }
 
288
 
 
289
  private KeyPair hostKeyPair()
 
290
  {
 
291
    byte[] bBytes = new byte[(l + 7) / 8];
 
292
    BigInteger b, B;
 
293
    do
 
294
      {
 
295
        do
 
296
          {
 
297
            nextRandomBytes(bBytes);
 
298
            b = new BigInteger(1, bBytes);
 
299
          }
 
300
        while (b.compareTo(ONE) <= 0 || b.compareTo(N) >= 0);
 
301
        B = THREE.multiply(v).add(g.modPow(b, N)).mod(N);
 
302
      }
 
303
    while (B.compareTo(ZERO) == 0 || B.compareTo(N) >= 0);
 
304
 
 
305
    KeyPair result = new KeyPair(
 
306
                                 new SRPPublicKey(new BigInteger[] { N, g, B }),
 
307
                                 new SRPPrivateKey(new BigInteger[] { N, g, b,
 
308
                                                                     v }));
 
309
    return result;
 
310
  }
 
311
 
 
312
  private KeyPair userKeyPair()
 
313
  {
 
314
    byte[] aBytes = new byte[(l + 7) / 8];
 
315
    BigInteger a, A;
 
316
    do
 
317
      {
 
318
        do
 
319
          {
 
320
            nextRandomBytes(aBytes);
 
321
            a = new BigInteger(1, aBytes);
 
322
          }
 
323
        while (a.compareTo(ONE) <= 0 || a.compareTo(N) >= 0);
 
324
        A = g.modPow(a, N);
 
325
      }
 
326
    while (A.compareTo(ZERO) == 0 || A.compareTo(N) >= 0);
 
327
 
 
328
    KeyPair result = new KeyPair(
 
329
                                 new SRPPublicKey(new BigInteger[] { N, g, A }),
 
330
                                 new SRPPrivateKey(new BigInteger[] { N, g, a }));
 
331
    return result;
 
332
  }
 
333
 
 
334
  private void nextRandomBytes(byte[] buffer)
 
335
  {
 
336
    if (rnd != null)
 
337
      {
 
338
        rnd.nextBytes(buffer);
 
339
      }
 
340
    else
 
341
      getDefaultPRNG().nextBytes(buffer);
 
342
  }
 
343
 
 
344
  private PRNG getDefaultPRNG()
 
345
  {
 
346
    if (prng == null)
 
347
      prng = PRNG.getInstance();
 
348
 
 
349
    return prng;
 
350
  }
 
351
}