python-pkcs11 0.10.1__cp315-cp315-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import SupportsInt
4
+
5
+
6
+ def biginteger(value: SupportsInt) -> bytes:
7
+ """
8
+ Returns a PKCS#11 biginteger bytestream from a Python integer or
9
+ similar type (e.g. :class:`asn1crypto.core.Integer`).
10
+
11
+ :param int value: Value
12
+ :rtype: bytes
13
+ """
14
+
15
+ value_int = int(value) # In case it's a asn1 type or similar
16
+
17
+ return value_int.to_bytes((value_int.bit_length() + 7) // 8, byteorder="big")
pkcs11/util/dh.py ADDED
@@ -0,0 +1,79 @@
1
+ """
2
+ Key handling utilities for Diffie-Hellman keys.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ from asn1crypto.algos import DHParameters
10
+ from asn1crypto.core import Integer
11
+
12
+ from pkcs11.constants import Attribute
13
+ from pkcs11.util import biginteger
14
+
15
+ if TYPE_CHECKING:
16
+ from pkcs11.types import DomainParameters, PublicKey
17
+
18
+
19
+ def decode_dh_domain_parameters(der: bytes) -> dict[Attribute, Any]:
20
+ """
21
+ Decode DER-encoded Diffie-Hellman domain parameters.
22
+
23
+ :param bytes der: DER-encoded parameters
24
+ :rtype: dict(Attribute,*)
25
+ """
26
+
27
+ params = DHParameters.load(der)
28
+
29
+ return {
30
+ Attribute.BASE: biginteger(params["g"]),
31
+ Attribute.PRIME: biginteger(params["p"]),
32
+ }
33
+
34
+
35
+ def encode_dh_domain_parameters(obj: DomainParameters) -> bytes:
36
+ """
37
+ Encode DH domain parameters into DER-encoded format.
38
+
39
+ Calculates the subprime if it isn't available.
40
+
41
+ :param DomainParameters obj: domain parameters
42
+ :rtype: bytes
43
+ """
44
+
45
+ asn1 = DHParameters(
46
+ {
47
+ "g": int.from_bytes(obj[Attribute.BASE], byteorder="big"),
48
+ "p": int.from_bytes(obj[Attribute.PRIME], byteorder="big"),
49
+ }
50
+ )
51
+
52
+ return asn1.dump()
53
+
54
+
55
+ def encode_dh_public_key(key: PublicKey) -> bytes:
56
+ """
57
+ Encode DH public key into RFC 3279 DER-encoded format.
58
+
59
+ :param PublicKey key: public key
60
+ :rtype: bytes
61
+ """
62
+
63
+ asn1 = Integer(int.from_bytes(key[Attribute.VALUE], byteorder="big"))
64
+
65
+ return asn1.dump()
66
+
67
+
68
+ def decode_dh_public_key(der: bytes) -> bytes:
69
+ """
70
+ Decode a DH public key from RFC 3279 DER-encoded format.
71
+
72
+ Returns a `biginteger` encoded as bytes.
73
+
74
+ :param bytes der: DER-encoded public key
75
+ :rtype: bytes
76
+ """
77
+
78
+ asn1 = Integer.load(der)
79
+ return biginteger(asn1)
pkcs11/util/dsa.py ADDED
@@ -0,0 +1,108 @@
1
+ """
2
+ Key handling utilities for DSA keys, domain parameters and signatures..
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ from asn1crypto.algos import DSASignature
10
+ from asn1crypto.core import Integer
11
+ from asn1crypto.keys import DSAParams
12
+
13
+ from pkcs11.constants import Attribute
14
+ from pkcs11.util import biginteger
15
+
16
+ if TYPE_CHECKING:
17
+ from pkcs11.types import DomainParameters, PublicKey
18
+
19
+
20
+ def decode_dsa_domain_parameters(der: bytes) -> dict[Attribute, Any]:
21
+ """
22
+ Decode RFC 3279 DER-encoded Dss-Params.
23
+
24
+ :param bytes der: DER-encoded parameters
25
+ :rtype: dict(Attribute,*)
26
+ """
27
+
28
+ params = DSAParams.load(der)
29
+
30
+ return {
31
+ Attribute.BASE: biginteger(params["g"]),
32
+ Attribute.PRIME: biginteger(params["p"]),
33
+ Attribute.SUBPRIME: biginteger(params["q"]),
34
+ }
35
+
36
+
37
+ def encode_dsa_domain_parameters(obj: DomainParameters) -> bytes:
38
+ """
39
+ Encode RFC 3279 DER-encoded Dss-Params.
40
+
41
+ :param DomainParameters obj: domain parameters
42
+ :rtype: bytes
43
+ """
44
+ asn1 = DSAParams(
45
+ {
46
+ "g": int.from_bytes(obj[Attribute.BASE], byteorder="big"),
47
+ "p": int.from_bytes(obj[Attribute.PRIME], byteorder="big"),
48
+ "q": int.from_bytes(obj[Attribute.SUBPRIME], byteorder="big"),
49
+ }
50
+ )
51
+
52
+ return asn1.dump()
53
+
54
+
55
+ def encode_dsa_public_key(key: PublicKey) -> bytes:
56
+ """
57
+ Encode DSA public key into RFC 3279 DER-encoded format.
58
+
59
+ :param PublicKey key: public key
60
+ :rtype: bytes
61
+ """
62
+
63
+ asn1 = Integer(int.from_bytes(key[Attribute.VALUE], byteorder="big"))
64
+
65
+ return asn1.dump()
66
+
67
+
68
+ def decode_dsa_public_key(der: bytes) -> bytes:
69
+ """
70
+ Decode a DSA public key from RFC 3279 DER-encoded format.
71
+
72
+ Returns a `biginteger` encoded as bytes.
73
+
74
+ :param bytes der: DER-encoded public key
75
+ :rtype: bytes
76
+ """
77
+
78
+ asn1 = Integer.load(der)
79
+
80
+ return biginteger(asn1)
81
+
82
+
83
+ def encode_dsa_signature(signature: bytes) -> bytes:
84
+ """
85
+ Encode a signature (generated by :meth:`pkcs11.SignMixin.sign`) into
86
+ DER-encoded ASN.1 (Dss_Sig_Value) format.
87
+
88
+ :param bytes signature: signature as bytes
89
+ :rtype: bytes
90
+ """
91
+
92
+ asn1 = DSASignature.from_p1363(signature)
93
+
94
+ return asn1.dump()
95
+
96
+
97
+ def decode_dsa_signature(der: bytes) -> bytes:
98
+ """
99
+ Decode a DER-encoded ASN.1 (Dss_Sig_Value) signature (as generated by
100
+ OpenSSL/X.509) into PKCS #11 format.
101
+
102
+ :param bytes der: DER-encoded signature
103
+ :rtype bytes:
104
+ """
105
+
106
+ asn1 = DSASignature.load(der)
107
+
108
+ return asn1.to_p1363()
pkcs11/util/ec.py ADDED
@@ -0,0 +1,143 @@
1
+ """
2
+ Key handling utilities for EC keys (ANSI X.62/RFC3279), domain parameter and
3
+ signatures.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import TYPE_CHECKING, Any
9
+
10
+ from asn1crypto.algos import DSASignature
11
+ from asn1crypto.core import OctetString
12
+ from asn1crypto.keys import (
13
+ ECDomainParameters,
14
+ ECPrivateKey,
15
+ NamedCurve,
16
+ PublicKeyInfo,
17
+ )
18
+
19
+ from pkcs11.constants import Attribute, ObjectClass
20
+ from pkcs11.mechanisms import KeyType
21
+
22
+ if TYPE_CHECKING:
23
+ from pkcs11.types import PublicKey
24
+
25
+
26
+ def encode_named_curve_parameters(oid: str) -> bytes:
27
+ """
28
+ Return DER-encoded ANSI X.62 EC parameters for a named curve.
29
+
30
+ Curve names are given by object identifier or common name. Names come
31
+ from `asn1crypto
32
+ <https://github.com/wbond/asn1crypto/blob/master/asn1crypto/keys.py#L338>`_.
33
+
34
+ :param str oid: OID or named curve
35
+ :rtype: bytes
36
+ """
37
+ return ECDomainParameters(
38
+ name="named",
39
+ value=NamedCurve.unmap(oid),
40
+ ).dump()
41
+
42
+
43
+ def decode_ec_public_key(
44
+ der: bytes,
45
+ encode_ec_point: bool = True,
46
+ ) -> dict[Attribute, Any]:
47
+ """
48
+ Decode a DER-encoded EC public key as stored by OpenSSL into a dictionary
49
+ of attributes able to be passed to :meth:`pkcs11.Session.create_object`.
50
+
51
+ .. note:: **encode_ec_point**
52
+
53
+ For use as an attribute `EC_POINT` should be DER-encoded (True).
54
+
55
+ For key derivation implementations can vary. Since v2.30 the
56
+ specification says implementations MUST accept a raw `EC_POINT` for
57
+ ECDH (False), however not all implementations follow this yet.
58
+
59
+ :param bytes der: DER-encoded key
60
+ :param encode_ec_point: See text.
61
+ :rtype: dict(Attribute,*)
62
+ """
63
+ asn1 = PublicKeyInfo.load(der)
64
+
65
+ assert asn1.algorithm == "ec", "Wrong algorithm, not an EC key!"
66
+
67
+ ecpoint = bytes(asn1["public_key"])
68
+
69
+ if encode_ec_point:
70
+ ecpoint = OctetString(ecpoint).dump()
71
+
72
+ return {
73
+ Attribute.KEY_TYPE: KeyType.EC,
74
+ Attribute.CLASS: ObjectClass.PUBLIC_KEY,
75
+ Attribute.EC_PARAMS: asn1["algorithm"]["parameters"].dump(),
76
+ Attribute.EC_POINT: ecpoint,
77
+ }
78
+
79
+
80
+ def decode_ec_private_key(der: bytes) -> dict[Attribute, Any]:
81
+ """
82
+ Decode a DER-encoded EC private key as stored by OpenSSL into a dictionary
83
+ of attributes able to be passed to :meth:`pkcs11.Session.create_object`.
84
+
85
+ :param bytes der: DER-encoded key
86
+ :rtype: dict(Attribute,*)
87
+ """
88
+
89
+ asn1 = ECPrivateKey.load(der)
90
+
91
+ return {
92
+ Attribute.KEY_TYPE: KeyType.EC,
93
+ Attribute.CLASS: ObjectClass.PRIVATE_KEY,
94
+ Attribute.EC_PARAMS: asn1["parameters"].chosen.dump(),
95
+ Attribute.VALUE: asn1["private_key"].contents,
96
+ }
97
+
98
+
99
+ def encode_ec_public_key(key: PublicKey) -> bytes:
100
+ """
101
+ Encode a DER-encoded EC public key as stored by OpenSSL.
102
+
103
+ :param PublicKey key: EC public key
104
+ :rtype: bytes
105
+ """
106
+
107
+ ecparams = ECDomainParameters.load(key[Attribute.EC_PARAMS])
108
+ ecpoint = bytes(OctetString.load(key[Attribute.EC_POINT]))
109
+
110
+ return PublicKeyInfo(
111
+ {
112
+ "algorithm": {
113
+ "algorithm": "ec",
114
+ "parameters": ecparams,
115
+ },
116
+ "public_key": ecpoint,
117
+ }
118
+ ).dump()
119
+
120
+
121
+ def encode_ecdsa_signature(signature: bytes) -> bytes:
122
+ """
123
+ Encode a signature (generated by :meth:`pkcs11.SignMixin.sign`) into
124
+ DER-encoded ASN.1 (ECDSA_Sig_Value) format.
125
+
126
+ :param bytes signature: signature as bytes
127
+ :rtype: bytes
128
+ """
129
+
130
+ return DSASignature.from_p1363(signature).dump()
131
+
132
+
133
+ def decode_ecdsa_signature(der: bytes) -> bytes:
134
+ """
135
+ Decode a DER-encoded ASN.1 (ECDSA_Sig_Value) signature (as generated by
136
+ OpenSSL/X.509) into PKCS #11 format.
137
+
138
+ :param bytes der: DER-encoded signature
139
+ :rtype bytes:
140
+ """
141
+
142
+ asn1 = DSASignature.load(der)
143
+ return asn1.to_p1363()
pkcs11/util/rsa.py ADDED
@@ -0,0 +1,95 @@
1
+ """
2
+ Key handling utilities for RSA keys (PKCS#1).
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ from asn1crypto.keys import RSAPrivateKey, RSAPublicKey
10
+
11
+ from pkcs11.constants import Attribute, MechanismFlag, ObjectClass
12
+ from pkcs11.defaults import DEFAULT_KEY_CAPABILITIES
13
+ from pkcs11.mechanisms import KeyType
14
+ from pkcs11.util import biginteger
15
+
16
+ if TYPE_CHECKING:
17
+ from pkcs11.types import PublicKey
18
+
19
+
20
+ def decode_rsa_private_key(
21
+ der: bytes,
22
+ capabilities: MechanismFlag | int | None = None,
23
+ ) -> dict[Attribute, Any]:
24
+ """
25
+ Decode a RFC2437 (PKCS#1) DER-encoded RSA private key into a dictionary of
26
+ attributes able to be passed to :meth:`pkcs11.Session.create_object`.
27
+
28
+ :param bytes der: DER-encoded key
29
+ :param MechanismFlag capabilities: Optional key capabilities
30
+ :rtype: dict(Attribute,*)
31
+ """
32
+ caps: MechanismFlag | int = (
33
+ DEFAULT_KEY_CAPABILITIES[KeyType.RSA] if capabilities is None else capabilities
34
+ )
35
+
36
+ key = RSAPrivateKey.load(der)
37
+
38
+ return {
39
+ Attribute.CLASS: ObjectClass.PRIVATE_KEY,
40
+ Attribute.KEY_TYPE: KeyType.RSA,
41
+ Attribute.MODULUS: biginteger(key["modulus"]),
42
+ Attribute.PUBLIC_EXPONENT: biginteger(key["public_exponent"]),
43
+ Attribute.PRIVATE_EXPONENT: biginteger(key["private_exponent"]),
44
+ Attribute.PRIME_1: biginteger(key["prime1"]),
45
+ Attribute.PRIME_2: biginteger(key["prime2"]),
46
+ Attribute.EXPONENT_1: biginteger(key["exponent1"]),
47
+ Attribute.EXPONENT_2: biginteger(key["exponent2"]),
48
+ Attribute.COEFFICIENT: biginteger(key["coefficient"]),
49
+ Attribute.DECRYPT: MechanismFlag.DECRYPT & caps != 0,
50
+ Attribute.SIGN: MechanismFlag.SIGN & caps != 0,
51
+ Attribute.UNWRAP: MechanismFlag.UNWRAP & caps != 0,
52
+ }
53
+
54
+
55
+ def decode_rsa_public_key(
56
+ der: bytes,
57
+ capabilities: MechanismFlag | int | None = None,
58
+ ) -> dict[Attribute, Any]:
59
+ """
60
+ Decode a RFC2437 (PKCS#1) DER-encoded RSA public key into a dictionary of
61
+ attributes able to be passed to :meth:`pkcs11.Session.create_object`.
62
+
63
+ :param bytes der: DER-encoded key
64
+ :param MechanismFlag capabilities: Optional key capabilities
65
+ :rtype: dict(Attribute,*)
66
+ """
67
+ caps: MechanismFlag | int = (
68
+ DEFAULT_KEY_CAPABILITIES[KeyType.RSA] if capabilities is None else capabilities
69
+ )
70
+
71
+ key = RSAPublicKey.load(der)
72
+ return {
73
+ Attribute.CLASS: ObjectClass.PUBLIC_KEY,
74
+ Attribute.KEY_TYPE: KeyType.RSA,
75
+ Attribute.MODULUS: biginteger(key["modulus"]),
76
+ Attribute.PUBLIC_EXPONENT: biginteger(key["public_exponent"]),
77
+ Attribute.ENCRYPT: MechanismFlag.ENCRYPT & caps != 0,
78
+ Attribute.VERIFY: MechanismFlag.VERIFY & caps != 0,
79
+ Attribute.WRAP: MechanismFlag.WRAP & caps != 0,
80
+ }
81
+
82
+
83
+ def encode_rsa_public_key(key: PublicKey) -> bytes:
84
+ """
85
+ Encode an RSA public key into PKCS#1 DER-encoded format.
86
+
87
+ :param PublicKey key: RSA public key
88
+ :rtype: bytes
89
+ """
90
+ return RSAPublicKey(
91
+ {
92
+ "modulus": int.from_bytes(key[Attribute.MODULUS], byteorder="big"),
93
+ "public_exponent": int.from_bytes(key[Attribute.PUBLIC_EXPONENT], byteorder="big"),
94
+ }
95
+ ).dump()
pkcs11/util/x509.py ADDED
@@ -0,0 +1,136 @@
1
+ """
2
+ Certificate handling utilities for X.509 (SSL) certificates.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from asn1crypto.core import OctetString
10
+ from asn1crypto.x509 import Certificate
11
+
12
+ from pkcs11.constants import Attribute, CertificateType, ObjectClass
13
+ from pkcs11.mechanisms import KeyType
14
+
15
+
16
+ def decode_x509_public_key(der: bytes) -> dict[Attribute, Any]:
17
+ """
18
+ Decode a DER-encoded X.509 certificate's public key into a set of
19
+ attributes able to be passed to :meth:`pkcs11.Session.create_object`.
20
+
21
+ For PEM-encoded certificates, use :func:`asn1crypto.pem.unarmor`.
22
+
23
+ .. warning::
24
+
25
+ Does not verify certificate.
26
+
27
+ :param bytes der: DER-encoded certificate
28
+ :rtype: dict(Attribute,*)
29
+ """
30
+ x509 = Certificate.load(der)
31
+ key_info = x509.public_key
32
+ key = bytes(key_info["public_key"])
33
+
34
+ key_type = {
35
+ "rsa": KeyType.RSA,
36
+ "dsa": KeyType.DSA,
37
+ "ec": KeyType.EC,
38
+ }[key_info.algorithm]
39
+
40
+ attrs: dict[Attribute, Any] = {
41
+ Attribute.CLASS: ObjectClass.PUBLIC_KEY,
42
+ Attribute.KEY_TYPE: key_type,
43
+ }
44
+
45
+ if key_type is KeyType.RSA:
46
+ from .rsa import decode_rsa_public_key
47
+
48
+ attrs.update(decode_rsa_public_key(key))
49
+ elif key_type is KeyType.DSA:
50
+ from .dsa import decode_dsa_domain_parameters, decode_dsa_public_key
51
+
52
+ params = key_info["algorithm"]["parameters"].dump()
53
+
54
+ attrs.update(decode_dsa_domain_parameters(params))
55
+ attrs.update(
56
+ {
57
+ Attribute.VALUE: decode_dsa_public_key(key),
58
+ }
59
+ )
60
+ elif key_type is KeyType.EC:
61
+ params = key_info["algorithm"]["parameters"].dump()
62
+
63
+ # bytes(key_info['public_key']) returns the binary encoding
64
+ # of the EC point itself (decoded from its BitString representation in X.509),
65
+ # but PKCS#11 expects this as a DER OctetString.
66
+ key = OctetString(key).dump()
67
+ attrs.update(
68
+ {
69
+ Attribute.EC_PARAMS: params,
70
+ Attribute.EC_POINT: key,
71
+ }
72
+ )
73
+ else:
74
+ raise AssertionError("Should not be reached")
75
+
76
+ return attrs
77
+
78
+
79
+ def decode_x509_certificate(
80
+ der: bytes,
81
+ extended_set: bool = False,
82
+ ) -> dict[Attribute, Any]:
83
+ """
84
+ Decode a DER-encoded X.509 certificate into a dictionary of
85
+ attributes able to be passed to :meth:`pkcs11.Session.create_object`.
86
+
87
+ Optionally pass `extended_set` to include additional attributes:
88
+ start date, end date and key identifiers.
89
+
90
+ For PEM-encoded certificates, use :func:`asn1crypto.pem.unarmor`.
91
+
92
+ .. warning::
93
+
94
+ Does not verify certificate.
95
+
96
+ :param bytes der: DER-encoded certificate
97
+ :param extended_set: decodes more metadata about the certificate
98
+ :rtype: dict(Attribute,*)
99
+ """
100
+ x509 = Certificate.load(der)
101
+ subject = x509.subject
102
+ issuer = x509.issuer
103
+ serial = x509["tbs_certificate"]["serial_number"]
104
+
105
+ template: dict[Attribute, Any] = {
106
+ Attribute.CLASS: ObjectClass.CERTIFICATE,
107
+ Attribute.CERTIFICATE_TYPE: CertificateType.X_509,
108
+ Attribute.SUBJECT: subject.dump(),
109
+ Attribute.ISSUER: issuer.dump(),
110
+ Attribute.SERIAL_NUMBER: serial.dump(),
111
+ Attribute.VALUE: x509.dump(),
112
+ }
113
+
114
+ if extended_set:
115
+ start_date = x509["tbs_certificate"]["validity"]["not_before"].native.date()
116
+ end_date = x509["tbs_certificate"]["validity"]["not_after"].native.date()
117
+
118
+ template.update(
119
+ {
120
+ Attribute.START_DATE: start_date,
121
+ Attribute.END_DATE: end_date,
122
+ }
123
+ )
124
+
125
+ # FIXME: is this correct?
126
+ try:
127
+ template[Attribute.HASH_OF_SUBJECT_PUBLIC_KEY] = x509.key_identifier
128
+ except KeyError:
129
+ pass
130
+
131
+ try:
132
+ template[Attribute.HASH_OF_ISSUER_PUBLIC_KEY] = x509.authority_key_identifier
133
+ except KeyError:
134
+ pass
135
+
136
+ return template