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()
|