1
|
#!/usr/bin/env python
|
2
|
#
|
3
|
# generate-ffdhe.py
|
4
|
#
|
5
|
# Generate PEM strings for the FFDHE parameters in RFC 7919
|
6
|
# For reference, see https://tools.ietf.org/rfc/rfc7919.txt
|
7
|
#
|
8
|
# This is derived from a similar script from the Mumble project.
|
9
|
# https://github.com/mumble-voip/mumble/blob/master/scripts/generate-ffdhe.py
|
10
|
|
11
|
from __future__ import (unicode_literals, print_function, division)
|
12
|
|
13
|
# Python 3 doesn't have a long type.
|
14
|
# Map the long type to int here, so
|
15
|
# we can easily be compatible with both
|
16
|
# interpreters.
|
17
|
try:
|
18
|
type(long)
|
19
|
except NameError:
|
20
|
long = int
|
21
|
|
22
|
import os
|
23
|
import base64
|
24
|
import codecs
|
25
|
|
26
|
# The following P values are directly sourced from RFC 7919 at
|
27
|
# https://tools.ietf.org/rfc/rfc7919.txt
|
28
|
|
29
|
ffdhe_str = {
|
30
|
'2048': '''
|
31
|
FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
|
32
|
D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
|
33
|
7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
|
34
|
2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
|
35
|
984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
|
36
|
30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
|
37
|
B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
|
38
|
0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
|
39
|
9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
|
40
|
3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
|
41
|
886B4238 61285C97 FFFFFFFF FFFFFFFF
|
42
|
''',
|
43
|
'3072': '''
|
44
|
FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
|
45
|
D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
|
46
|
7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
|
47
|
2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
|
48
|
984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
|
49
|
30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
|
50
|
B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
|
51
|
0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
|
52
|
9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
|
53
|
3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
|
54
|
886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
|
55
|
61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
|
56
|
AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
|
57
|
64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
|
58
|
ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
|
59
|
3C1B20EE 3FD59D7C 25E41D2B 66C62E37 FFFFFFFF FFFFFFFF
|
60
|
''',
|
61
|
'4096': '''
|
62
|
FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
|
63
|
D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
|
64
|
7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
|
65
|
2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
|
66
|
984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
|
67
|
30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
|
68
|
B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
|
69
|
0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
|
70
|
9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
|
71
|
3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
|
72
|
886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
|
73
|
61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
|
74
|
AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
|
75
|
64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
|
76
|
ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
|
77
|
3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB
|
78
|
7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004
|
79
|
87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832
|
80
|
A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A
|
81
|
1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF
|
82
|
8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E655F6A
|
83
|
FFFFFFFF FFFFFFFF
|
84
|
''',
|
85
|
'6144': '''
|
86
|
FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
|
87
|
D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
|
88
|
7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
|
89
|
2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
|
90
|
984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
|
91
|
30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
|
92
|
B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
|
93
|
0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
|
94
|
9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
|
95
|
3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
|
96
|
886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
|
97
|
61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
|
98
|
AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
|
99
|
64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
|
100
|
ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
|
101
|
3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB
|
102
|
7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004
|
103
|
87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832
|
104
|
A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A
|
105
|
1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF
|
106
|
8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E0DD902
|
107
|
0BFD64B6 45036C7A 4E677D2C 38532A3A 23BA4442 CAF53EA6
|
108
|
3BB45432 9B7624C8 917BDD64 B1C0FD4C B38E8C33 4C701C3A
|
109
|
CDAD0657 FCCFEC71 9B1F5C3E 4E46041F 388147FB 4CFDB477
|
110
|
A52471F7 A9A96910 B855322E DB6340D8 A00EF092 350511E3
|
111
|
0ABEC1FF F9E3A26E 7FB29F8C 183023C3 587E38DA 0077D9B4
|
112
|
763E4E4B 94B2BBC1 94C6651E 77CAF992 EEAAC023 2A281BF6
|
113
|
B3A739C1 22611682 0AE8DB58 47A67CBE F9C9091B 462D538C
|
114
|
D72B0374 6AE77F5E 62292C31 1562A846 505DC82D B854338A
|
115
|
E49F5235 C95B9117 8CCF2DD5 CACEF403 EC9D1810 C6272B04
|
116
|
5B3B71F9 DC6B80D6 3FDD4A8E 9ADB1E69 62A69526 D43161C1
|
117
|
A41D570D 7938DAD4 A40E329C D0E40E65 FFFFFFFF FFFFFFFF
|
118
|
''',
|
119
|
'8192': '''
|
120
|
FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
|
121
|
D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
|
122
|
7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
|
123
|
2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
|
124
|
984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
|
125
|
30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
|
126
|
B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
|
127
|
0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
|
128
|
9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
|
129
|
3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
|
130
|
886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
|
131
|
61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
|
132
|
AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
|
133
|
64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
|
134
|
ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
|
135
|
3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB
|
136
|
7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004
|
137
|
87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832
|
138
|
A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A
|
139
|
1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF
|
140
|
8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E0DD902
|
141
|
0BFD64B6 45036C7A 4E677D2C 38532A3A 23BA4442 CAF53EA6
|
142
|
3BB45432 9B7624C8 917BDD64 B1C0FD4C B38E8C33 4C701C3A
|
143
|
CDAD0657 FCCFEC71 9B1F5C3E 4E46041F 388147FB 4CFDB477
|
144
|
A52471F7 A9A96910 B855322E DB6340D8 A00EF092 350511E3
|
145
|
0ABEC1FF F9E3A26E 7FB29F8C 183023C3 587E38DA 0077D9B4
|
146
|
763E4E4B 94B2BBC1 94C6651E 77CAF992 EEAAC023 2A281BF6
|
147
|
B3A739C1 22611682 0AE8DB58 47A67CBE F9C9091B 462D538C
|
148
|
D72B0374 6AE77F5E 62292C31 1562A846 505DC82D B854338A
|
149
|
E49F5235 C95B9117 8CCF2DD5 CACEF403 EC9D1810 C6272B04
|
150
|
5B3B71F9 DC6B80D6 3FDD4A8E 9ADB1E69 62A69526 D43161C1
|
151
|
A41D570D 7938DAD4 A40E329C CFF46AAA 36AD004C F600C838
|
152
|
1E425A31 D951AE64 FDB23FCE C9509D43 687FEB69 EDD1CC5E
|
153
|
0B8CC3BD F64B10EF 86B63142 A3AB8829 555B2F74 7C932665
|
154
|
CB2C0F1C C01BD702 29388839 D2AF05E4 54504AC7 8B758282
|
155
|
2846C0BA 35C35F5C 59160CC0 46FD8251 541FC68C 9C86B022
|
156
|
BB709987 6A460E74 51A8A931 09703FEE 1C217E6C 3826E52C
|
157
|
51AA691E 0E423CFC 99E9E316 50C1217B 624816CD AD9A95F9
|
158
|
D5B80194 88D9C0A0 A1FE3075 A577E231 83F81D4A 3F2FA457
|
159
|
1EFC8CE0 BA8A4FE8 B6855DFE 72B0A66E DED2FBAB FBE58A30
|
160
|
FAFABE1C 5D71A87E 2F741EF8 C1FE86FE A6BBFDE5 30677F0D
|
161
|
97D11D49 F7A8443D 0822E506 A9F4614E 011E2A94 838FF88C
|
162
|
D68C8BB7 C5C6424C FFFFFFFF FFFFFFFF
|
163
|
'''
|
164
|
}
|
165
|
|
166
|
# All groups from RFC 7919 use generator 2.
|
167
|
|
168
|
g = '''02'''
|
169
|
|
170
|
def dehexify(hexString):
|
171
|
'''
|
172
|
Convert the "bignum" hexString
|
173
|
representation to a bytearray
|
174
|
containing the number.
|
175
|
'''
|
176
|
return bytearray.fromhex(' '.join(line.strip() for line in hexString.splitlines()))
|
177
|
|
178
|
def derLength(size):
|
179
|
'''
|
180
|
Returns the ASN.1 DER length bytes
|
181
|
for the given size.
|
182
|
|
183
|
Short form: For lengths <= 127,
|
184
|
the length is just a byte containing
|
185
|
the literal number. (Note that for
|
186
|
numbers <= 127, the MSB is not
|
187
|
set.)
|
188
|
|
189
|
In doctest form, that is:
|
190
|
|
191
|
>>> derLength(1)
|
192
|
bytearray(b'\\x01')
|
193
|
|
194
|
>>> derLength(127)
|
195
|
bytearray(b'\\x7f')
|
196
|
|
197
|
Long form: For lengths > 127,
|
198
|
the encoding is different: The
|
199
|
first byte has the MSB set (that
|
200
|
is, by itself, 0x80). The rest of
|
201
|
the bits in the first byte specify
|
202
|
the number of bytes that follow.
|
203
|
|
204
|
So, to encode the length 128, you
|
205
|
would emit
|
206
|
|
207
|
0x81 0x80
|
208
|
|
209
|
The high bit of the first byte is set.
|
210
|
This means the remaining 7 bits contain
|
211
|
how many bytes follow it. If we mask the
|
212
|
MSB away, we end up with 0x01. So, only
|
213
|
a single byte follows.
|
214
|
The value of the following byte is 0x80,
|
215
|
which is 128 decimal.
|
216
|
|
217
|
In doctest form, that is:
|
218
|
|
219
|
>>> derLength(128)
|
220
|
bytearray(b'\\x81\\x80')
|
221
|
|
222
|
Error cases:
|
223
|
|
224
|
The size passed to this function must be an integer:
|
225
|
|
226
|
>>> derLength(0.1)
|
227
|
Traceback (most recent call last):
|
228
|
...
|
229
|
Exception: bad type
|
230
|
|
231
|
>>> derLength('5')
|
232
|
Traceback (most recent call last):
|
233
|
...
|
234
|
Exception: bad type
|
235
|
|
236
|
Negative numbers are not supported, and throw an exception:
|
237
|
|
238
|
>>> derLength(-1)
|
239
|
Traceback (most recent call last):
|
240
|
...
|
241
|
Exception: bad size
|
242
|
|
243
|
The long form does not support very large numbers. This is
|
244
|
because the 'additional bytes' counter can only count up to
|
245
|
127 (2**7-1) bytes.
|
246
|
|
247
|
So, if we try to encode a length that will use exactly 127
|
248
|
bytes, it will succeed:
|
249
|
|
250
|
>>> derLength(int('ff'*127, 16)) # doctest:+ELLIPSIS
|
251
|
bytearray(b'\\xff...\\xff')
|
252
|
|
253
|
But if we try to go over that limit, we get an exception:
|
254
|
|
255
|
>>> derLength(int('ff'*128, 16))
|
256
|
Traceback (most recent call last):
|
257
|
...
|
258
|
Exception: unencodable
|
259
|
'''
|
260
|
|
261
|
# Ensure that the passed-in size is an integer.
|
262
|
if not isinstance(size, (int, long)):
|
263
|
raise Exception('bad type')
|
264
|
|
265
|
if size > 127:
|
266
|
# Convert 'size' to a hexString-style
|
267
|
# bignum that we can pass to dehexify.
|
268
|
#
|
269
|
# Strip '0x' prefix from the hex string.
|
270
|
hexString = hex(size)[2:]
|
271
|
# In Python 2.7, the output of hex()
|
272
|
# can have an L suffix. Make sure we
|
273
|
# strip that.
|
274
|
if hexString.endswith('L'):
|
275
|
hexString = hexString[:-1]
|
276
|
# Ensure the final hex string only
|
277
|
# contains full bytes. If not, prepend
|
278
|
# a zero byte.
|
279
|
if len(hexString) % 2 != 0:
|
280
|
hexString = '0' + hexString
|
281
|
|
282
|
# If the computed hexString bignum
|
283
|
# contains more than 127 bytes, we
|
284
|
# can't encode it using ASN.1 DER
|
285
|
# encoding. Throw an exception.
|
286
|
nbytes = len(hexString) // 2
|
287
|
if nbytes > 127:
|
288
|
raise Exception('unencodable')
|
289
|
|
290
|
buf = dehexify(hexString)
|
291
|
out = bytearray((0x80 | nbytes,))
|
292
|
out += buf
|
293
|
return out
|
294
|
elif size > 0:
|
295
|
# Short form is simply the number itself,
|
296
|
# as a byte.
|
297
|
return bytearray((size,))
|
298
|
else:
|
299
|
# We don't support negative sizes.
|
300
|
raise Exception('bad size')
|
301
|
|
302
|
def derSequence(sequence):
|
303
|
'''
|
304
|
Encode an ASN.1 DER sequence
|
305
|
|
306
|
Takes a sequence of DER data as its input.
|
307
|
|
308
|
Returns a bytearray of the resulting data.
|
309
|
|
310
|
The encoding of a DER sequence is simply
|
311
|
an identifier (0x30), a length (the length
|
312
|
of the content bytes -- see the derLength
|
313
|
function), and the content itself (just a
|
314
|
byte stream of other ASN.1 DER objects)
|
315
|
'''
|
316
|
out = bytearray((0x30,)) # SEQUENCE tag
|
317
|
content = bytearray()
|
318
|
for entry in sequence:
|
319
|
content += entry
|
320
|
out += derLength(len(content))
|
321
|
out += content
|
322
|
return out
|
323
|
|
324
|
def derUnsignedInteger(hexString):
|
325
|
'''
|
326
|
Encode a hex string to a ASN.1 DER INTEGER.
|
327
|
This function only handles unsigned integers.
|
328
|
|
329
|
Returns a bytearray of the resulting data.
|
330
|
|
331
|
The encoding of an ASN.1 DER INTEGER is an
|
332
|
identifier (0x02), a length (the length of the
|
333
|
content bytes -- see the derLength function),
|
334
|
and the content, which in this case is the
|
335
|
bytes that make up the integer.
|
336
|
|
337
|
An INTEGER can be signed, or unsigned. Our
|
338
|
function here only deals with unsigned integers.
|
339
|
|
340
|
Signed integers have the MSB/sign bit set.
|
341
|
|
342
|
Our input data is guaranteed to be unsigned,
|
343
|
so if we detect that the MSB is set in the
|
344
|
data, we prepend a zero byte to it. This
|
345
|
is the way to signal that the value is unsigned
|
346
|
rather than signed.
|
347
|
'''
|
348
|
out = bytearray((0x02,)) # INTEGER tag
|
349
|
buf = dehexify(hexString)
|
350
|
|
351
|
# If the sign bit is set, prepend a zero byte.
|
352
|
# Otherwise, the number will be treated as signed,
|
353
|
# which we don't want.
|
354
|
if (buf[0] & 0x80) != 0:
|
355
|
buf = bytearray((0,)) + buf
|
356
|
out += derLength(len(buf))
|
357
|
out += buf
|
358
|
return out
|
359
|
|
360
|
def pem(der, kind='DH PARAMETERS'):
|
361
|
'''
|
362
|
Convert the ASN.1 DER data to PEM form.
|
363
|
|
364
|
Returns the resulting string (type 'unicode' for Python 2).
|
365
|
|
366
|
The PEM format consists of a header, the content itself (base64,
|
367
|
using the standard alphabet) and a trailer.
|
368
|
|
369
|
The header is of the form:
|
370
|
-----BEGIN $KIND-----
|
371
|
|
372
|
and the trailer is of the form:
|
373
|
-----END $KIND-----
|
374
|
|
375
|
where $KIND defines the type of data
|
376
|
contained in the PEM data.
|
377
|
|
378
|
Between the header and the trailer is
|
379
|
the content itself. The content is the
|
380
|
DER form encoded using base64.
|
381
|
|
382
|
Our implementation splits the base64
|
383
|
data such that each line of base64 data
|
384
|
can be no longer than 64 characters long.
|
385
|
'''
|
386
|
out = u'-----BEGIN {0}-----\n'.format(kind)
|
387
|
enc = base64.b64encode(der)
|
388
|
n = 0
|
389
|
for ch in enc:
|
390
|
if type(ch) == int: # Python 3
|
391
|
out += chr(ch)
|
392
|
else:
|
393
|
out += ch
|
394
|
n += 1
|
395
|
if n == 64:
|
396
|
out += '\n'
|
397
|
n = 0
|
398
|
if out[-1] != '\n':
|
399
|
out += '\n'
|
400
|
out += u'-----END {0}-----\n'.format(kind)
|
401
|
return out
|
402
|
|
403
|
def writePEM(f, identifier, str):
|
404
|
f.write(str)
|
405
|
|
406
|
def main():
|
407
|
for len, str in ffdhe_str.items():
|
408
|
f = codecs.open(os.path.join('output', 'dh-parameters.' + len), 'w', 'utf-8')
|
409
|
|
410
|
writePEM(f, 'ffdhe' + len + '_pem', pem(
|
411
|
derSequence((
|
412
|
derUnsignedInteger(str),
|
413
|
derUnsignedInteger(g),
|
414
|
))
|
415
|
))
|
416
|
|
417
|
if __name__ == '__main__':
|
418
|
main()
|