monotone

monotone Mtn Source Tree

Root/botan/dl_group.cpp

1/*************************************************
2* Discrete Logarithm Parameters Source File *
3* (C) 1999-2006 The Botan Project *
4*************************************************/
5
6#include <botan/dl_group.h>
7#include <botan/config.h>
8#include <botan/parsing.h>
9#include <botan/numthry.h>
10#include <botan/der_enc.h>
11#include <botan/ber_dec.h>
12#include <botan/pipe.h>
13#include <botan/util.h>
14#include <botan/pem.h>
15
16namespace Botan {
17
18/*************************************************
19* DL_Group Constructor *
20*************************************************/
21DL_Group::DL_Group()
22 {
23 initialized = false;
24 }
25
26/*************************************************
27* DL_Group Constructor *
28*************************************************/
29DL_Group::DL_Group(const std::string& type)
30 {
31 DataSource_Memory pem(global_config().get("dl", type));
32 PEM_decode(pem);
33 }
34
35/*************************************************
36* DL_Group Constructor *
37*************************************************/
38DL_Group::DL_Group(u32bit pbits, PrimeType type)
39 {
40 if(pbits < 512)
41 throw Invalid_Argument("DL_Group: prime size " + to_string(pbits) +
42 " is too small");
43
44 if(type == Strong)
45 {
46 p = random_safe_prime(pbits);
47 q = (p - 1) / 2;
48 g = 2;
49 }
50 else if(type == Prime_Subgroup || type == DSA_Kosherizer)
51 {
52 if(type == Prime_Subgroup)
53 {
54 const u32bit qbits = 2 * dl_work_factor(pbits);
55 q = random_prime(qbits);
56 BigInt X;
57 while(p.bits() != pbits || !is_prime(p))
58 {
59 X = random_integer(pbits);
60 p = X - (X % (2*q) - 1);
61 }
62 }
63 else
64 generate_dsa_primes(p, q, pbits);
65
66 g = make_dsa_generator(p, q);
67 }
68
69 initialized = true;
70 }
71
72/*************************************************
73* DL_Group Constructor *
74*************************************************/
75DL_Group::DL_Group(const MemoryRegion<byte>& seed, u32bit pbits, u32bit start)
76 {
77 if(!generate_dsa_primes(p, q, seed.begin(), seed.size(), pbits, start))
78 throw Invalid_Argument("DL_Group: The seed/counter given does not "
79 "generate a DSA group");
80
81 g = make_dsa_generator(p, q);
82
83 initialized = true;
84 }
85
86/*************************************************
87* DL_Group Constructor *
88*************************************************/
89DL_Group::DL_Group(const BigInt& p1, const BigInt& g1)
90 {
91 initialize(p1, 0, g1);
92 }
93
94/*************************************************
95* DL_Group Constructor *
96*************************************************/
97DL_Group::DL_Group(const BigInt& p1, const BigInt& q1, const BigInt& g1)
98 {
99 initialize(p1, q1, g1);
100 }
101
102/*************************************************
103* DL_Group Initializer *
104*************************************************/
105void DL_Group::initialize(const BigInt& p1, const BigInt& q1, const BigInt& g1)
106 {
107 if(p1 < 3)
108 throw Invalid_Argument("DL_Group: Prime invalid");
109 if(g1 < 2 || g1 >= p1)
110 throw Invalid_Argument("DL_Group: Generator invalid");
111 if(q1 < 0 || q1 >= p1)
112 throw Invalid_Argument("DL_Group: Subgroup invalid");
113
114 p = p1;
115 g = g1;
116 q = q1;
117
118 if(q == 0 && check_prime((p - 1) / 2))
119 q = (p - 1) / 2;
120
121 initialized = true;
122 }
123
124/*************************************************
125* Verify that the group has been set *
126*************************************************/
127void DL_Group::init_check() const
128 {
129 if(!initialized)
130 throw Invalid_State("DLP group cannot be used uninitialized");
131 }
132
133/*************************************************
134* Verify the parameters *
135*************************************************/
136bool DL_Group::verify_group(bool strong) const
137 {
138 init_check();
139
140 if(g < 2 || p < 3 || q < 0)
141 return false;
142 if((q != 0) && ((p - 1) % q != 0))
143 return false;
144
145 if(!strong)
146 return true;
147
148 if(!check_prime(p))
149 return false;
150 if((q > 0) && !check_prime(q))
151 return false;
152 return true;
153 }
154
155/*************************************************
156* Return the prime *
157*************************************************/
158const BigInt& DL_Group::get_p() const
159 {
160 init_check();
161 return p;
162 }
163
164/*************************************************
165* Return the generator *
166*************************************************/
167const BigInt& DL_Group::get_g() const
168 {
169 init_check();
170 return g;
171 }
172
173/*************************************************
174* Return the subgroup *
175*************************************************/
176const BigInt& DL_Group::get_q() const
177 {
178 init_check();
179 if(q == 0)
180 throw Format_Error("DLP group has no q prime specified");
181 return q;
182 }
183
184/*************************************************
185* DER encode the parameters *
186*************************************************/
187SecureVector<byte> DL_Group::DER_encode(Format format) const
188 {
189 init_check();
190
191 if((q == 0) && (format != PKCS_3))
192 throw Encoding_Error("The ANSI DL parameter formats require a subgroup");
193
194 if(format == ANSI_X9_57)
195 {
196 return DER_Encoder()
197 .start_cons(SEQUENCE)
198 .encode(p)
199 .encode(q)
200 .encode(g)
201 .end_cons()
202 .get_contents();
203 }
204 else if(format == ANSI_X9_42)
205 {
206 return DER_Encoder()
207 .start_cons(SEQUENCE)
208 .encode(p)
209 .encode(g)
210 .encode(q)
211 .end_cons()
212 .get_contents();
213 }
214 else if(format == PKCS_3)
215 {
216 return DER_Encoder()
217 .start_cons(SEQUENCE)
218 .encode(p)
219 .encode(g)
220 .end_cons()
221 .get_contents();
222 }
223
224 throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
225 }
226
227/*************************************************
228* PEM encode the parameters *
229*************************************************/
230std::string DL_Group::PEM_encode(Format format) const
231 {
232 SecureVector<byte> encoding = DER_encode(format);
233 if(format == PKCS_3)
234 return PEM_Code::encode(encoding, "DH PARAMETERS");
235 else if(format == ANSI_X9_57)
236 return PEM_Code::encode(encoding, "DSA PARAMETERS");
237 else if(format == ANSI_X9_42)
238 return PEM_Code::encode(encoding, "X942 DH PARAMETERS");
239 else
240 throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
241 }
242
243/*************************************************
244* Decode BER encoded parameters *
245*************************************************/
246void DL_Group::BER_decode(DataSource& source, Format format)
247 {
248 BigInt new_p, new_q, new_g;
249
250 BER_Decoder decoder(source);
251 BER_Decoder ber = decoder.start_cons(SEQUENCE);
252
253 if(format == ANSI_X9_57)
254 {
255 ber.decode(new_p)
256 .decode(new_q)
257 .decode(new_g)
258 .verify_end();
259 }
260 else if(format == ANSI_X9_42)
261 {
262 ber.decode(new_p)
263 .decode(new_g)
264 .decode(new_q)
265 .discard_remaining();
266 }
267 else if(format == PKCS_3)
268 {
269 ber.decode(new_p)
270 .decode(new_g)
271 .discard_remaining();
272 }
273 else
274 throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
275
276 initialize(new_p, new_q, new_g);
277 }
278
279/*************************************************
280* Decode PEM encoded parameters *
281*************************************************/
282void DL_Group::PEM_decode(DataSource& source)
283 {
284 std::string label;
285 DataSource_Memory ber(PEM_Code::decode(source, label));
286
287 if(label == "DH PARAMETERS")
288 BER_decode(ber, PKCS_3);
289 else if(label == "DSA PARAMETERS")
290 BER_decode(ber, ANSI_X9_57);
291 else if(label == "X942 DH PARAMETERS")
292 BER_decode(ber, ANSI_X9_42);
293 else
294 throw Decoding_Error("DL_Group: Invalid PEM label " + label);
295 }
296
297/*************************************************
298* Create a random DSA-style generator *
299*************************************************/
300BigInt DL_Group::make_dsa_generator(const BigInt& p, const BigInt& q)
301 {
302 BigInt g, e = (p - 1) / q;
303
304 for(u32bit j = 0; j != PRIME_TABLE_SIZE; ++j)
305 {
306 g = power_mod(PRIMES[j], e, p);
307 if(g != 1)
308 break;
309 }
310
311 if(g == 1)
312 throw Exception("DL_Group: Couldn't create a suitable generator");
313
314 return g;
315 }
316
317}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status