aboutsummaryrefslogtreecommitdiff
path: root/pyecsca/ec/key_agreement.py
blob: 018b177751768e3c1163570ed2059014b6366090 (plain)
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
import hashlib
from typing import Optional, Any

from public import public

from .mult import ScalarMultiplier
from .point import Point


@public
class KeyAgreement(object):
    """An EC based key agreement primitive. (ECDH)"""
    mult: ScalarMultiplier
    pubkey: Point
    privkey: int
    hash_algo: Optional[Any]

    def __init__(self, mult: ScalarMultiplier, pubkey: Point, privkey: int,
                 hash_algo: Optional[Any] = None):
        self.mult = mult
        self.pubkey = pubkey
        self.privkey = privkey
        self.hash_algo = hash_algo

    def perform_raw(self) -> Point:
        """
        Perform the scalar-multiplication of the key agreement.

        :return: The shared point.
        """
        point = self.mult.multiply(self.privkey, self.pubkey)
        return point.to_affine()  # TODO: This conversion should be somehow added to the context

    def perform(self) -> bytes:
        """
        Perform the key agreement operation.

        :return: The shared secret.
        """
        affine_point = self.perform_raw()
        x = int(affine_point.x)
        p = self.mult.group.curve.prime
        n = (p.bit_length() + 7) // 8
        result = x.to_bytes(n, byteorder="big")
        if self.hash_algo is not None:
            result = self.hash_algo(result).digest()
        return result


@public
class ECDH_NONE(KeyAgreement):
    """Raw x-coordinate ECDH."""

    def __init__(self, mult: ScalarMultiplier, pubkey: Point, privkey: int):
        super().__init__(mult, pubkey, privkey)


@public
class ECDH_SHA1(KeyAgreement):
    """ECDH with SHA1 of x-coordinate."""

    def __init__(self, mult: ScalarMultiplier, pubkey: Point, privkey: int):
        super().__init__(mult, pubkey, privkey, hashlib.sha1)


@public
class ECDH_SHA224(KeyAgreement):
    """ECDH with SHA224 of x-coordinate."""

    def __init__(self, mult: ScalarMultiplier, pubkey: Point, privkey: int):
        super().__init__(mult, pubkey, privkey, hashlib.sha224)


@public
class ECDH_SHA256(KeyAgreement):
    """ECDH with SHA256 of x-coordinate."""

    def __init__(self, mult: ScalarMultiplier, pubkey: Point, privkey: int):
        super().__init__(mult, pubkey, privkey, hashlib.sha256)


@public
class ECDH_SHA384(KeyAgreement):
    """ECDH with SHA384 of x-coordinate."""

    def __init__(self, mult: ScalarMultiplier, pubkey: Point, privkey: int):
        super().__init__(mult, pubkey, privkey, hashlib.sha384)


@public
class ECDH_SHA512(KeyAgreement):
    """ECDH with SHA512 of x-coordinate."""

    def __init__(self, mult: ScalarMultiplier, pubkey: Point, privkey: int):
        super().__init__(mult, pubkey, privkey, hashlib.sha512)