|
33 | 33 | import re |
34 | 34 | import warnings |
35 | 35 | import zlib |
36 | | -from base64 import b64decode |
37 | 36 | from dataclasses import astuple, dataclass |
38 | 37 | from datetime import date |
39 | 38 | from enum import Enum, IntEnum, unique |
@@ -657,53 +656,39 @@ def _parse_device_public_key(key_type, encoded): |
657 | 656 | return ec.EllipticCurvePublicKey.from_encoded_point(curve(), data[0x86]) |
658 | 657 |
|
659 | 658 |
|
660 | | -# This data embeds pre-computed structures used by the zlib deflate algorithm |
661 | | -# It's purpose is to avoid to store the full dictionary in the compressed |
662 | | -# stream, thus reducing the size of the certificate |
663 | | -# Source: https://datatracker.ietf.org/doc/html/draft-pritikin-comp-x509-00#appendix-A |
664 | | -_cxf_dictionary = b64decode(""" |
665 | | -MIIBOTCCASOgAwIBAgIBATANBgkqhkiG9w0BAQUFADAZMRcwFQYDVQQDEw5odHRw |
666 | | -Oi8vd3d3LmNvbTAeFw0xMDA1MTExOTEzMDNaFw0xMTA1MTExOTEzMDNaMF8xEDAO |
667 | | -BgkqhkiG9w0BCQEWAUAxCjAIBgNVBAMTASAxCzAJBgNVBAYTAlVTMQswCQYDVQQI |
668 | | -EwJXSTELMAkGA1UEChMCb24xDDAKBgNVBAsTA291bjEKMAgGA1UEBRMBIDAfMA0G |
669 | | -CSqGSIb3DQEBAQUAAw4AMAsCBG6G5ZUCAwEAAaNNMEswCQYDVR0TBAIwADAdBgNV |
670 | | -HQ4EFgQUHSkK6busCxxK6PKpBlL9q8K1mcQwHwYDVR0jBBgwFoAUn7r/DVMuEpK9 |
671 | | -Rxq3nyiLml10+nQwDQYJKoZIhvcNAQEFBQADAQA= |
672 | | -""") |
673 | | - |
674 | | - |
675 | 659 | def decompress_certificate(cert_data: bytes) -> bytes: |
676 | 660 | """ |
677 | 661 | Decompress a compressed certificate using various methods. |
678 | 662 | """ |
679 | 663 | logger.debug("Certificate is compressed, decompressing...") |
680 | 664 |
|
681 | | - # CXF Deflate Method (as used by Pointsharp Net iD) |
682 | | - if cert_data[:2] == b"\01\00": |
683 | | - expected_length = int.from_bytes(cert_data[2:4], "little") |
684 | | - decompressor = zlib.decompressobj(wbits=zlib.MAX_WBITS, zdict=_cxf_dictionary) |
685 | | - try: |
686 | | - cert_data = decompressor.decompress(cert_data[4:]) |
687 | | - if len(cert_data) != expected_length: |
688 | | - logger.error( |
689 | | - "Unexpected decompressed length, expected %d, got %d", |
690 | | - expected_length, |
691 | | - len(cert_data), |
692 | | - ) |
693 | | - raise ValueError("Decompressed length does not match expected length") |
694 | | - |
695 | | - logger.debug("Decompressed certificate with CXF deflate format") |
696 | | - return cert_data |
697 | | - except (zlib.error, ValueError): |
698 | | - logger.warning("Failed to decompress with CXF format") |
699 | | - |
700 | | - # Gzip Method (default) |
701 | | - try: |
702 | | - cert_data = gzip.decompress(cert_data) |
703 | | - logger.debug("Decompressed certificate with basic gzip format") |
704 | | - return cert_data |
705 | | - except (zlib.error, gzip.BadGzipFile): |
706 | | - logger.warning("Failed to decompressed with basic gzip format") |
| 665 | + match tuple(cert_data[:2]): |
| 666 | + case (0x1F, 0x8B): # Gzip (most commonly used) |
| 667 | + logger.debug("Decompressing certificate using gzip") |
| 668 | + try: |
| 669 | + return gzip.decompress(cert_data) |
| 670 | + except (zlib.error, gzip.BadGzipFile): |
| 671 | + logger.warning("Failed to decompressed with gzip") |
| 672 | + case (0x01, 0x00): # Net iD zlib format |
| 673 | + logger.debug("Decompressing certificate using zlib") |
| 674 | + expected_length = int.from_bytes(cert_data[2:4], "little") |
| 675 | + try: |
| 676 | + decompressed = zlib.decompress(cert_data[4:]) |
| 677 | + if len(decompressed) != expected_length: |
| 678 | + logger.error( |
| 679 | + "Unexpected decompressed length, expected %d, got %d", |
| 680 | + expected_length, |
| 681 | + len(decompressed), |
| 682 | + ) |
| 683 | + raise BadResponseError( |
| 684 | + "Decompressed length does not match expected length" |
| 685 | + ) |
| 686 | + |
| 687 | + return decompressed |
| 688 | + except (zlib.error, ValueError): |
| 689 | + logger.warning("Failed to decompress with zlib") |
| 690 | + case _: |
| 691 | + logger.warning("Unknown compression type") |
707 | 692 |
|
708 | 693 | raise BadResponseError("Failed to decompress certificate") |
709 | 694 |
|
|
0 commit comments