monotone

monotone Mtn Source Tree

Root/botan/dl_group.cpp

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

Archive Download this file

Branches

Tags

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