aboutsummaryrefslogtreecommitdiff
path: root/freezed_deps/ecdsa/keys.py
diff options
context:
space:
mode:
Diffstat (limited to 'freezed_deps/ecdsa/keys.py')
-rw-r--r--freezed_deps/ecdsa/keys.py1219
1 files changed, 0 insertions, 1219 deletions
diff --git a/freezed_deps/ecdsa/keys.py b/freezed_deps/ecdsa/keys.py
deleted file mode 100644
index 172fdf5..0000000
--- a/freezed_deps/ecdsa/keys.py
+++ /dev/null
@@ -1,1219 +0,0 @@
-"""
-Primary classes for performing signing and verification operations.
-
-.. glossary::
-
- raw encoding
- Conversion of public, private keys and signatures (which in
- mathematical sense are integers or pairs of integers) to strings of
- bytes that does not use any special tags or encoding rules.
- For any given curve, all keys of the same type or signatures will be
- encoded to byte strings of the same length. In more formal sense,
- the integers are encoded as big-endian, constant length byte strings,
- where the string length is determined by the curve order (e.g.
- for NIST256p the order is 256 bits long, so the private key will be 32
- bytes long while public key will be 64 bytes long). The encoding of a
- single integer is zero-padded on the left if the numerical value is
- low. In case of public keys and signatures, which are comprised of two
- integers, the integers are simply concatenated.
-
- uncompressed
- The most common formatting specified in PKIX standards. Specified in
- X9.62 and SEC1 standards. The only difference between it and
- :term:`raw encoding` is the prepending of a 0x04 byte. Thus an
- uncompressed NIST256p public key encoding will be 65 bytes long.
-
- compressed
- The public point representation that uses half of bytes of the
- :term:`uncompressed` encoding (rounded up). It uses the first byte of
- the encoding to specify the sign of the y coordinate and encodes the
- x coordinate as-is. The first byte of the encoding is equal to
- 0x02 or 0x03. Compressed encoding of NIST256p public key will be 33
- bytes long.
-
- hybrid
- A combination of :term:`uncompressed` and :term:`compressed` encodings.
- Both x and y coordinates are stored just as in :term:`compressed`
- encoding, but the first byte reflects the sign of the y coordinate. The
- first byte of the encoding will be equal to 0x06 or 0x7. Hybrid
- encoding of NIST256p public key will be 65 bytes long.
-
- PEM
- The acronym stands for Privacy Enhanced Email, but currently it is used
- primarily as the way to encode :term:`DER` objects into text that can
- be either easily copy-pasted or transferred over email.
- It uses headers like ``-----BEGIN <type of contents>-----`` and footers
- like ``-----END <type of contents>-----`` to separate multiple
- types of objects in the same file or the object from the surrounding
- comments. The actual object stored is base64 encoded.
-
- DER
- Distinguished Encoding Rules, the way to encode :term:`ASN.1` objects
- deterministically and uniquely into byte strings.
-
- ASN.1
- Abstract Syntax Notation 1 is a standard description language for
- specifying serialisation and deserialisation of data structures in a
- portable and cross-platform way.
-
- bytes-like object
- All the types that implement the buffer protocol. That includes
- ``str`` (only on python2), ``bytes``, ``bytesarray``, ``array.array`
- and ``memoryview`` of those objects.
- Please note that ``array.array` serialisation (converting it to byte
- string) is endianess dependant! Signature computed over ``array.array``
- of integers on a big-endian system will not be verified on a
- little-endian system and vice-versa.
-"""
-
-import binascii
-from hashlib import sha1
-from six import PY3, b
-from . import ecdsa
-from . import der
-from . import rfc6979
-from . import ellipticcurve
-from .curves import NIST192p, find_curve
-from .numbertheory import square_root_mod_prime, SquareRootError
-from .ecdsa import RSZeroError
-from .util import string_to_number, number_to_string, randrange
-from .util import sigencode_string, sigdecode_string
-from .util import oid_ecPublicKey, encoded_oid_ecPublicKey, MalformedSignature
-from ._compat import normalise_bytes
-
-
-__all__ = ["BadSignatureError", "BadDigestError", "VerifyingKey", "SigningKey",
- "MalformedPointError"]
-
-
-class BadSignatureError(Exception):
- """
- Raised when verification of signature failed.
-
- Will be raised irrespective of reason of the failure:
-
- * the calculated or provided hash does not match the signature
- * the signature does not match the curve/public key
- * the encoding of the signature is malformed
- * the size of the signature does not match the curve of the VerifyingKey
- """
-
- pass
-
-
-class BadDigestError(Exception):
- """Raised in case the selected hash is too large for the curve."""
-
- pass
-
-
-class MalformedPointError(AssertionError):
- """Raised in case the encoding of private or public key is malformed."""
-
- pass
-
-
-class VerifyingKey(object):
- """
- Class for handling keys that can verify signatures (public keys).
-
- :ivar ecdsa.curves.Curve curve: The Curve over which all the cryptographic
- operations will take place
- :ivar default_hashfunc: the function that will be used for hashing the
- data. Should implement the same API as hashlib.sha1
- :vartype default_hashfunc: callable
- :ivar pubkey: the actual public key
- :vartype pubkey: ecdsa.ecdsa.Public_key
- """
-
- def __init__(self, _error__please_use_generate=None):
- """Unsupported, please use one of the classmethods to initialise."""
- if not _error__please_use_generate:
- raise TypeError("Please use VerifyingKey.generate() to "
- "construct me")
- self.curve = None
- self.default_hashfunc = None
- self.pubkey = None
-
- def __repr__(self):
- pub_key = self.to_string("compressed")
- return "VerifyingKey.from_string({0!r}, {1!r}, {2})".format(
- pub_key, self.curve, self.default_hashfunc().name)
-
- def __eq__(self, other):
- """Return True if the points are identical, False otherwise."""
- if isinstance(other, VerifyingKey):
- return self.curve == other.curve \
- and self.pubkey == other.pubkey
- return NotImplemented
-
- @classmethod
- def from_public_point(cls, point, curve=NIST192p, hashfunc=sha1,
- validate_point=True):
- """
- Initialise the object from a Point object.
-
- This is a low-level method, generally you will not want to use it.
-
- :param point: The point to wrap around, the actual public key
- :type point: ecdsa.ellipticcurve.Point
- :param curve: The curve on which the point needs to reside, defaults
- to NIST192p
- :type curve: ecdsa.curves.Curve
- :param hashfunc: The default hash function that will be used for
- verification, needs to implement the same interface
- as hashlib.sha1
- :type hashfunc: callable
- :type bool validate_point: whether to check if the point lies on curve
- should always be used if the public point is not a result
- of our own calculation
-
- :raises MalformedPointError: if the public point does not lie on the
- curve
-
- :return: Initialised VerifyingKey object
- :rtype: VerifyingKey
- """
- self = cls(_error__please_use_generate=True)
- if not isinstance(point, ellipticcurve.PointJacobi):
- point = ellipticcurve.PointJacobi.from_affine(point)
- self.curve = curve
- self.default_hashfunc = hashfunc
- try:
- self.pubkey = ecdsa.Public_key(curve.generator, point,
- validate_point)
- except ecdsa.InvalidPointError:
- raise MalformedPointError("Point does not lie on the curve")
- self.pubkey.order = curve.order
- return self
-
- def precompute(self):
- self.pubkey.point = ellipticcurve.PointJacobi.from_affine(
- self.pubkey.point, True)
-
- @staticmethod
- def _from_raw_encoding(string, curve):
- """
- Decode public point from :term:`raw encoding`.
-
- :term:`raw encoding` is the same as the :term:`uncompressed` encoding,
- but without the 0x04 byte at the beginning.
- """
- order = curve.order
- # real assert, from_string() should not call us with different length
- assert len(string) == curve.verifying_key_length
- xs = string[:curve.baselen]
- ys = string[curve.baselen:]
- if len(xs) != curve.baselen:
- raise MalformedPointError("Unexpected length of encoded x")
- if len(ys) != curve.baselen:
- raise MalformedPointError("Unexpected length of encoded y")
- x = string_to_number(xs)
- y = string_to_number(ys)
-
- return ellipticcurve.PointJacobi(curve.curve, x, y, 1, order)
-
- @staticmethod
- def _from_compressed(string, curve):
- """Decode public point from compressed encoding."""
- if string[:1] not in (b('\x02'), b('\x03')):
- raise MalformedPointError("Malformed compressed point encoding")
-
- is_even = string[:1] == b('\x02')
- x = string_to_number(string[1:])
- order = curve.order
- p = curve.curve.p()
- alpha = (pow(x, 3, p) + (curve.curve.a() * x) + curve.curve.b()) % p
- try:
- beta = square_root_mod_prime(alpha, p)
- except SquareRootError as e:
- raise MalformedPointError(
- "Encoding does not correspond to a point on curve", e)
- if is_even == bool(beta & 1):
- y = p - beta
- else:
- y = beta
- return ellipticcurve.PointJacobi(curve.curve, x, y, 1, order)
-
- @classmethod
- def _from_hybrid(cls, string, curve, validate_point):
- """Decode public point from hybrid encoding."""
- # real assert, from_string() should not call us with different types
- assert string[:1] in (b('\x06'), b('\x07'))
-
- # primarily use the uncompressed as it's easiest to handle
- point = cls._from_raw_encoding(string[1:], curve)
-
- # but validate if it's self-consistent if we're asked to do that
- if validate_point \
- and (point.y() & 1 and string[:1] != b('\x07')
- or (not point.y() & 1) and string[:1] != b('\x06')):
- raise MalformedPointError("Inconsistent hybrid point encoding")
-
- return point
-
- @classmethod
- def from_string(cls, string, curve=NIST192p, hashfunc=sha1,
- validate_point=True):
- """
- Initialise the object from byte encoding of public key.
-
- The method does accept and automatically detect the type of point
- encoding used. It supports the :term:`raw encoding`,
- :term:`uncompressed`, :term:`compressed` and :term:`hybrid` encodings.
-
- Note, while the method is named "from_string" it's a misnomer from
- Python 2 days when there were no binary strings. In Python 3 the
- input needs to be a bytes-like object.
-
- :param string: single point encoding of the public key
- :type string: :term:`bytes-like object`
- :param curve: the curve on which the public key is expected to lie
- :type curve: ecdsa.curves.Curve
- :param hashfunc: The default hash function that will be used for
- verification, needs to implement the same interface as hashlib.sha1
- :type hashfunc: callable
- :param validate_point: whether to verify that the point lies on the
- provided curve or not, defaults to True
- :type validate_point: bool
-
- :raises MalformedPointError: if the public point does not lie on the
- curve or the encoding is invalid
-
- :return: Initialised VerifyingKey object
- :rtype: VerifyingKey
- """
- string = normalise_bytes(string)
- sig_len = len(string)
- if sig_len == curve.verifying_key_length:
- point = cls._from_raw_encoding(string, curve)
- elif sig_len == curve.verifying_key_length + 1:
- if string[:1] in (b('\x06'), b('\x07')):
- point = cls._from_hybrid(string, curve, validate_point)
- elif string[:1] == b('\x04'):
- point = cls._from_raw_encoding(string[1:], curve)
- else:
- raise MalformedPointError(
- "Invalid X9.62 encoding of the public point")
- elif sig_len == curve.baselen + 1:
- point = cls._from_compressed(string, curve)
- else:
- raise MalformedPointError(
- "Length of string does not match lengths of "
- "any of the supported encodings of {0} "
- "curve.".format(curve.name))
- return cls.from_public_point(point, curve, hashfunc,
- validate_point)
-
- @classmethod
- def from_pem(cls, string, hashfunc=sha1):
- """
- Initialise from public key stored in :term:`PEM` format.
-
- The PEM header of the key should be ``BEGIN PUBLIC KEY``.
-
- See the :func:`~VerifyingKey.from_der()` method for details of the
- format supported.
-
- Note: only a single PEM object encoding is supported in provided
- string.
-
- :param string: text with PEM-encoded public ECDSA key
- :type string: str
-
- :return: Initialised VerifyingKey object
- :rtype: VerifyingKey
- """
- return cls.from_der(der.unpem(string), hashfunc=hashfunc)
-
- @classmethod
- def from_der(cls, string, hashfunc=sha1):
- """
- Initialise the key stored in :term:`DER` format.
-
- The expected format of the key is the SubjectPublicKeyInfo structure
- from RFC5912 (for RSA keys, it's known as the PKCS#1 format)::
-
- SubjectPublicKeyInfo {PUBLIC-KEY: IOSet} ::= SEQUENCE {
- algorithm AlgorithmIdentifier {PUBLIC-KEY, {IOSet}},
- subjectPublicKey BIT STRING
- }
-
- Note: only public EC keys are supported by this method. The
- SubjectPublicKeyInfo.algorithm.algorithm field must specify
- id-ecPublicKey (see RFC3279).
-
- Only the named curve encoding is supported, thus the
- SubjectPublicKeyInfo.algorithm.parameters field needs to be an
- object identifier. A sequence in that field indicates an explicit
- parameter curve encoding, this format is not supported. A NULL object
- in that field indicates an "implicitlyCA" encoding, where the curve
- parameters come from CA certificate, those, again, are not supported.
-
- :param string: binary string with the DER encoding of public ECDSA key
- :type string: bytes-like object
-
- :return: Initialised VerifyingKey object
- :rtype: VerifyingKey
- """
- string = normalise_bytes(string)
- # [[oid_ecPublicKey,oid_curve], point_str_bitstring]
- s1, empty = der.remove_sequence(string)
- if empty != b"":
- raise der.UnexpectedDER("trailing junk after DER pubkey: %s" %
- binascii.hexlify(empty))
- s2, point_str_bitstring = der.remove_sequence(s1)
- # s2 = oid_ecPublicKey,oid_curve
- oid_pk, rest = der.remove_object(s2)
- oid_curve, empty = der.remove_object(rest)
- if empty != b"":
- raise der.UnexpectedDER("trailing junk after DER pubkey objects: %s" %
- binascii.hexlify(empty))
- if not oid_pk == oid_ecPublicKey:
- raise der.UnexpectedDER("Unexpected object identifier in DER "
- "encoding: {0!r}".format(oid_pk))
- curve = find_curve(oid_curve)
- point_str, empty = der.remove_bitstring(point_str_bitstring, 0)
- if empty != b"":
- raise der.UnexpectedDER("trailing junk after pubkey pointstring: %s" %
- binascii.hexlify(empty))
- # raw encoding of point is invalid in DER files
- if len(point_str) == curve.verifying_key_length:
- raise der.UnexpectedDER("Malformed encoding of public point")
- return cls.from_string(point_str, curve, hashfunc=hashfunc)
-
- @classmethod
- def from_public_key_recovery(cls, signature, data, curve, hashfunc=sha1,
- sigdecode=sigdecode_string):
- """
- Return keys that can be used as verifiers of the provided signature.
-
- Tries to recover the public key that can be used to verify the
- signature, usually returns two keys like that.
-
- :param signature: the byte string with the encoded signature
- :type signature: bytes-like object
- :param data: the data to be hashed for signature verification
- :type data: bytes-like object
- :param curve: the curve over which the signature was performed
- :type curve: ecdsa.curves.Curve
- :param hashfunc: The default hash function that will be used for
- verification, needs to implement the same interface as hashlib.sha1
- :type hashfunc: callable
- :param sigdecode: Callable to define the way the signature needs to
- be decoded to an object, needs to handle `signature` as the
- first parameter, the curve order (an int) as the second and return
- a tuple with two integers, "r" as the first one and "s" as the
- second one. See :func:`ecdsa.util.sigdecode_string` and
- :func:`ecdsa.util.sigdecode_der` for examples.
- :type sigdecode: callable
-
- :return: Initialised VerifyingKey objects
- :rtype: list of VerifyingKey
- """
- data = normalise_bytes(data)
- digest = hashfunc(data).digest()
- return cls.from_public_key_recovery_with_digest(
- signature, digest, curve, hashfunc=hashfunc,
- sigdecode=sigdecode)
-
- @classmethod
- def from_public_key_recovery_with_digest(
- cls, signature, digest, curve,
- hashfunc=sha1, sigdecode=sigdecode_string):
- """
- Return keys that can be used as verifiers of the provided signature.
-
- Tries to recover the public key that can be used to verify the
- signature, usually returns two keys like that.
-
- :param signature: the byte string with the encoded signature
- :type signature: bytes-like object
- :param digest: the hash value of the message signed by the signature
- :type digest: bytes-like object
- :param curve: the curve over which the signature was performed
- :type curve: ecdsa.curves.Curve
- :param hashfunc: The default hash function that will be used for
- verification, needs to implement the same interface as hashlib.sha1
- :type hashfunc: callable
- :param sigdecode: Callable to define the way the signature needs to
- be decoded to an object, needs to handle `signature` as the
- first parameter, the curve order (an int) as the second and return
- a tuple with two integers, "r" as the first one and "s" as the
- second one. See :func:`ecdsa.util.sigdecode_string` and
- :func:`ecdsa.util.sigdecode_der` for examples.
- :type sigdecode: callable
-
-
- :return: Initialised VerifyingKey object
- :rtype: VerifyingKey
- """
- generator = curve.generator
- r, s = sigdecode(signature, generator.order())
- sig = ecdsa.Signature(r, s)
-
- digest = normalise_bytes(digest)
- digest_as_number = string_to_number(digest)
- pks = sig.recover_public_keys(digest_as_number, generator)
-
- # Transforms the ecdsa.Public_key object into a VerifyingKey
- verifying_keys = [cls.from_public_point(pk.point, curve, hashfunc)
- for pk in pks]
- return verifying_keys
-
- def _raw_encode(self):
- """Convert the public key to the :term:`raw encoding`."""
- order = self.pubkey.order
- x_str = number_to_string(self.pubkey.point.x(), order)
- y_str = number_to_string(self.pubkey.point.y(), order)
- return x_str + y_str
-
- def _compressed_encode(self):
- """Encode the public point into the compressed form."""
- order = self.pubkey.order
- x_str = number_to_string(self.pubkey.point.x(), order)
- if self.pubkey.point.y() & 1:
- return b('\x03') + x_str
- else:
- return b('\x02') + x_str
-
- def _hybrid_encode(self):
- """Encode the public point into the hybrid form."""
- raw_enc = self._raw_encode()
- if self.pubkey.point.y() & 1:
- return b('\x07') + raw_enc
- else:
- return b('\x06') + raw_enc
-
- def to_string(self, encoding="raw"):
- """
- Convert the public key to a byte string.
-
- The method by default uses the :term:`raw encoding` (specified
- by `encoding="raw"`. It can also output keys in :term:`uncompressed`,
- :term:`compressed` and :term:`hybrid` formats.
-
- Remember that the curve identification is not part of the encoding
- so to decode the point using :func:`~VerifyingKey.from_string`, curve
- needs to be specified.
-
- Note: while the method is called "to_string", it's a misnomer from
- Python 2 days when character strings and byte strings shared type.
- On Python 3 the returned type will be `bytes`.
-
- :return: :term:`raw encoding` of the public key (public point) on the
- curve
- :rtype: bytes
- """
- assert encoding in ("raw", "uncompressed", "compressed", "hybrid")
- if encoding == "raw":
- return self._raw_encode()
- elif encoding == "uncompressed":
- return b('\x04') + self._raw_encode()
- elif encoding == "hybrid":
- return self._hybrid_encode()
- else:
- return self._compressed_encode()
-
- def to_pem(self, point_encoding="uncompressed"):
- """
- Convert the public key to the :term:`PEM` format.
-
- The PEM header of the key will be ``BEGIN PUBLIC KEY``.
-
- The format of the key is described in the
- :func:`~VerifyingKey.from_der()` method.
- This method supports only "named curve" encoding of keys.
-
- :param str point_encoding: specification of the encoding format
- of public keys. "uncompressed" is most portable, "compressed" is
- smallest. "hybrid" is uncommon and unsupported by most
- implementations, it is as big as "uncompressed".
-
- :return: portable encoding of the public key
- :rtype: str
- """
- return der.topem(self.to_der(point_encoding), "PUBLIC KEY")
-
- def to_der(self, point_encoding="uncompressed"):
- """
- Convert the public key to the :term:`DER` format.
-
- The format of the key is described in the
- :func:`~VerifyingKey.from_der()` method.
- This method supports only "named curve" encoding of keys.
-
- :param str point_encoding: specification of the encoding format
- of public keys. "uncompressed" is most portable, "compressed" is
- smallest. "hybrid" is uncommon and unsupported by most
- implementations, it is as big as "uncompressed".
-
- :return: DER encoding of the public key
- :rtype: bytes
- """
- if point_encoding == "raw":
- raise ValueError("raw point_encoding not allowed in DER")
- point_str = self.to_string(point_encoding)
- return der.encode_sequence(der.encode_sequence(encoded_oid_ecPublicKey,
- self.curve.encoded_oid),
- # 0 is the number of unused bits in the
- # bit string
- der.encode_bitstring(point_str, 0))
-
- def verify(self, signature, data, hashfunc=None,
- sigdecode=sigdecode_string):
- """
- Verify a signature made over provided data.
-
- Will hash `data` to verify the signature.
-
- By default expects signature in :term:`raw encoding`. Can also be used
- to verify signatures in ASN.1 DER encoding by using
- :func:`ecdsa.util.sigdecode_der`
- as the `sigdecode` parameter.
-
- :param signature: encoding of the signature
- :type signature: sigdecode method dependant
- :param data: data signed by the `signature`, will be hashed using
- `hashfunc`, if specified, or default hash function
- :type data: bytes like object
- :param hashfunc: The default hash function that will be used for
- verification, needs to implement the same interface as hashlib.sha1
- :type hashfunc: callable
- :param sigdecode: Callable to define the way the signature needs to
- be decoded to an object, needs to handle `signature` as the
- first parameter, the curve order (an int) as the second and return
- a tuple with two integers, "r" as the first one and "s" as the
- second one. See :func:`ecdsa.util.sigdecode_string` and
- :func:`ecdsa.util.sigdecode_der` for examples.
- :type sigdecode: callable
-
- :raises BadSignatureError: if the signature is invalid or malformed
-
- :return: True if the verification was successful
- :rtype: bool
- """
- # signature doesn't have to be a bytes-like-object so don't normalise
- # it, the decoders will do that
- data = normalise_bytes(data)
-
- hashfunc = hashfunc or self.default_hashfunc
- digest = hashfunc(data).digest()
- return self.verify_digest(signature, digest, sigdecode, True)
-
- def verify_digest(self, signature, digest, sigdecode=sigdecode_string,
- allow_truncate=False):
- """
- Verify a signature made over provided hash value.
-
- By default expects signature in :term:`raw encoding`. Can also be used
- to verify signatures in ASN.1 DER encoding by using
- :func:`ecdsa.util.sigdecode_der`
- as the `sigdecode` parameter.
-
- :param signature: encoding of the signature
- :type signature: sigdecode method dependant
- :param digest: raw hash value that the signature authenticates.
- :type digest: bytes like object
- :param sigdecode: Callable to define the way the signature needs to
- be decoded to an object, needs to handle `signature` as the
- first parameter, the curve order (an int) as the second and return
- a tuple with two integers, "r" as the first one and "s" as the
- second one. See :func:`ecdsa.util.sigdecode_string` and
- :func:`ecdsa.util.sigdecode_der` for examples.
- :type sigdecode: callable
- :param bool allow_truncate: if True, the provided digest can have
- bigger bit-size than the order of the curve, the extra bits (at
- the end of the digest) will be truncated. Use it when verifying
- SHA-384 output using NIST256p or in similar situations.
-
- :raises BadSignatureError: if the signature is invalid or malformed
- :raises BadDigestError: if the provided digest is too big for the curve
- associated with this VerifyingKey and allow_truncate was not set
-
- :return: True if the verification was successful
- :rtype: bool
- """
- # signature doesn't have to be a bytes-like-object so don't normalise
- # it, the decoders will do that
- digest = normalise_bytes(digest)
- if allow_truncate:
- digest = digest[:self.curve.baselen]
- if len(digest) > self.curve.baselen:
- raise BadDigestError("this curve (%s) is too short "
- "for your digest (%d)" % (self.curve.name,
- 8 * len(digest)))
- number = string_to_number(digest)
- try:
- r, s = sigdecode(signature, self.pubkey.order)
- except (der.UnexpectedDER, MalformedSignature) as e:
- raise BadSignatureError("Malformed formatting of signature", e)
- sig = ecdsa.Signature(r, s)
- if self.pubkey.verifies(number, sig):
- return True
- raise BadSignatureError("Signature verification failed")
-
-
-class SigningKey(object):
- """
- Class for handling keys that can create signatures (private keys).
-
- :ivar ecdsa.curves.Curve curve: The Curve over which all the cryptographic
- operations will take place
- :ivar default_hashfunc: the function that will be used for hashing the
- data. Should implement the same API as hashlib.sha1
- :ivar int baselen: the length of a :term:`raw encoding` of private key
- :ivar ecdsa.keys.VerifyingKey verifying_key: the public key
- associated with this private key
- :ivar ecdsa.ecdsa.Private_key privkey: the actual private key
- """
-
- def __init__(self, _error__please_use_generate=None):
- """Unsupported, please use one of the classmethods to initialise."""
- if not _error__please_use_generate:
- raise TypeError("Please use SigningKey.generate() to construct me")
- self.curve = None
- self.default_hashfunc = None
- self.baselen = None
- self.verifying_key = None
- self.privkey = None
-
- def __eq__(self, other):
- """Return True if the points are identical, False otherwise."""
- if isinstance(other, SigningKey):
- return self.curve == other.curve \
- and self.verifying_key == other.verifying_key \
- and self.privkey == other.privkey
- return NotImplemented
-
- @classmethod
- def generate(cls, curve=NIST192p, entropy=None, hashfunc=sha1):
- """
- Generate a random private key.
-
- :param curve: The curve on which the point needs to reside, defaults
- to NIST192p
- :type curve: ecdsa.curves.Curve
- :param entropy: Source of randomness for generating the private keys,
- should provide cryptographically secure random numbers if the keys
- need to be secure. Uses os.urandom() by default.
- :type entropy: callable
- :param hashfunc: The default hash function that will be used for
- signing, needs to implement the same interface
- as hashlib.sha1
- :type hashfunc: callable
-
- :return: Initialised SigningKey object
- :rtype: SigningKey
- """
- secexp = randrange(curve.order, entropy)
- return cls.from_secret_exponent(secexp, curve, hashfunc)
-
- @classmethod
- def from_secret_exponent(cls, secexp, curve=NIST192p, hashfunc=sha1):
- """
- Create a private key from a random integer.
-
- Note: it's a low level method, it's recommended to use the
- :func:`~SigningKey.generate` method to create private keys.
-
- :param int secexp: secret multiplier (the actual private key in ECDSA).
- Needs to be an integer between 1 and the curve order.
- :param curve: The curve on which the point needs to reside
- :type curve: ecdsa.curves.Curve
- :param hashfunc: The default hash function that will be used for
- signing, needs to implement the same interface
- as hashlib.sha1
- :type hashfunc: callable
-
- :raises MalformedPointError: when the provided secexp is too large
- or too small for the curve selected
- :raises RuntimeError: if the generation of public key from private
- key failed
-
- :return: Initialised SigningKey object
- :rtype: SigningKey
- """
- self = cls(_error__please_use_generate=True)
- self.curve = curve
- self.default_hashfunc = hashfunc
- self.baselen = curve.baselen
- n = curve.order
- if not 1 <= secexp < n:
- raise MalformedPointError(
- "Invalid value for secexp, expected integer between 1 and {0}"
- .format(n))
- pubkey_point = curve.generator * secexp
- if hasattr(pubkey_point, "scale"):
- pubkey_point = pubkey_point.scale()
- self.verifying_key = VerifyingKey.from_public_point(pubkey_point, curve,
- hashfunc, False)
- pubkey = self.verifying_key.pubkey
- self.privkey = ecdsa.Private_key(pubkey, secexp)
- self.privkey.order = n
- return self
-
- @classmethod
- def from_string(cls, string, curve=NIST192p, hashfunc=sha1):
- """
- Decode the private key from :term:`raw encoding`.
-
- Note: the name of this method is a misnomer coming from days of
- Python 2, when binary strings and character strings shared a type.
- In Python 3, the expected type is `bytes`.
-
- :param string: the raw encoding of the private key
- :type string: bytes like object
- :param curve: The curve on which the point needs to reside
- :type curve: ecdsa.curves.Curve
- :param hashfunc: The default hash function that will be used for
- signing, needs to implement the same interface
- as hashlib.sha1
- :type hashfunc: callable
-
- :raises MalformedPointError: if the length of encoding doesn't match
- the provided curve or the encoded values is too large
- :raises RuntimeError: if the generation of public key from private
- key failed
-
- :return: Initialised SigningKey object
- :rtype: SigningKey
- """
- string = normalise_bytes(string)
- if len(string) != curve.baselen:
- raise MalformedPointError(
- "Invalid length of private key, received {0}, expected {1}"
- .format(len(string), curve.baselen))
- secexp = string_to_number(string)
- return cls.from_secret_exponent(secexp, curve, hashfunc)
-
- @classmethod
- def from_pem(cls, string, hashfunc=sha1):
- """
- Initialise from key stored in :term:`PEM` format.
-
- Note, the only PEM format supported is the un-encrypted RFC5915
- (the sslay format) supported by OpenSSL, the more common PKCS#8 format
- is NOT supported (see:
- https://github.com/warner/python-ecdsa/issues/113 )
-
- ``openssl ec -in pkcs8.pem -out sslay.pem`` can be used to
- convert PKCS#8 file to this legacy format.
-
- The legacy format files have the header with the string
- ``BEGIN EC PRIVATE KEY``.
- Encrypted files (ones that include the string
- ``Proc-Type: 4,ENCRYPTED``
- right after the PEM header) are not supported.
-
- See :func:`~SigningKey.from_der` for ASN.1 syntax of the objects in
- this files.
-
- :param string: text with PEM-encoded private ECDSA key
- :type string: str
-
- :raises MalformedPointError: if the length of encoding doesn't match
- the provided curve or the encoded values is too large
- :raises RuntimeError: if the generation of public key from private
- key failed
- :raises UnexpectedDER: if the encoding of the PEM file is incorrect
-
- :return: Initialised VerifyingKey object
- :rtype: VerifyingKey
- """
- # the privkey pem may have multiple sections, commonly it also has
- # "EC PARAMETERS", we need just "EC PRIVATE KEY".
- if PY3 and isinstance(string, str):
- string = string.encode()
- privkey_pem = string[string.index(b("-----BEGIN EC PRIVATE KEY-----")):]
- return cls.from_der(der.unpem(privkey_pem), hashfunc)
-
- @classmethod
- def from_der(cls, string, hashfunc=sha1):
- """
- Initialise from key stored in :term:`DER` format.
-
- Note, the only DER format supported is the RFC5915
- (the sslay format) supported by OpenSSL, the more common PKCS#8 format
- is NOT supported (see:
- https://github.com/warner/python-ecdsa/issues/113 )
-
- ``openssl ec -in pkcs8.pem -outform der -out sslay.der`` can be
- used to convert PKCS#8 file to this legacy format.
-
- The encoding of the ASN.1 object in those files follows following
- syntax specified in RFC5915::
-
- ECPrivateKey ::= SEQUENCE {
- version INTEGER { ecPrivkeyVer1(1) }} (ecPrivkeyVer1),
- privateKey OCTET STRING,
- parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
- publicKey [1] BIT STRING OPTIONAL
- }
-
- The only format supported for the `parameters` field is the named
- curve method. Explicit encoding of curve parameters is not supported.
-
- While `parameters` field is defined as optional, this implementation
- requires its presence for correct parsing of the keys.
-
- `publicKey` field is ignored completely (errors, if any, in it will
- be undetected).
-
- :param string: binary string with DER-encoded private ECDSA key
- :type string: bytes like object
-
- :raises MalformedPointError: if the length of encoding doesn't match
- the provided curve or the encoded values is too large
- :raises RuntimeError: if the generation of public key from private
- key failed
- :raises UnexpectedDER: if the encoding of the DER file is incorrect
-
- :return: Initialised VerifyingKey object
- :rtype: VerifyingKey
- """