|
16 | 16 |
|
17 | 17 | from cryptography import x509
|
18 | 18 | from cryptography.hazmat.backends import default_backend
|
| 19 | +from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat |
19 | 20 | from kinto_http import Client
|
20 | 21 | from kinto_http.exceptions import KintoException
|
21 | 22 | from kinto_http.patch_type import BasicPatch
|
@@ -300,33 +301,37 @@ def __init__(self, **kwargs):
|
300 | 301 | [
|
301 | 302 | "derHash",
|
302 | 303 | "id",
|
303 |
| - "pubKeyHash", |
304 |
| - "subject", |
305 | 304 | ],
|
306 | 305 | kwargs,
|
307 | 306 | ):
|
308 | 307 | raise parseError
|
309 | 308 |
|
310 | 309 | try:
|
311 |
| - self.pubKeyHash = base64.b64decode( |
312 |
| - kwargs["pubKeyHash"], altchars="-_", validate=True |
313 |
| - ) # sha256 of the SPKI |
| 310 | + if "pubKeyHash" in kwargs: |
| 311 | + self.pubKeyHash = base64.b64decode( |
| 312 | + kwargs["pubKeyHash"], altchars="-_", validate=True |
| 313 | + ) # sha256 of the SPKI |
| 314 | + else: |
| 315 | + self.pubKeyHash = None |
| 316 | + except base64.binascii.Error: |
| 317 | + raise parseError |
| 318 | + |
| 319 | + if self.pubKeyHash and len(self.pubKeyHash) != 32: |
| 320 | + raise IntermediateRecordError(f"Invalid pubkey hash: {kwargs}") |
314 | 321 |
|
| 322 | + try: |
315 | 323 | if "derHash" in kwargs:
|
316 | 324 | self.derHash = base64.b64decode(
|
317 | 325 | kwargs["derHash"], altchars="-_", validate=True
|
318 | 326 | )
|
| 327 | + else: |
| 328 | + self.derHash = None |
319 | 329 | except base64.binascii.Error:
|
320 | 330 | raise parseError
|
321 | 331 |
|
322 |
| - if len(self.pubKeyHash) != 32: |
323 |
| - raise IntermediateRecordError(f"Invalid pubkey hash: {kwargs}") |
324 |
| - |
325 | 332 | if self.derHash and len(self.derHash) != 32:
|
326 | 333 | raise IntermediateRecordError(f"Invalid DER hash. {kwargs}")
|
327 | 334 |
|
328 |
| - self.subject = kwargs["subject"] |
329 |
| - |
330 | 335 | if "pem" in kwargs:
|
331 | 336 | self.set_pem(kwargs["pem"])
|
332 | 337 |
|
@@ -376,14 +381,28 @@ def set_pem(self, pem_data):
|
376 | 381 | self.pemData = pem_data
|
377 | 382 | self.pemHash = hashlib.sha256(pem_data.encode("utf-8")).hexdigest()
|
378 | 383 | derCert = asciiPemToBinaryDer(pem_data)
|
379 |
| - self.derHash = hashlib.sha256(derCert).digest() |
380 | 384 | try:
|
381 | 385 | self.cert = x509.load_pem_x509_certificate(
|
382 | 386 | pem_data.encode("utf-8"), default_backend()
|
383 | 387 | )
|
384 | 388 | except Exception as e:
|
385 | 389 | raise IntermediateRecordError("Cannot parse PEM data: {}".format(e))
|
386 | 390 |
|
| 391 | + derHash = hashlib.sha256(self.cert.public_bytes(Encoding.DER)).digest() |
| 392 | + if self.derHash and self.derHash != derHash: |
| 393 | + raise IntermediateRecordError("DER hash does not match") |
| 394 | + self.derHash = derHash |
| 395 | + |
| 396 | + self.subject = self.cert.subject.rfc4514_string() |
| 397 | + |
| 398 | + derSpki = self.cert.public_key().public_bytes( |
| 399 | + encoding=Encoding.DER, format=PublicFormat.SubjectPublicKeyInfo |
| 400 | + ) |
| 401 | + spkiHash = hashlib.sha256(derSpki).digest() |
| 402 | + if self.pubKeyHash and self.pubKeyHash != spkiHash: |
| 403 | + raise IntermediateRecordError("SPKI hash does not match") |
| 404 | + self.pubKeyHash = spkiHash |
| 405 | + |
387 | 406 | def download_pem(self, kinto_client):
|
388 | 407 | if not self.pemAttachment:
|
389 | 408 | raise Exception("pemAttachment not set")
|
|
0 commit comments