blob: 67ed280929ed02978d56db24ce9d8f206460f5e1 (
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
96
97
98
99
100
101
102
103
104
|
.. hazmat::
X25519 key exchange
===================
.. currentmodule:: cryptography.hazmat.primitives.asymmetric.x25519
X25519 is an elliptic curve `Diffie-Hellman key exchange`_ using `Curve25519`_.
It allows two parties to jointly agree on a shared secret using an insecure
channel.
Exchange Algorithm
~~~~~~~~~~~~~~~~~~
For most applications the ``shared_key`` should be passed to a key
derivation function. This allows mixing of additional information into the
key, derivation of multiple keys, and destroys any structure that may be
present.
.. doctest::
>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
>>> # Generate a private key for use in the exchange.
>>> private_key = X25519PrivateKey.generate()
>>> # In a real handshake the peer_public_key will be received from the
>>> # other party. For this example we'll generate another private key and
>>> # get a public key from that. Note that in a DH handshake both peers
>>> # must agree on a common set of parameters.
>>> peer_public_key = X25519PrivateKey.generate().public_key()
>>> shared_key = private_key.exchange(peer_public_key)
>>> # Perform key derivation.
>>> derived_key = HKDF(
... algorithm=hashes.SHA256(),
... length=32,
... salt=None,
... info=b'handshake data',
... backend=default_backend()
... ).derive(shared_key)
>>> # For the next handshake we MUST generate another private key.
>>> private_key_2 = X25519PrivateKey.generate()
>>> peer_public_key_2 = X25519PrivateKey.generate().public_key()
>>> shared_key_2 = private_key_2.exchange(peer_public_key_2)
>>> derived_key_2 = HKDF(
... algorithm=hashes.SHA256(),
... length=32,
... salt=None,
... info=b'handshake data',
... backend=default_backend()
... ).derive(shared_key_2)
Key interfaces
~~~~~~~~~~~~~~
.. class:: X25519PrivateKey
.. versionadded:: 2.0
.. classmethod:: generate()
Generate an X25519 private key.
:returns: :class:`X25519PrivateKey`
.. method:: public_key()
:returns: :class:`X25519PublicKey`
.. method:: exchange(peer_public_key)
:param X25519PublicKey peer_public_key: The public key for the
peer.
:returns bytes: A shared key.
.. class:: X25519PublicKey
.. versionadded:: 2.0
.. classmethod:: from_public_bytes(data)
:param bytes data: 32 byte public key.
:returns: :class:`X25519PublicKey`
.. doctest::
>>> from cryptography.hazmat.primitives.asymmetric import x25519
>>> private_key = x25519.X25519PrivateKey.generate()
>>> public_key = private_key.public_key()
>>> public_bytes = public_key.public_bytes()
>>> loaded_public_key = x25519.X25519PublicKey.from_public_bytes(public_bytes)
.. method:: public_bytes()
:returns bytes: The raw bytes of the public key.
.. _`Diffie-Hellman key exchange`: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
.. _`Curve25519`: https://en.wikipedia.org/wiki/Curve25519
|