OLD | NEW |
---|---|
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import asn1 | 5 import asn1 |
6 import datetime | |
6 import hashlib | 7 import hashlib |
7 import os | 8 import os |
9 import time | |
8 | 10 |
11 GENERALIZED_TIME_FORMAT = "%Y%m%d%H%M%SZ" | |
12 | |
13 OCSP_STATE_GOOD = 1 | |
14 OCSP_STATE_REVOKED = 2 | |
15 OCSP_STATE_INVALID = 3 | |
16 OCSP_STATE_UNAUTHORIZED = 4 | |
17 OCSP_STATE_UNKNOWN = 5 | |
18 | |
19 OCSP_DATE_VALID = 1 | |
20 OCSP_DATE_OLD = 2 | |
21 OCSP_DATE_YOUNG = 3 | |
22 OCSP_DATE_LONG = 4 | |
9 | 23 |
10 # This file implements very minimal certificate and OCSP generation. It's | 24 # This file implements very minimal certificate and OCSP generation. It's |
11 # designed to test revocation checking. | 25 # designed to test revocation checking. |
12 | 26 |
13 def RandomNumber(length_in_bytes): | 27 def RandomNumber(length_in_bytes): |
14 '''RandomNumber returns a random number of length 8*|length_in_bytes| bits''' | 28 '''RandomNumber returns a random number of length 8*|length_in_bytes| bits''' |
15 rand = os.urandom(length_in_bytes) | 29 rand = os.urandom(length_in_bytes) |
16 n = 0 | 30 n = 0 |
17 for x in rand: | 31 for x in rand: |
18 n <<= 8 | 32 n <<= 8 |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 | 252 |
239 return asn1.ToDER(asn1.SEQUENCE([ | 253 return asn1.ToDER(asn1.SEQUENCE([ |
240 asn1.Raw(tbsCert), | 254 asn1.Raw(tbsCert), |
241 asn1.SEQUENCE([ | 255 asn1.SEQUENCE([ |
242 SHA256_WITH_RSA_ENCRYPTION, | 256 SHA256_WITH_RSA_ENCRYPTION, |
243 None, | 257 None, |
244 ]), | 258 ]), |
245 asn1.BitString(privkey.Sign(tbsCert)), | 259 asn1.BitString(privkey.Sign(tbsCert)), |
246 ])) | 260 ])) |
247 | 261 |
248 | 262 def MakeOCSPResponse(issuer_cn, issuer_key, serial, ocsp_state, ocsp_date): |
249 def MakeOCSPResponse(issuer_cn, issuer_key, serial, ocsp_state): | |
250 # https://tools.ietf.org/html/rfc2560 | 263 # https://tools.ietf.org/html/rfc2560 |
251 issuer_name_hash = asn1.OCTETSTRING( | 264 issuer_name_hash = asn1.OCTETSTRING( |
252 hashlib.sha1(asn1.ToDER(Name(cn = issuer_cn))).digest()) | 265 hashlib.sha1(asn1.ToDER(Name(cn = issuer_cn))).digest()) |
253 | 266 |
254 issuer_key_hash = asn1.OCTETSTRING( | 267 issuer_key_hash = asn1.OCTETSTRING( |
255 hashlib.sha1(asn1.ToDER(issuer_key)).digest()) | 268 hashlib.sha1(asn1.ToDER(issuer_key)).digest()) |
256 | 269 |
257 cert_status = None | 270 cert_status = None |
258 if ocsp_state == OCSP_STATE_REVOKED: | 271 if ocsp_state == OCSP_STATE_REVOKED: |
259 cert_status = asn1.Explicit(1, asn1.GeneralizedTime("20100101060000Z")) | 272 cert_status = asn1.Explicit(1, asn1.GeneralizedTime("20100101060000Z")) |
260 elif ocsp_state == OCSP_STATE_UNKNOWN: | 273 elif ocsp_state == OCSP_STATE_UNKNOWN: |
261 cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 2, 0)) | 274 cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 2, 0)) |
262 elif ocsp_state == OCSP_STATE_GOOD: | 275 elif ocsp_state == OCSP_STATE_GOOD: |
263 cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 0, 0)) | 276 cert_status = asn1.Raw(asn1.TagAndLength(0x80 | 0, 0)) |
264 else: | 277 else: |
265 raise ValueError('Bad OCSP state: ' + str(ocsp_state)) | 278 raise ValueError('Bad OCSP state: ' + str(ocsp_state)) |
266 | 279 |
280 now = datetime.datetime.fromtimestamp(time.mktime(time.gmtime())) | |
281 if ocsp_date == OCSP_DATE_VALID: | |
282 thisUpdate = now - datetime.timedelta(hours=1) | |
283 nextUpdate = thisUpdate + datetime.timedelta(weeks=1) | |
284 elif ocsp_date == OCSP_DATE_OLD: | |
285 thisUpdate = now - datetime.timedelta(hours=1, weeks=1) | |
286 nextUpdate = thisUpdate + datetime.timedelta(weeks=1) | |
287 elif ocsp_date == OCSP_DATE_YOUNG: | |
svaldez
2016/06/23 14:03:16
EARLY?
| |
288 thisUpdate = now + datetime.timedelta(hours=1) | |
289 nextUpdate = thisUpdate + datetime.timedelta(weeks=1) | |
290 elif ocsp_date == OCSP_DATE_LONG: | |
291 thisUpdate = now - datetime.timedelta(days=365) | |
292 nextUpdate = thisUpdate + datetime.timedelta(hours=1, days=365) | |
293 else: | |
294 raise ValueError('Bad OCSP date: ' + str(ocsp_date)) | |
295 | |
267 basic_resp_data_der = asn1.ToDER(asn1.SEQUENCE([ | 296 basic_resp_data_der = asn1.ToDER(asn1.SEQUENCE([ |
268 asn1.Explicit(2, issuer_key_hash), | 297 asn1.Explicit(2, issuer_key_hash), |
269 asn1.GeneralizedTime("20100101060000Z"), # producedAt | 298 asn1.GeneralizedTime("20100101060000Z"), # producedAt |
270 asn1.SEQUENCE([ | 299 asn1.SEQUENCE([ |
271 asn1.SEQUENCE([ # SingleResponse | 300 asn1.SEQUENCE([ # SingleResponse |
272 asn1.SEQUENCE([ # CertID | 301 asn1.SEQUENCE([ # CertID |
273 asn1.SEQUENCE([ # hashAlgorithm | 302 asn1.SEQUENCE([ # hashAlgorithm |
274 HASH_SHA1, | 303 HASH_SHA1, |
275 None, | 304 None, |
276 ]), | 305 ]), |
277 issuer_name_hash, | 306 issuer_name_hash, |
278 issuer_key_hash, | 307 issuer_key_hash, |
279 serial, | 308 serial, |
280 ]), | 309 ]), |
281 cert_status, | 310 cert_status, |
282 asn1.GeneralizedTime("20100101060000Z"), # thisUpdate | 311 asn1.GeneralizedTime( # thisUpdate, 1 hour ago |
283 asn1.Explicit(0, asn1.GeneralizedTime("20300101060000Z")), # nextUpdate | 312 thisUpdate.strftime(GENERALIZED_TIME_FORMAT) |
313 ), | |
314 asn1.Explicit( # nextUpdate, 7 days later | |
315 0, | |
316 asn1.GeneralizedTime(nextUpdate.strftime(GENERALIZED_TIME_FORMAT)) | |
317 ), | |
284 ]), | 318 ]), |
285 ]), | 319 ]), |
286 ])) | 320 ])) |
287 | 321 |
288 basic_resp = asn1.SEQUENCE([ | 322 basic_resp = asn1.SEQUENCE([ |
289 asn1.Raw(basic_resp_data_der), | 323 asn1.Raw(basic_resp_data_der), |
290 asn1.SEQUENCE([ | 324 asn1.SEQUENCE([ |
291 SHA256_WITH_RSA_ENCRYPTION, | 325 SHA256_WITH_RSA_ENCRYPTION, |
292 None, | 326 None, |
293 ]), | 327 ]), |
(...skipping 10 matching lines...) Expand all Loading... | |
304 | 338 |
305 return asn1.ToDER(resp) | 339 return asn1.ToDER(resp) |
306 | 340 |
307 | 341 |
308 def DERToPEM(der): | 342 def DERToPEM(der): |
309 pem = '-----BEGIN CERTIFICATE-----\n' | 343 pem = '-----BEGIN CERTIFICATE-----\n' |
310 pem += der.encode('base64') | 344 pem += der.encode('base64') |
311 pem += '-----END CERTIFICATE-----\n' | 345 pem += '-----END CERTIFICATE-----\n' |
312 return pem | 346 return pem |
313 | 347 |
314 OCSP_STATE_GOOD = 1 | |
315 OCSP_STATE_REVOKED = 2 | |
316 OCSP_STATE_INVALID = 3 | |
317 OCSP_STATE_UNAUTHORIZED = 4 | |
318 OCSP_STATE_UNKNOWN = 5 | |
319 | |
320 # unauthorizedDER is an OCSPResponse with a status of 6: | 348 # unauthorizedDER is an OCSPResponse with a status of 6: |
321 # SEQUENCE { ENUM(6) } | 349 # SEQUENCE { ENUM(6) } |
322 unauthorizedDER = '30030a0106'.decode('hex') | 350 unauthorizedDER = '30030a0106'.decode('hex') |
323 | 351 |
324 def GenerateCertKeyAndOCSP(subject = "127.0.0.1", | 352 def GenerateCertKeyAndOCSP(subject = "127.0.0.1", |
325 ocsp_url = "http://127.0.0.1", | 353 ocsp_url = "http://127.0.0.1", |
326 ocsp_state = OCSP_STATE_GOOD, | 354 ocsp_state = OCSP_STATE_GOOD, |
355 ocsp_date = OCSP_DATE_VALID, | |
327 serial = 0): | 356 serial = 0): |
328 '''GenerateCertKeyAndOCSP returns a (cert_and_key_pem, ocsp_der) where: | 357 '''GenerateCertKeyAndOCSP returns a (cert_and_key_pem, ocsp_der) where: |
329 * cert_and_key_pem contains a certificate and private key in PEM format | 358 * cert_and_key_pem contains a certificate and private key in PEM format |
330 with the given subject common name and OCSP URL. | 359 with the given subject common name and OCSP URL. |
331 * ocsp_der contains a DER encoded OCSP response or None if ocsp_url is | 360 * ocsp_der contains a DER encoded OCSP response or None if ocsp_url is |
332 None''' | 361 None''' |
333 | 362 |
334 if serial == 0: | 363 if serial == 0: |
335 serial = RandomNumber(16) | 364 serial = RandomNumber(16) |
336 cert_der = MakeCertificate(ISSUER_CN, bytes(subject), serial, KEY, KEY, | 365 cert_der = MakeCertificate(ISSUER_CN, bytes(subject), serial, KEY, KEY, |
337 bytes(ocsp_url)) | 366 bytes(ocsp_url)) |
338 cert_pem = DERToPEM(cert_der) | 367 cert_pem = DERToPEM(cert_der) |
339 | 368 |
340 ocsp_der = None | 369 ocsp_der = None |
341 if ocsp_url is not None: | 370 if ocsp_url is not None: |
342 if ocsp_state == OCSP_STATE_UNAUTHORIZED: | 371 if ocsp_state == OCSP_STATE_UNAUTHORIZED: |
343 ocsp_der = unauthorizedDER | 372 ocsp_der = unauthorizedDER |
344 elif ocsp_state == OCSP_STATE_INVALID: | 373 elif ocsp_state == OCSP_STATE_INVALID: |
345 ocsp_der = '3' | 374 ocsp_der = '3' |
346 else: | 375 else: |
347 ocsp_der = MakeOCSPResponse(ISSUER_CN, KEY, serial, ocsp_state) | 376 ocsp_der = MakeOCSPResponse( |
377 ISSUER_CN, KEY, serial, ocsp_state, ocsp_date) | |
348 | 378 |
349 return (cert_pem + KEY_PEM, ocsp_der) | 379 return (cert_pem + KEY_PEM, ocsp_der) |
OLD | NEW |