mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Initial commit
This commit is contained in:
336
venv/Lib/site-packages/ecdsa/ecdh.py
Normal file
336
venv/Lib/site-packages/ecdsa/ecdh.py
Normal file
@@ -0,0 +1,336 @@
|
||||
"""
|
||||
Class for performing Elliptic-curve Diffie-Hellman (ECDH) operations.
|
||||
"""
|
||||
|
||||
from .util import number_to_string
|
||||
from .ellipticcurve import INFINITY
|
||||
from .keys import SigningKey, VerifyingKey
|
||||
|
||||
|
||||
__all__ = [
|
||||
"ECDH",
|
||||
"NoKeyError",
|
||||
"NoCurveError",
|
||||
"InvalidCurveError",
|
||||
"InvalidSharedSecretError",
|
||||
]
|
||||
|
||||
|
||||
class NoKeyError(Exception):
|
||||
"""ECDH. Key not found but it is needed for operation."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class NoCurveError(Exception):
|
||||
"""ECDH. Curve not set but it is needed for operation."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class InvalidCurveError(Exception):
|
||||
"""
|
||||
ECDH. Raised in case the public and private keys use different curves.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class InvalidSharedSecretError(Exception):
|
||||
"""ECDH. Raised in case the shared secret we obtained is an INFINITY."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ECDH(object):
|
||||
"""
|
||||
Elliptic-curve Diffie-Hellman (ECDH). A key agreement protocol.
|
||||
|
||||
Allows two parties, each having an elliptic-curve public-private key
|
||||
pair, to establish a shared secret over an insecure channel
|
||||
"""
|
||||
|
||||
def __init__(self, curve=None, private_key=None, public_key=None):
|
||||
"""
|
||||
ECDH init.
|
||||
|
||||
Call can be initialised without parameters, then the first operation
|
||||
(loading either key) will set the used curve.
|
||||
All parameters must be ultimately set before shared secret
|
||||
calculation will be allowed.
|
||||
|
||||
:param curve: curve for operations
|
||||
:type curve: Curve
|
||||
:param private_key: `my` private key for ECDH
|
||||
:type private_key: SigningKey
|
||||
:param public_key: `their` public key for ECDH
|
||||
:type public_key: VerifyingKey
|
||||
"""
|
||||
self.curve = curve
|
||||
self.private_key = None
|
||||
self.public_key = None
|
||||
if private_key:
|
||||
self.load_private_key(private_key)
|
||||
if public_key:
|
||||
self.load_received_public_key(public_key)
|
||||
|
||||
def _get_shared_secret(self, remote_public_key):
|
||||
if not self.private_key:
|
||||
raise NoKeyError(
|
||||
"Private key needs to be set to create shared secret"
|
||||
)
|
||||
if not self.public_key:
|
||||
raise NoKeyError(
|
||||
"Public key needs to be set to create shared secret"
|
||||
)
|
||||
if not (
|
||||
self.private_key.curve == self.curve == remote_public_key.curve
|
||||
):
|
||||
raise InvalidCurveError(
|
||||
"Curves for public key and private key is not equal."
|
||||
)
|
||||
|
||||
# shared secret = PUBKEYtheirs * PRIVATEKEYours
|
||||
result = (
|
||||
remote_public_key.pubkey.point
|
||||
* self.private_key.privkey.secret_multiplier
|
||||
)
|
||||
if result == INFINITY:
|
||||
raise InvalidSharedSecretError("Invalid shared secret (INFINITY).")
|
||||
|
||||
return result.x()
|
||||
|
||||
def set_curve(self, key_curve):
|
||||
"""
|
||||
Set the working curve for ecdh operations.
|
||||
|
||||
:param key_curve: curve from `curves` module
|
||||
:type key_curve: Curve
|
||||
"""
|
||||
self.curve = key_curve
|
||||
|
||||
def generate_private_key(self):
|
||||
"""
|
||||
Generate local private key for ecdh operation with curve that was set.
|
||||
|
||||
:raises NoCurveError: Curve must be set before key generation.
|
||||
|
||||
:return: public (verifying) key from this private key.
|
||||
:rtype: VerifyingKey
|
||||
"""
|
||||
if not self.curve:
|
||||
raise NoCurveError("Curve must be set prior to key generation.")
|
||||
return self.load_private_key(SigningKey.generate(curve=self.curve))
|
||||
|
||||
def load_private_key(self, private_key):
|
||||
"""
|
||||
Load private key from SigningKey (keys.py) object.
|
||||
|
||||
Needs to have the same curve as was set with set_curve method.
|
||||
If curve is not set - it sets from this SigningKey
|
||||
|
||||
:param private_key: Initialised SigningKey class
|
||||
:type private_key: SigningKey
|
||||
|
||||
:raises InvalidCurveError: private_key curve not the same as self.curve
|
||||
|
||||
:return: public (verifying) key from this private key.
|
||||
:rtype: VerifyingKey
|
||||
"""
|
||||
if not self.curve:
|
||||
self.curve = private_key.curve
|
||||
if self.curve != private_key.curve:
|
||||
raise InvalidCurveError("Curve mismatch.")
|
||||
self.private_key = private_key
|
||||
return self.private_key.get_verifying_key()
|
||||
|
||||
def load_private_key_bytes(self, private_key):
|
||||
"""
|
||||
Load private key from byte string.
|
||||
|
||||
Uses current curve and checks if the provided key matches
|
||||
the curve of ECDH key agreement.
|
||||
Key loads via from_string method of SigningKey class
|
||||
|
||||
:param private_key: private key in bytes string format
|
||||
:type private_key: :term:`bytes-like object`
|
||||
|
||||
:raises NoCurveError: Curve must be set before loading.
|
||||
|
||||
:return: public (verifying) key from this private key.
|
||||
:rtype: VerifyingKey
|
||||
"""
|
||||
if not self.curve:
|
||||
raise NoCurveError("Curve must be set prior to key load.")
|
||||
return self.load_private_key(
|
||||
SigningKey.from_string(private_key, curve=self.curve)
|
||||
)
|
||||
|
||||
def load_private_key_der(self, private_key_der):
|
||||
"""
|
||||
Load private key from DER byte string.
|
||||
|
||||
Compares the curve of the DER-encoded key with the ECDH set curve,
|
||||
uses the former if unset.
|
||||
|
||||
Note, the only DER format supported is the RFC5915
|
||||
Look at keys.py:SigningKey.from_der()
|
||||
|
||||
:param private_key_der: string with the DER encoding of private ECDSA
|
||||
key
|
||||
:type private_key_der: string
|
||||
|
||||
:raises InvalidCurveError: private_key curve not the same as self.curve
|
||||
|
||||
:return: public (verifying) key from this private key.
|
||||
:rtype: VerifyingKey
|
||||
"""
|
||||
return self.load_private_key(SigningKey.from_der(private_key_der))
|
||||
|
||||
def load_private_key_pem(self, private_key_pem):
|
||||
"""
|
||||
Load private key from PEM string.
|
||||
|
||||
Compares the curve of the DER-encoded key with the ECDH set curve,
|
||||
uses the former if unset.
|
||||
|
||||
Note, the only PEM format supported is the RFC5915
|
||||
Look at keys.py:SigningKey.from_pem()
|
||||
it needs to have `EC PRIVATE KEY` section
|
||||
|
||||
:param private_key_pem: string with PEM-encoded private ECDSA key
|
||||
:type private_key_pem: string
|
||||
|
||||
:raises InvalidCurveError: private_key curve not the same as self.curve
|
||||
|
||||
:return: public (verifying) key from this private key.
|
||||
:rtype: VerifyingKey
|
||||
"""
|
||||
return self.load_private_key(SigningKey.from_pem(private_key_pem))
|
||||
|
||||
def get_public_key(self):
|
||||
"""
|
||||
Provides a public key that matches the local private key.
|
||||
|
||||
Needs to be sent to the remote party.
|
||||
|
||||
:return: public (verifying) key from local private key.
|
||||
:rtype: VerifyingKey
|
||||
"""
|
||||
return self.private_key.get_verifying_key()
|
||||
|
||||
def load_received_public_key(self, public_key):
|
||||
"""
|
||||
Load public key from VerifyingKey (keys.py) object.
|
||||
|
||||
Needs to have the same curve as set as current for ecdh operation.
|
||||
If curve is not set - it sets it from VerifyingKey.
|
||||
|
||||
:param public_key: Initialised VerifyingKey class
|
||||
:type public_key: VerifyingKey
|
||||
|
||||
:raises InvalidCurveError: public_key curve not the same as self.curve
|
||||
"""
|
||||
if not self.curve:
|
||||
self.curve = public_key.curve
|
||||
if self.curve != public_key.curve:
|
||||
raise InvalidCurveError("Curve mismatch.")
|
||||
self.public_key = public_key
|
||||
|
||||
def load_received_public_key_bytes(
|
||||
self, public_key_str, valid_encodings=None
|
||||
):
|
||||
"""
|
||||
Load public key from byte string.
|
||||
|
||||
Uses current curve and checks if key length corresponds to
|
||||
the current curve.
|
||||
Key loads via from_string method of VerifyingKey class
|
||||
|
||||
:param public_key_str: public key in bytes string format
|
||||
:type public_key_str: :term:`bytes-like object`
|
||||
:param valid_encodings: list of acceptable point encoding formats,
|
||||
supported ones are: :term:`uncompressed`, :term:`compressed`,
|
||||
:term:`hybrid`, and :term:`raw encoding` (specified with ``raw``
|
||||
name). All formats by default (specified with ``None``).
|
||||
:type valid_encodings: :term:`set-like object`
|
||||
"""
|
||||
return self.load_received_public_key(
|
||||
VerifyingKey.from_string(
|
||||
public_key_str, self.curve, valid_encodings
|
||||
)
|
||||
)
|
||||
|
||||
def load_received_public_key_der(self, public_key_der):
|
||||
"""
|
||||
Load public key from DER byte string.
|
||||
|
||||
Compares the curve of the DER-encoded key with the ECDH set curve,
|
||||
uses the former if unset.
|
||||
|
||||
Note, the only DER format supported is the RFC5912
|
||||
Look at keys.py:VerifyingKey.from_der()
|
||||
|
||||
:param public_key_der: string with the DER encoding of public ECDSA key
|
||||
:type public_key_der: string
|
||||
|
||||
:raises InvalidCurveError: public_key curve not the same as self.curve
|
||||
"""
|
||||
return self.load_received_public_key(
|
||||
VerifyingKey.from_der(public_key_der)
|
||||
)
|
||||
|
||||
def load_received_public_key_pem(self, public_key_pem):
|
||||
"""
|
||||
Load public key from PEM string.
|
||||
|
||||
Compares the curve of the PEM-encoded key with the ECDH set curve,
|
||||
uses the former if unset.
|
||||
|
||||
Note, the only PEM format supported is the RFC5912
|
||||
Look at keys.py:VerifyingKey.from_pem()
|
||||
|
||||
:param public_key_pem: string with PEM-encoded public ECDSA key
|
||||
:type public_key_pem: string
|
||||
|
||||
:raises InvalidCurveError: public_key curve not the same as self.curve
|
||||
"""
|
||||
return self.load_received_public_key(
|
||||
VerifyingKey.from_pem(public_key_pem)
|
||||
)
|
||||
|
||||
def generate_sharedsecret_bytes(self):
|
||||
"""
|
||||
Generate shared secret from local private key and remote public key.
|
||||
|
||||
The objects needs to have both private key and received public key
|
||||
before generation is allowed.
|
||||
|
||||
:raises InvalidCurveError: public_key curve not the same as self.curve
|
||||
:raises NoKeyError: public_key or private_key is not set
|
||||
|
||||
:return: shared secret
|
||||
:rtype: bytes
|
||||
"""
|
||||
return number_to_string(
|
||||
self.generate_sharedsecret(), self.private_key.curve.curve.p()
|
||||
)
|
||||
|
||||
def generate_sharedsecret(self):
|
||||
"""
|
||||
Generate shared secret from local private key and remote public key.
|
||||
|
||||
The objects needs to have both private key and received public key
|
||||
before generation is allowed.
|
||||
|
||||
It's the same for local and remote party,
|
||||
shared secret(local private key, remote public key) ==
|
||||
shared secret(local public key, remote private key)
|
||||
|
||||
:raises InvalidCurveError: public_key curve not the same as self.curve
|
||||
:raises NoKeyError: public_key or private_key is not set
|
||||
|
||||
:return: shared secret
|
||||
:rtype: int
|
||||
"""
|
||||
return self._get_shared_secret(self.public_key)
|
Reference in New Issue
Block a user