Diffie-Hellman Key Exchange Scheme

This module contains a toy implementation of the Diffie-Hellman key exchange scheme.

AUTHORS:

  • Vincent Macri (2024-07-30): initial version

class sage.crypto.key_exchange.diffie_hellman.DiffieHellman(p: Integer, g: Integer | IntegerMod_abstract, proof: bool = True)[source]

Bases: KeyExchangeScheme

Create an instance of the Diffie-Hellman key exchange scheme using the given prime p and base g.

INPUT:

  • p – prime integer defining the field \(\GF{p}\) that the key exchanges will be performed over, must be at least 5

  • g – base for the key exchange, (coerceable to) an element of \(\GF{p}\) from \(2\) to \(p - 2\)

  • proof – (default: True) whether to require a proof that p is prime. If False, a probabilistic test can be used for checking that p is prime. This should be set to False when using large (cryptographic size) primes, otherwise checking primality will take too long.

Warning

This is a toy implementation for educational use only! Do not use this implementation, or any cryptographic features of Sage, in any setting where security is needed!

REFERENCES:

For more information, see Section 8.1 of [PP2010].

EXAMPLES:

sage: DH = key_exchange.DiffieHellman(13, 2)
doctest:...: FutureWarning: This class/method/function is marked as experimental. It, its functionality or its interface might change without a formal deprecation.
See https://github.com/sagemath/sage/issues/37305 for details.
>>> from sage.all import *
>>> DH = key_exchange.DiffieHellman(Integer(13), Integer(2))
doctest:...: FutureWarning: This class/method/function is marked as experimental. It, its functionality or its interface might change without a formal deprecation.
See https://github.com/sagemath/sage/issues/37305 for details.

This is an example of a full key exchange using a cryptographically large prime. This is the prime from the 8192-bit MODP group in RFC 3526 (see [KK2003]):

sage: p = 2^8192 - 2^8128 - 1 + 2^64 * (round(2^8062 * pi) + 4743158)
sage: DH = key_exchange.DiffieHellman(p, 2, proof=False)
sage: alice_sk = DH.generate_secret_key()
sage: alice_pk = DH.generate_public_key(alice_sk)
sage: bob_sk = DH.generate_secret_key()
sage: bob_pk = DH.generate_public_key(bob_sk)
sage: alice_shared_secret = DH.compute_shared_secret(bob_pk, alice_sk)
sage: bob_shared_secret = DH.compute_shared_secret(alice_pk, bob_sk)
sage: alice_shared_secret == bob_shared_secret
True
>>> from sage.all import *
>>> p = Integer(2)**Integer(8192) - Integer(2)**Integer(8128) - Integer(1) + Integer(2)**Integer(64) * (round(Integer(2)**Integer(8062) * pi) + Integer(4743158))
>>> DH = key_exchange.DiffieHellman(p, Integer(2), proof=False)
>>> alice_sk = DH.generate_secret_key()
>>> alice_pk = DH.generate_public_key(alice_sk)
>>> bob_sk = DH.generate_secret_key()
>>> bob_pk = DH.generate_public_key(bob_sk)
>>> alice_shared_secret = DH.compute_shared_secret(bob_pk, alice_sk)
>>> bob_shared_secret = DH.compute_shared_secret(alice_pk, bob_sk)
>>> alice_shared_secret == bob_shared_secret
True
compute_shared_secret(pk, sk)[source]

Compute the shared secret using the given public key and secret keys.

INPUT:

  • pk – public key

  • sk – secret key

EXAMPLES:

sage: DH = key_exchange.DiffieHellman(17, 3)
sage: DH.compute_shared_secret(13, 11)
4
>>> from sage.all import *
>>> DH = key_exchange.DiffieHellman(Integer(17), Integer(3))
>>> DH.compute_shared_secret(Integer(13), Integer(11))
4
field()[source]

Return the field this DiffieHellman instance is working over.

EXAMPLES:

sage: DH = key_exchange.DiffieHellman(5, 2)
sage: DH.field()
Finite Field of size 5
>>> from sage.all import *
>>> DH = key_exchange.DiffieHellman(Integer(5), Integer(2))
>>> DH.field()
Finite Field of size 5
generate_public_key(secret_key)[source]

Generate a Diffie-Hellman public key using the given secret key.

INPUT:

  • secret_key – the secret key to generate the public key with

EXAMPLES:

sage: DH = key_exchange.DiffieHellman(13, 2)
sage: DH.generate_public_key(4)
3
>>> from sage.all import *
>>> DH = key_exchange.DiffieHellman(Integer(13), Integer(2))
>>> DH.generate_public_key(Integer(4))
3
generate_secret_key()[source]

Generate a random Diffie-Hellman secret key.

generator()[source]

Return the generator g for this DiffieHellman instance.

EXAMPLES:

sage: DH = key_exchange.DiffieHellman(7, 3)
sage: DH.generator()
3
>>> from sage.all import *
>>> DH = key_exchange.DiffieHellman(Integer(7), Integer(3))
>>> DH.generator()
3
parameters()[source]

Get the parameters (p, g) for this DiffieHellman instance.

EXAMPLES:

sage: DH = key_exchange.DiffieHellman(7, 3)
sage: DH.parameters()
(7, 3)
>>> from sage.all import *
>>> DH = key_exchange.DiffieHellman(Integer(7), Integer(3))
>>> DH.parameters()
(7, 3)
prime()[source]

Return the prime p for this DiffieHellman instance.

EXAMPLES:

sage: DH = key_exchange.DiffieHellman(7, 3)
sage: DH.prime()
7
>>> from sage.all import *
>>> DH = key_exchange.DiffieHellman(Integer(7), Integer(3))
>>> DH.prime()
7
subgroup_size()[source]

Calculates the size of the subgroup of \(\GF{p}\) generated by self.generator().

EXAMPLES:

This is an example of a DiffieHellman instance where the subgroup size is \((p - 1) / 2\):

sage: DH = key_exchange.DiffieHellman(47, 2)
sage: DH.subgroup_size()
23
>>> from sage.all import *
>>> DH = key_exchange.DiffieHellman(Integer(47), Integer(2))
>>> DH.subgroup_size()
23

This is an example of a DiffieHellman instance where the subgroup size is \(p - 1\):

sage: DH = key_exchange.DiffieHellman(47, 5)
sage: DH.subgroup_size()
46
>>> from sage.all import *
>>> DH = key_exchange.DiffieHellman(Integer(47), Integer(5))
>>> DH.subgroup_size()
46