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
|