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:
52:
59: public class SRPKeyPairGenerator
60: implements IKeyPairGenerator
61: {
62: private static final Logger log = Logger.getLogger(SRPKeyPairGenerator.class.getName());
63: private static final BigInteger ZERO = BigInteger.ZERO;
64: private static final BigInteger ONE = BigInteger.ONE;
65: private static final BigInteger TWO = BigInteger.valueOf(2L);
66: private static final BigInteger THREE = BigInteger.valueOf(3L);
67:
68: public static final String MODULUS_LENGTH = "gnu.crypto.srp.L";
69:
70: public static final String USE_DEFAULTS = "gnu.crypto.srp.use.defaults";
71:
72: public static final String SHARED_MODULUS = "gnu.crypto.srp.N";
73:
74: public static final String GENERATOR = "gnu.crypto.srp.g";
75:
76: public static final String USER_VERIFIER = "gnu.crypto.srp.v";
77:
81: public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp.prng";
82:
83: private static final int DEFAULT_MODULUS_LENGTH = 1024;
84:
85: private SecureRandom rnd = null;
86:
87: private int l;
88:
89: private BigInteger N;
90:
91: private BigInteger g;
92:
93: private BigInteger v;
94:
95: private PRNG prng = null;
96:
97:
98:
99: public String name()
100: {
101: return Registry.SRP_KPG;
102: }
103:
104: public void setup(Map attributes)
105: {
106:
107: rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
108: N = (BigInteger) attributes.get(SHARED_MODULUS);
109: if (N != null)
110: {
111: l = N.bitLength();
112: g = (BigInteger) attributes.get(GENERATOR);
113: if (g == null)
114: g = TWO;
115: SRPAlgorithm.checkParams(N, g);
116: }
117: else
118: {
119: Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS);
120: if (useDefaults == null)
121: useDefaults = Boolean.TRUE;
122: Integer L = (Integer) attributes.get(MODULUS_LENGTH);
123: l = DEFAULT_MODULUS_LENGTH;
124: if (useDefaults.equals(Boolean.TRUE))
125: {
126: if (L != null)
127: {
128: l = L.intValue();
129: switch (l)
130: {
131: case 512:
132: N = SRPAlgorithm.N_512;
133: break;
134: case 640:
135: N = SRPAlgorithm.N_640;
136: break;
137: case 768:
138: N = SRPAlgorithm.N_768;
139: break;
140: case 1024:
141: N = SRPAlgorithm.N_1024;
142: break;
143: case 1280:
144: N = SRPAlgorithm.N_1280;
145: break;
146: case 1536:
147: N = SRPAlgorithm.N_1536;
148: break;
149: case 2048:
150: N = SRPAlgorithm.N_2048;
151: break;
152: default:
153: throw new IllegalArgumentException(
154: "unknown default shared modulus bit length");
155: }
156: g = TWO;
157: l = N.bitLength();
158: }
159: }
160: else
161: {
162: if (L != null)
163: {
164: l = L.intValue();
165: if ((l % 256) != 0 || l < 512 || l > 2048)
166: throw new IllegalArgumentException(
167: "invalid shared modulus bit length");
168: }
169: }
170: }
171:
172: v = (BigInteger) attributes.get(USER_VERIFIER);
173: }
174:
175: public KeyPair generate()
176: {
177: if (N == null)
178: {
179: BigInteger[] params = generateParameters();
180: BigInteger q = params[0];
181: N = params[1];
182: g = params[2];
183: if (Configuration.DEBUG)
184: {
185: log.fine("q: " + q.toString(16));
186: log.fine("N: " + N.toString(16));
187: log.fine("g: " + g.toString(16));
188: }
189: }
190: return (v != null ? hostKeyPair() : userKeyPair());
191: }
192:
193: private synchronized BigInteger[] generateParameters()
194: {
195:
196:
197: BigInteger q, p, g;
198: byte[] qBytes = new byte[l / 8];
199: do
200: {
201: do
202: {
203: nextRandomBytes(qBytes);
204: q = new BigInteger(1, qBytes);
205: q = q.setBit(0).setBit(l - 2).clearBit(l - 1);
206: }
207: while (! q.isProbablePrime(80));
208: p = q.multiply(TWO).add(ONE);
209: }
210: while (p.bitLength() != l || ! p.isProbablePrime(80));
211:
212: BigInteger p_minus_1 = p.subtract(ONE);
213: g = TWO;
214:
215:
216: for (BigInteger h = TWO; h.compareTo(p_minus_1) < 0; h = h.add(ONE))
217: {
218:
219: g = h.modPow(TWO, p);
220:
221: if (! g.equals(ONE))
222: break;
223: }
224: return new BigInteger[] { q, p, g };
225: }
226:
227: private KeyPair hostKeyPair()
228: {
229: byte[] bBytes = new byte[(l + 7) / 8];
230: BigInteger b, B;
231: do
232: {
233: do
234: {
235: nextRandomBytes(bBytes);
236: b = new BigInteger(1, bBytes);
237: }
238: while (b.compareTo(ONE) <= 0 || b.compareTo(N) >= 0);
239: B = THREE.multiply(v).add(g.modPow(b, N)).mod(N);
240: }
241: while (B.compareTo(ZERO) == 0 || B.compareTo(N) >= 0);
242: KeyPair result = new KeyPair(new SRPPublicKey(new BigInteger[] { N, g, B }),
243: new SRPPrivateKey(new BigInteger[] { N, g, b, v }));
244: return result;
245: }
246:
247: private KeyPair userKeyPair()
248: {
249: byte[] aBytes = new byte[(l + 7) / 8];
250: BigInteger a, A;
251: do
252: {
253: do
254: {
255: nextRandomBytes(aBytes);
256: a = new BigInteger(1, aBytes);
257: }
258: while (a.compareTo(ONE) <= 0 || a.compareTo(N) >= 0);
259: A = g.modPow(a, N);
260: }
261: while (A.compareTo(ZERO) == 0 || A.compareTo(N) >= 0);
262: KeyPair result = new KeyPair(new SRPPublicKey(new BigInteger[] { N, g, A }),
263: new SRPPrivateKey(new BigInteger[] { N, g, a }));
264: return result;
265: }
266:
267: private void nextRandomBytes(byte[] buffer)
268: {
269: if (rnd != null)
270: rnd.nextBytes(buffer);
271: else
272: getDefaultPRNG().nextBytes(buffer);
273: }
274:
275: private PRNG getDefaultPRNG()
276: {
277: if (prng == null)
278: prng = PRNG.getInstance();
279:
280: return prng;
281: }
282: }