File: ec.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 (131 lines) | stat: -rw-r--r-- 3,534 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
121
122
123
124
125
126
127
128
129
130
131
"""
Key handling utilities for EC keys (ANSI X.62/RFC3279), domain parameter and
signatures.
"""

from asn1crypto.keys import (
    ECDomainParameters,
    ECPrivateKey,
    NamedCurve,
    PublicKeyInfo,
)
from asn1crypto.algos import DSASignature
from asn1crypto.core import OctetString
from ..constants import Attribute, ObjectClass
from ..mechanisms import KeyType


def encode_named_curve_parameters(oid):
    """
    Return DER-encoded ANSI X.62 EC parameters for a named curve.

    Curve names are given by object identifier or common name. Names come
    from `asn1crypto
    <https://github.com/wbond/asn1crypto/blob/master/asn1crypto/keys.py#L338>`_.

    :param str oid: OID or named curve
    :rtype: bytes
    """
    return ECDomainParameters(
        name='named',
        value=NamedCurve.unmap(oid),
    ).dump()


def decode_ec_public_key(der, encode_ec_point=True):
    """
    Decode a DER-encoded EC public key as stored by OpenSSL into a dictionary
    of attributes able to be passed to :meth:`pkcs11.Session.create_object`.

    .. note:: **encode_ec_point**

        For use as an attribute `EC_POINT` should be DER-encoded (True).

        For key derivation implementations can vary.  Since v2.30 the
        specification says implementations MUST accept a raw `EC_POINT` for
        ECDH (False), however not all implementations follow this yet.

    :param bytes der: DER-encoded key
    :param encode_ec_point: See text.
    :rtype: dict(Attribute,*)
    """
    asn1 = PublicKeyInfo.load(der)

    assert asn1.algorithm == 'ec', \
        "Wrong algorithm, not an EC key!"

    ecpoint = bytes(asn1['public_key'])

    if encode_ec_point:
        ecpoint = OctetString(ecpoint).dump()

    return {
        Attribute.KEY_TYPE: KeyType.EC,
        Attribute.CLASS: ObjectClass.PUBLIC_KEY,
        Attribute.EC_PARAMS: asn1['algorithm']['parameters'].dump(),
        Attribute.EC_POINT: ecpoint,
    }


def decode_ec_private_key(der):
    """
    Decode a DER-encoded EC private key as stored by OpenSSL into a dictionary
    of attributes able to be passed to :meth:`pkcs11.Session.create_object`.

    :param bytes der: DER-encoded key
    :rtype: dict(Attribute,*)
    """

    asn1 = ECPrivateKey.load(der)

    return {
        Attribute.KEY_TYPE: KeyType.EC,
        Attribute.CLASS: ObjectClass.PRIVATE_KEY,
        Attribute.EC_PARAMS: asn1['parameters'].chosen.dump(),
        Attribute.VALUE: asn1['private_key'].contents,
    }


def encode_ec_public_key(key):
    """
    Encode a DER-encoded EC public key as stored by OpenSSL.

    :param PublicKey key: EC public key
    :rtype: bytes
    """

    ecparams = ECDomainParameters.load(key[Attribute.EC_PARAMS])
    ecpoint = bytes(OctetString.load(key[Attribute.EC_POINT]))

    return PublicKeyInfo({
        'algorithm': {
            'algorithm': 'ec',
            'parameters': ecparams,
        },
        'public_key': ecpoint,
    }).dump()


def encode_ecdsa_signature(signature):
    """
    Encode a signature (generated by :meth:`pkcs11.SignMixin.sign`) into
    DER-encoded ASN.1 (ECDSA_Sig_Value) format.

    :param bytes signature: signature as bytes
    :rtype: bytes
    """

    return DSASignature.from_p1363(signature).dump()


def decode_ecdsa_signature(der):
    """
    Decode a DER-encoded ASN.1 (ECDSA_Sig_Value) signature (as generated by
    OpenSSL/X.509) into PKCS #11 format.

    :param bytes der: DER-encoded signature
    :rtype bytes:
    """

    asn1 = DSASignature.load(der)
    return asn1.to_p1363()