File: x509.py

package info (click to toggle)
python-pkcs11 0.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 804 kB
  • sloc: python: 3,844; ansic: 1,981; sh: 33; makefile: 24
file content (120 lines) | stat: -rw-r--r-- 3,442 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""
Certificate handling utilities for X.509 (SSL) certificates.
"""

from asn1crypto.x509 import Certificate

from ..constants import Attribute, ObjectClass, CertificateType
from ..mechanisms import KeyType


def decode_x509_public_key(der):
    """
    Decode a DER-encoded X.509 certificate's public key into a set of
    attributes able to be passed to :meth:`pkcs11.Session.create_object`.

    For PEM-encoded certificates, use :func:`asn1crypto.pem.unarmor`.

    .. warning::

        Does not verify certificate.

    :param bytes der: DER-encoded certificate
    :rtype: dict(Attribute,*)
    """
    x509 = Certificate.load(der)
    key_info = x509.public_key
    key = bytes(key_info['public_key'])

    key_type = {
        'rsa': KeyType.RSA,
        'dsa': KeyType.DSA,
        'ec': KeyType.EC,
    }[key_info.algorithm]

    attrs = {
        Attribute.CLASS: ObjectClass.PUBLIC_KEY,
        Attribute.KEY_TYPE: key_type,
    }

    if key_type is KeyType.RSA:
        from .rsa import decode_rsa_public_key
        attrs.update(decode_rsa_public_key(key))
    elif key_type is KeyType.DSA:
        from .dsa import decode_dsa_domain_parameters, decode_dsa_public_key
        params = key_info['algorithm']['parameters'].dump()

        attrs.update(decode_dsa_domain_parameters(params))
        attrs.update({
            Attribute.VALUE: decode_dsa_public_key(key),
        })
    elif key_type is KeyType.EC:
        params = key_info['algorithm']['parameters'].dump()

        attrs.update({
            Attribute.EC_PARAMS: params,
            Attribute.EC_POINT: key,
        })
    else:
        raise AssertionError("Should not be reached")

    return attrs


def decode_x509_certificate(der, extended_set=False):
    """
    Decode a DER-encoded X.509 certificate into a dictionary of
    attributes able to be passed to :meth:`pkcs11.Session.create_object`.

    Optionally pass `extended_set` to include additional attributes:
    start date, end date and key identifiers.

    For PEM-encoded certificates, use :func:`asn1crypto.pem.unarmor`.

    .. warning::

        Does not verify certificate.

    :param bytes der: DER-encoded certificate
    :param extended_set: decodes more metadata about the certificate
    :rtype: dict(Attribute,*)
    """
    x509 = Certificate.load(der)
    subject = x509.subject
    issuer = x509.issuer
    serial = x509['tbs_certificate']['serial_number']

    template = {
        Attribute.CLASS: ObjectClass.CERTIFICATE,
        Attribute.CERTIFICATE_TYPE: CertificateType.X_509,
        Attribute.SUBJECT: subject.dump(),
        Attribute.ISSUER: issuer.dump(),
        Attribute.SERIAL_NUMBER: serial.dump(),
        Attribute.VALUE: x509.dump(),
    }

    if extended_set:
        start_date = \
            x509['tbs_certificate']['validity']['not_before'].native.date()
        end_date = \
            x509['tbs_certificate']['validity']['not_after'].native.date()

        template.update({
            Attribute.START_DATE: start_date,
            Attribute.END_DATE: end_date,
        })

        # FIXME: is this correct?
        try:
            template[Attribute.HASH_OF_SUBJECT_PUBLIC_KEY] = \
                x509.key_identifier
        except KeyError:
            pass

        try:
            template[Attribute.HASH_OF_ISSUER_PUBLIC_KEY] = \
                x509.authority_key_identifier
        except KeyError:
            pass

    return template