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