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