From 62787b2ad11f78b0baa9b6ffe0c7db528102b607 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Mon, 15 Jul 2024 17:10:34 -0600 Subject: [PATCH 01/29] Initial work on public key exchange in Sage --- src/doc/en/reference/cryptography/index.rst | 2 + src/doc/en/reference/references/index.rst | 9 +- src/sage/crypto/key_exchange/all.py | 4 + .../crypto/key_exchange/diffie_hellman.py | 214 ++++++++++++++++++ src/sage/crypto/key_exchange/pke.py | 41 ++++ 5 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 src/sage/crypto/key_exchange/all.py create mode 100644 src/sage/crypto/key_exchange/diffie_hellman.py create mode 100644 src/sage/crypto/key_exchange/pke.py diff --git a/src/doc/en/reference/cryptography/index.rst b/src/doc/en/reference/cryptography/index.rst index 3c7997247be..7f58b50ee5f 100644 --- a/src/doc/en/reference/cryptography/index.rst +++ b/src/doc/en/reference/cryptography/index.rst @@ -34,4 +34,6 @@ Cryptography sage/crypto/lattice sage/crypto/lwe + sage/crypto/key_exchange/diffie_hellman + .. include:: ../footer.txt diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index b7725c7848b..1a9cf5d5186 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -9,9 +9,7 @@ REFERENCES: :ref:`E ` :ref:`F ` :ref:`G ` -:ref:`H ` -:ref:`I ` -:ref:`J ` +:ref:`H ` :ref:`I ` :ref:`J ` :ref:`K ` :ref:`L ` :ref:`M ` @@ -5343,6 +5341,11 @@ REFERENCES: Mathematical Physics, Analysis and Geometry 1, 171-191 (1998). :doi:`10.1023/A:1009724323513` +.. [PP2010] \C. Paar and J. Pelzl. + *Understanding Cryptography*. + Springer Berlin, Heidelberg, 2010. + :doi:`10.1007/978-3-642-04101-3` + .. [PPW2013] \D. Perkinson, J. Perlman, and J. Wilmes. *Primer for the algebraic geometry of sandpiles*. Tropical and Non-Archimedean diff --git a/src/sage/crypto/key_exchange/all.py b/src/sage/crypto/key_exchange/all.py new file mode 100644 index 00000000000..d961ec5ed13 --- /dev/null +++ b/src/sage/crypto/key_exchange/all.py @@ -0,0 +1,4 @@ +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.crypto.key_exchange.diffie_hellman', 'DiffieHellman') +del lazy_import diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py new file mode 100644 index 00000000000..08e00288a24 --- /dev/null +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -0,0 +1,214 @@ +r""" +Diffie-Hellman Public Key Exchange Scheme + +This module contains a toy implementation of the Diffie-Hellman public key exchange +scheme. + +AUTHORS: + +- Vincent Macri (2024-07-15): initial version +""" +# **************************************************************************** +# Copyright (C) 2024 Vincent Macri +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.misc.superseded import experimental + +from sage.crypto.key_exchange.pke import KeyExchangeScheme + +from sage.arith.misc import is_prime +from sage.misc.prandom import randint +from sage.rings.integer import Integer +from sage.rings.finite_rings.finite_field_constructor import GF +from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn_with_category +from sage.rings.finite_rings.integer_mod import IntegerMod_int +from sage.structure.sage_object import SageObject + +from typing import Union + +class DiffieHellman(KeyExchangeScheme): + + @experimental(37305) + def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): + """ + Create an instance of the Diffie-Hellman key exchange scheme using the + given prime ``p`` and base ``g``. + + INPUT: + + - ``p`` -- prime integer that the key exchanges will be performed over `\\GF{p}` + + - ``g`` -- base for the key exchange, (coerceable to) an element of `\\GF{p}` from `2` to `p - 2` + + .. 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 [PP2010]_, section 8.1. + + EXAMPLES:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = 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. + """ + # The modn implementation takes care of checking that ``p`` is prime + self._field = GF(p, impl='modn') + + self._p = p + self._g = self._field(g) + + # While these values won't cause mathematical problems, they do completely + # break the security of the Diffie-Hellman scheme. + # g = 0 makes every secret key and shared secret 0 + # g = 1 makes every secret key and shared secret 1 + # g = -1 makes every secret key and shared secret 1 or -1 + if self._g == 0 or self._g == 1 or self._g == p - 1: + raise ValueError('g cannot be 0, 1, or p - 1 (mod p)') + + def field(self) -> FiniteField_prime_modn_with_category: + """ + Return the field this Diffie-Hellman instance is working over. + + EXAMPLES:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(5, 2) + sage: DH.field() + Finite Field of size 5 + """ + return self._field + + def prime(self) -> Integer: + """ + Return the prime ``p`` for this Diffie-Hellman instance. + + EXAMPLES:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(7, 3) + sage: DH.prime() + 7 + """ + return self._p + + def generator(self) -> IntegerMod_int: + """ + Return the generator ``g`` for this Diffie-Hellman instance. + + EXAMPLES:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(7, 3) + sage: DH.generator() + 3 + """ + return self._g + + def parameters(self) -> tuple[Integer, IntegerMod_int]: + """ + Output the parameters ``(p, g)`` for this Diffie-Hellman instance. + + EXAMPLES:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(7, 3) + sage: DH.parameters() + (7, 3) + """ + return (self._p, self._g) + + def generate_secret_key(self) -> Integer: + """ + Generate a random Diffie-Hellman secret key. + + TESTS: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(7, 2) + sage: keys = [DH.generate_secret_key() for i in range(10)] + sage: all(2 <= i <= 5 for i in keys) + True + """ + return randint(2, self._p - 2) + + def generate_public_key(self, secret_key: Integer) -> IntegerMod_int: + """ + 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: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(13, 2) + sage: DH.generate_public_key(4) + 3 + """ + return self._g**secret_key + + def compute_shared_secret(self, alice_pk: IntegerMod_int, bob_sk: Integer) -> IntegerMod_int: + """ + Compute Alice and Bob's shared secret using Alice's public key and + Bob's secret key. + + INPUT: + + - ``alice_pk`` -- Alice's public key + + - ``bob_sk`` -- Bob's secret key + + EXAMPLES:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(17, 3) + sage: DH.compute_shared_secret(13, 11) + 4 + """ + return self._field(alice_pk**bob_sk) + + def subgroup_size(self) -> Integer: + """ + Calculates the size of the subgroup of `\\GF{p}` generated by ``self.generator()``. + + EXAMPLES: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(47, 2) + sage: DH.subgroup_size() + 23 + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(47, 5) + sage: DH.subgroup_size() + 46 + """ + return self._g.multiplicative_order() + + def __len__(self): + return int(self.subgroup_size()) + + def __eq__(self, other): + return self._p == other._p and self._g == other._g + + def __hash__(self): + return hash((self._p, other._g)) + + def _repr_(self): + return f'Diffie-Hellman key exchange over {self._field} with generator {self._g}' + + def _latex_(self): + return f'\\text{{Diffie-Hellman key exchange over }}{self._field}\\text{{ with generator }}{self._g}' diff --git a/src/sage/crypto/key_exchange/pke.py b/src/sage/crypto/key_exchange/pke.py new file mode 100644 index 00000000000..2c18f791c48 --- /dev/null +++ b/src/sage/crypto/key_exchange/pke.py @@ -0,0 +1,41 @@ +r""" +Public key exchange schemes. + +This module contains base classes for public key exchange schemes. The classes defined in +this module should not be called directly. It is the responsibility of child classes to +implement specific cryptosystems. + + +AUTHORS: + +- Vincent Macri (2024-07-12): initial version +""" +# **************************************************************************** +# Copyright (C) 2024 Vincent Macri +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.misc.superseded import experimental + +class KeyExchangeScheme: + + @experimental(37305) + def __init__(self): + pass + + def generate_secret_key(self): + raise NotImplementedError + + def generate_public_key(self, secret_key): + raise NotImplementedError + + def compute_shared_secret(self, alice_pk, bob_sk): + raise NotImplementedError + + def parameters(self): + raise NotImplementedError From 0b2d8abcb805fb7df8710499eed848b968a07ff9 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Mon, 15 Jul 2024 17:16:44 -0600 Subject: [PATCH 02/29] Fix formatting error in references --- src/doc/en/reference/references/index.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 1a9cf5d5186..5daed6ce180 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -9,7 +9,9 @@ REFERENCES: :ref:`E ` :ref:`F ` :ref:`G ` -:ref:`H ` :ref:`I ` :ref:`J ` +:ref:`H ` +:ref:`I ` +:ref:`J ` :ref:`K ` :ref:`L ` :ref:`M ` From 265571202fb1523b2cc860bae277fde7a5e278df Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Mon, 15 Jul 2024 17:25:17 -0600 Subject: [PATCH 03/29] Style and doc date --- src/sage/crypto/key_exchange/diffie_hellman.py | 4 ++-- src/sage/crypto/key_exchange/pke.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 08e00288a24..892543663a8 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -55,7 +55,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): REFERENCES: For more information, see [PP2010]_, section 8.1. - + EXAMPLES:: sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman @@ -68,7 +68,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): self._p = p self._g = self._field(g) - + # While these values won't cause mathematical problems, they do completely # break the security of the Diffie-Hellman scheme. # g = 0 makes every secret key and shared secret 0 diff --git a/src/sage/crypto/key_exchange/pke.py b/src/sage/crypto/key_exchange/pke.py index 2c18f791c48..93fc6bf8edc 100644 --- a/src/sage/crypto/key_exchange/pke.py +++ b/src/sage/crypto/key_exchange/pke.py @@ -8,7 +8,7 @@ AUTHORS: -- Vincent Macri (2024-07-12): initial version +- Vincent Macri (2024-07-15): initial version """ # **************************************************************************** # Copyright (C) 2024 Vincent Macri From 73bffc6ecd24a8edad2241a48e62e5aa25849bef Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 16 Jul 2024 11:01:54 -0600 Subject: [PATCH 04/29] Fix annotations and add missing check --- src/sage/crypto/key_exchange/diffie_hellman.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 892543663a8..d72f88f3a44 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -26,7 +26,7 @@ from sage.misc.prandom import randint from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_constructor import GF -from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn_with_category +from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn from sage.rings.finite_rings.integer_mod import IntegerMod_int from sage.structure.sage_object import SageObject @@ -42,7 +42,8 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): INPUT: - - ``p`` -- prime integer that the key exchanges will be performed over `\\GF{p}` + - ``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` @@ -63,6 +64,10 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): 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. """ + + if p < 5: + raise ValueError('p must be at least 5') + # The modn implementation takes care of checking that ``p`` is prime self._field = GF(p, impl='modn') @@ -77,7 +82,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): if self._g == 0 or self._g == 1 or self._g == p - 1: raise ValueError('g cannot be 0, 1, or p - 1 (mod p)') - def field(self) -> FiniteField_prime_modn_with_category: + def field(self) -> FiniteField_prime_modn: """ Return the field this Diffie-Hellman instance is working over. From c183db2ec995e8631283995435c5fa505e221e33 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 16 Jul 2024 14:18:05 -0600 Subject: [PATCH 05/29] References --- src/doc/en/reference/references/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 5daed6ce180..b73de8ee5a1 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -5344,7 +5344,7 @@ REFERENCES: :doi:`10.1023/A:1009724323513` .. [PP2010] \C. Paar and J. Pelzl. - *Understanding Cryptography*. + *Understanding Cryptography: A Textbook for Students and Practitioners*. Springer Berlin, Heidelberg, 2010. :doi:`10.1007/978-3-642-04101-3` From cc513e7e72d04c1ebdf0f053dde56a005afbd6a8 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 16 Jul 2024 14:33:00 -0600 Subject: [PATCH 06/29] Missing tests --- .../crypto/key_exchange/diffie_hellman.py | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index d72f88f3a44..0a43a37d77a 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -63,6 +63,29 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): sage: DH = 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. + + TESTS:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(3, 2) + Traceback (most recent call last): + ... + ValueError: p must be at least 5 + + sage: DH = DiffieHellman(5, 0) + Traceback (most recent call last): + ... + ValueError: g cannot be 0, 1, or p - 1 (mod p) + + sage: DH = DiffieHellman(5, 1) + Traceback (most recent call last): + ... + ValueError: g cannot be 0, 1, or p - 1 (mod p) + + sage: DH = DiffieHellman(5, 4) + Traceback (most recent call last): + ... + ValueError: g cannot be 0, 1, or p - 1 (mod p) """ if p < 5: @@ -207,10 +230,33 @@ def __len__(self): return int(self.subgroup_size()) def __eq__(self, other): - return self._p == other._p and self._g == other._g + """ + Check if two Diffie-Hellman instances have the same parameter set. + + EXAMPLES:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH1 = DiffieHellman(5, 2) + sage: DH2 = DiffieHellman(5, 2) + sage: DH1 == DH2 + True + """ + return self.parameters() == other.parameters() def __hash__(self): - return hash((self._p, other._g)) + """ + Compute the hash value of a Diffie-Hellman instance. + + EXAMPLES:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH1 = DiffieHellman(7, 3) + sage: DH2 = DiffieHellman(7, 3) + sage: s = set([DH1, DH2]) + sage: len(s) + 1 + """ + return hash((self._p, self._g)) def _repr_(self): return f'Diffie-Hellman key exchange over {self._field} with generator {self._g}' From 5ee6d0adafe37fab5d85869ea56c4f50529b0b3d Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 16 Jul 2024 14:33:23 -0600 Subject: [PATCH 07/29] Formatting --- src/sage/crypto/key_exchange/diffie_hellman.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 0a43a37d77a..72f9d0781ae 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -42,7 +42,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): INPUT: - - ``p`` -- prime integer defining the field `\\GF{p}`` that the key exchanges + - ``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` From 4cb006f1dcc9a40e6ef465ba57a44149ad4be28f Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 16 Jul 2024 14:52:32 -0600 Subject: [PATCH 08/29] Cleanup and tests --- .../crypto/key_exchange/diffie_hellman.py | 75 +++++++++++++++---- src/sage/crypto/key_exchange/pke.py | 3 +- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 72f9d0781ae..067e5cb8415 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -28,14 +28,14 @@ from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn from sage.rings.finite_rings.integer_mod import IntegerMod_int -from sage.structure.sage_object import SageObject +from sage.structure.proof.proof import WithProof from typing import Union class DiffieHellman(KeyExchangeScheme): @experimental(37305) - def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): + def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int], proof: bool = True): """ Create an instance of the Diffie-Hellman key exchange scheme using the given prime ``p`` and base ``g``. @@ -47,6 +47,12 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): - ``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 @@ -64,6 +70,20 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): 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 RFC3526. + + sage: p = 2^8192 - 2^8128 - 1 + 2^64 * (round(2^8062 * pi) + 4743158) + sage: DH = 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 + TESTS:: sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman @@ -91,8 +111,12 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int]): if p < 5: raise ValueError('p must be at least 5') - # The modn implementation takes care of checking that ``p`` is prime - self._field = GF(p, impl='modn') + if proof: + # The modn implementation takes care of checking that ``p`` is prime + self._field = GF(p, impl='modn') + else: + with WithProof('arithmetic', False): + self._field = GF(p, impl='modn') self._p = p self._g = self._field(g) @@ -188,16 +212,15 @@ def generate_public_key(self, secret_key: Integer) -> IntegerMod_int: """ return self._g**secret_key - def compute_shared_secret(self, alice_pk: IntegerMod_int, bob_sk: Integer) -> IntegerMod_int: + def compute_shared_secret(self, pk: IntegerMod_int, sk: Integer) -> IntegerMod_int: """ - Compute Alice and Bob's shared secret using Alice's public key and - Bob's secret key. + Compute the shared secret using the given public key and secret keys. INPUT: - - ``alice_pk`` -- Alice's public key + - ``pk`` -- public key - - ``bob_sk`` -- Bob's secret key + - ``sk`` -- secret key EXAMPLES:: @@ -206,11 +229,12 @@ def compute_shared_secret(self, alice_pk: IntegerMod_int, bob_sk: Integer) -> In sage: DH.compute_shared_secret(13, 11) 4 """ - return self._field(alice_pk**bob_sk) + return self._field(pk**sk) def subgroup_size(self) -> Integer: """ - Calculates the size of the subgroup of `\\GF{p}` generated by ``self.generator()``. + Calculates the size of the subgroup of `\\GF{p}` generated by + ``self.generator()``. EXAMPLES: @@ -227,13 +251,17 @@ def subgroup_size(self) -> Integer: return self._g.multiplicative_order() def __len__(self): + """ + Calculates the size of the subgroup of `\\GF{p}` generated by + ``self.generator()``. This is a wrapper around `subgroup_size`. + """ return int(self.subgroup_size()) def __eq__(self, other): """ Check if two Diffie-Hellman instances have the same parameter set. - EXAMPLES:: + TESTS:: sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH1 = DiffieHellman(5, 2) @@ -247,7 +275,7 @@ def __hash__(self): """ Compute the hash value of a Diffie-Hellman instance. - EXAMPLES:: + TESTS:: sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH1 = DiffieHellman(7, 3) @@ -259,7 +287,26 @@ def __hash__(self): return hash((self._p, self._g)) def _repr_(self): + """ + Get the string representation of the Diffie-Hellman instance. + + TESTS:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(7, 3) + sage: DH + Diffie-Hellman key exchange over Finite Field of size 7 with generator 3 + """ return f'Diffie-Hellman key exchange over {self._field} with generator {self._g}' def _latex_(self): - return f'\\text{{Diffie-Hellman key exchange over }}{self._field}\\text{{ with generator }}{self._g}' + """ + Get the LaTeX representation of the Diffie-Hellman instance. + + TESTS:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(7, 3) + sage: latex(DH) + """ + return f'\\text{{Diffie-Hellman key exchange over }}{self._field._latex_()}\\text{{ with generator }}{self._g}' diff --git a/src/sage/crypto/key_exchange/pke.py b/src/sage/crypto/key_exchange/pke.py index 93fc6bf8edc..bd594f14cab 100644 --- a/src/sage/crypto/key_exchange/pke.py +++ b/src/sage/crypto/key_exchange/pke.py @@ -21,8 +21,9 @@ # **************************************************************************** from sage.misc.superseded import experimental +from sage.structure.sage_object import SageObject -class KeyExchangeScheme: +class KeyExchangeScheme(SageObject): @experimental(37305) def __init__(self): From 16d3d98b2fcd934b93b3a262647cf2cff0eaeb1b Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 16 Jul 2024 14:53:26 -0600 Subject: [PATCH 09/29] Rename file --- src/sage/crypto/key_exchange/diffie_hellman.py | 2 +- src/sage/crypto/key_exchange/{pke.py => key_exchange.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/sage/crypto/key_exchange/{pke.py => key_exchange.py} (100%) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 067e5cb8415..114aa7365e3 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -20,7 +20,7 @@ from sage.misc.superseded import experimental -from sage.crypto.key_exchange.pke import KeyExchangeScheme +from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme from sage.arith.misc import is_prime from sage.misc.prandom import randint diff --git a/src/sage/crypto/key_exchange/pke.py b/src/sage/crypto/key_exchange/key_exchange.py similarity index 100% rename from src/sage/crypto/key_exchange/pke.py rename to src/sage/crypto/key_exchange/key_exchange.py From f0a8ea0199fc58500afab696b8b102f54af9aac2 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 16 Jul 2024 14:55:51 -0600 Subject: [PATCH 10/29] LaTeX doctest --- src/sage/crypto/key_exchange/diffie_hellman.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 114aa7365e3..9323c3b322c 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -308,5 +308,6 @@ def _latex_(self): sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(7, 3) sage: latex(DH) + \text{Diffie-Hellman key exchange over }\Bold{F}_{7}\text{ with generator }3 """ return f'\\text{{Diffie-Hellman key exchange over }}{self._field._latex_()}\\text{{ with generator }}{self._g}' From bacebe9f9c9ae22b05a18fbd75955fdab33eb55e Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 16 Jul 2024 15:04:35 -0600 Subject: [PATCH 11/29] Style fix --- src/sage/crypto/key_exchange/diffie_hellman.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 9323c3b322c..c1a8e7c5a2a 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -300,7 +300,7 @@ def _repr_(self): return f'Diffie-Hellman key exchange over {self._field} with generator {self._g}' def _latex_(self): - """ + r""" Get the LaTeX representation of the Diffie-Hellman instance. TESTS:: From b12adddea0e622e253e852b51b9acdc6cc990d66 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 16 Jul 2024 16:12:30 -0600 Subject: [PATCH 12/29] Fix doc formatting --- src/sage/crypto/key_exchange/diffie_hellman.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index c1a8e7c5a2a..cf686ef504d 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -71,7 +71,8 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int], proof: bool = 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 RFC3526. + large prime. This is the prime from the 8192-bit MODP group in + RFC3526.:: sage: p = 2^8192 - 2^8128 - 1 + 2^64 * (round(2^8062 * pi) + 4743158) sage: DH = DiffieHellman(p, 2, proof=False) From 6f7b5e2d4da4254ebbaf5c9bd005a81b42f1eec2 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Wed, 17 Jul 2024 10:40:03 -0600 Subject: [PATCH 13/29] Apply suggestions from code review Co-authored-by: grnx <47418794+JosePisco@users.noreply.github.com> --- src/sage/crypto/key_exchange/diffie_hellman.py | 18 ++++++++++-------- src/sage/crypto/key_exchange/key_exchange.py | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index cf686ef504d..a01aac7dc5d 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -1,8 +1,8 @@ r""" Diffie-Hellman Public Key Exchange Scheme -This module contains a toy implementation of the Diffie-Hellman public key exchange -scheme. +This module contains a toy implementation of the Diffie-Hellman public key +exchange scheme. AUTHORS: @@ -26,7 +26,8 @@ from sage.misc.prandom import randint from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_constructor import GF -from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn +from sage.rings.finite_rings.finite_field_prime_modn import \ + FiniteField_prime_modn from sage.rings.finite_rings.integer_mod import IntegerMod_int from sage.structure.proof.proof import WithProof @@ -42,10 +43,11 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int], proof: bool = INPUT: - - ``p`` -- prime integer defining the field `\\GF{p}` that the key exchanges - will be performed over, must be at least 5 + - ``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` + - ``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 @@ -122,8 +124,8 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int], proof: bool = self._p = p self._g = self._field(g) - # While these values won't cause mathematical problems, they do completely - # break the security of the Diffie-Hellman scheme. + # While these values won't cause mathematical problems, they do + # completely break the security of the Diffie-Hellman scheme. # g = 0 makes every secret key and shared secret 0 # g = 1 makes every secret key and shared secret 1 # g = -1 makes every secret key and shared secret 1 or -1 diff --git a/src/sage/crypto/key_exchange/key_exchange.py b/src/sage/crypto/key_exchange/key_exchange.py index bd594f14cab..c9dbb85adcc 100644 --- a/src/sage/crypto/key_exchange/key_exchange.py +++ b/src/sage/crypto/key_exchange/key_exchange.py @@ -1,9 +1,9 @@ r""" Public key exchange schemes. -This module contains base classes for public key exchange schemes. The classes defined in -this module should not be called directly. It is the responsibility of child classes to -implement specific cryptosystems. +This module contains base classes for public key exchange schemes. The classes +defined in this module should not be called directly. It is the responsibility +of child classes to implement specific cryptosystems. AUTHORS: From f7b074494c53b7c7aabb4356e37a2843466ef818 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Wed, 17 Jul 2024 10:47:42 -0600 Subject: [PATCH 14/29] Formatting for when referring to the DiffieHellman class rather than the key exchange scheme --- .../crypto/key_exchange/diffie_hellman.py | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index a01aac7dc5d..1f2da9a0018 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -74,7 +74,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int], proof: bool = 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 - RFC3526.:: + RFC3526:: sage: p = 2^8192 - 2^8128 - 1 + 2^64 * (round(2^8062 * pi) + 4743158) sage: DH = DiffieHellman(p, 2, proof=False) @@ -134,7 +134,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int], proof: bool = def field(self) -> FiniteField_prime_modn: """ - Return the field this Diffie-Hellman instance is working over. + Return the field this ``DiffieHellman`` instance is working over. EXAMPLES:: @@ -147,7 +147,7 @@ def field(self) -> FiniteField_prime_modn: def prime(self) -> Integer: """ - Return the prime ``p`` for this Diffie-Hellman instance. + Return the prime ``p`` for this ``DiffieHellman`` instance. EXAMPLES:: @@ -160,7 +160,7 @@ def prime(self) -> Integer: def generator(self) -> IntegerMod_int: """ - Return the generator ``g`` for this Diffie-Hellman instance. + Return the generator ``g`` for this ``DiffieHellman`` instance. EXAMPLES:: @@ -173,7 +173,7 @@ def generator(self) -> IntegerMod_int: def parameters(self) -> tuple[Integer, IntegerMod_int]: """ - Output the parameters ``(p, g)`` for this Diffie-Hellman instance. + Output the parameters ``(p, g)`` for this ``DiffieHellman`` instance. EXAMPLES:: @@ -241,6 +241,8 @@ def subgroup_size(self) -> Integer: EXAMPLES: + This is an example of a ``DiffieHellman`` instance where the subgroup size is `(p - 1) / 2` + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(47, 2) sage: DH.subgroup_size() @@ -262,7 +264,7 @@ def __len__(self): def __eq__(self, other): """ - Check if two Diffie-Hellman instances have the same parameter set. + Check if two ``DiffieHellman`` instances have the same parameter set. TESTS:: @@ -276,7 +278,7 @@ def __eq__(self, other): def __hash__(self): """ - Compute the hash value of a Diffie-Hellman instance. + Compute the hash value of a ``DiffieHellman`` instance. TESTS:: @@ -291,7 +293,7 @@ def __hash__(self): def _repr_(self): """ - Get the string representation of the Diffie-Hellman instance. + Get the string representation of the ``DiffieHellman`` instance. TESTS:: @@ -304,7 +306,7 @@ def _repr_(self): def _latex_(self): r""" - Get the LaTeX representation of the Diffie-Hellman instance. + Get the LaTeX representation of the ``DiffieHellman`` instance. TESTS:: From 6b8617404fbe84e0cc60fe0449b506aa52251a66 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Wed, 17 Jul 2024 10:50:54 -0600 Subject: [PATCH 15/29] Add missing test --- src/sage/crypto/key_exchange/diffie_hellman.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 1f2da9a0018..8268aba6d6c 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -241,13 +241,15 @@ def subgroup_size(self) -> Integer: EXAMPLES: - This is an example of a ``DiffieHellman`` instance where the subgroup size is `(p - 1) / 2` + This is an example of a ``DiffieHellman`` instance where the subgroup size is `(p - 1) / 2`:: sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(47, 2) sage: DH.subgroup_size() 23 + This is an example of a ``DiffieHellman`` instance where the subgroup size is `p - 1`:: + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(47, 5) sage: DH.subgroup_size() @@ -259,6 +261,13 @@ def __len__(self): """ Calculates the size of the subgroup of `\\GF{p}` generated by ``self.generator()``. This is a wrapper around `subgroup_size`. + + TESTS:: + + sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman + sage: DH = DiffieHellman(53, 9) + sage: len(DH) + 26 """ return int(self.subgroup_size()) From a97866a30a673571ef01af5a8c89c297fd6a333c Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Wed, 17 Jul 2024 11:24:57 -0600 Subject: [PATCH 16/29] Formatting and type annotation fixes --- .../crypto/key_exchange/diffie_hellman.py | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 8268aba6d6c..fe23f3b09d6 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -28,7 +28,7 @@ from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.finite_rings.finite_field_prime_modn import \ FiniteField_prime_modn -from sage.rings.finite_rings.integer_mod import IntegerMod_int +from sage.rings.finite_rings.integer_mod import IntegerMod_abstract from sage.structure.proof.proof import WithProof from typing import Union @@ -36,7 +36,8 @@ class DiffieHellman(KeyExchangeScheme): @experimental(37305) - def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int], proof: bool = True): + def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], + proof: bool = True) -> None: """ Create an instance of the Diffie-Hellman key exchange scheme using the given prime ``p`` and base ``g``. @@ -52,7 +53,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_int], proof: bool = - ``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 + when using large (cryptographic size) primes, otherwise checking primality will take too long. .. WARNING:: @@ -158,7 +159,7 @@ def prime(self) -> Integer: """ return self._p - def generator(self) -> IntegerMod_int: + def generator(self) -> IntegerMod_abstract: """ Return the generator ``g`` for this ``DiffieHellman`` instance. @@ -171,7 +172,7 @@ def generator(self) -> IntegerMod_int: """ return self._g - def parameters(self) -> tuple[Integer, IntegerMod_int]: + def parameters(self) -> tuple[Integer, IntegerMod_abstract]: """ Output the parameters ``(p, g)`` for this ``DiffieHellman`` instance. @@ -198,7 +199,7 @@ def generate_secret_key(self) -> Integer: """ return randint(2, self._p - 2) - def generate_public_key(self, secret_key: Integer) -> IntegerMod_int: + def generate_public_key(self, secret_key: Integer) -> IntegerMod_abstract: """ Generate a Diffie-Hellman public key using the given secret key. @@ -215,7 +216,7 @@ def generate_public_key(self, secret_key: Integer) -> IntegerMod_int: """ return self._g**secret_key - def compute_shared_secret(self, pk: IntegerMod_int, sk: Integer) -> IntegerMod_int: + def compute_shared_secret(self, pk: IntegerMod_abstract, sk: Integer) -> IntegerMod_abstract: """ Compute the shared secret using the given public key and secret keys. @@ -257,7 +258,7 @@ def subgroup_size(self) -> Integer: """ return self._g.multiplicative_order() - def __len__(self): + def __len__(self) -> int: """ Calculates the size of the subgroup of `\\GF{p}` generated by ``self.generator()``. This is a wrapper around `subgroup_size`. @@ -271,7 +272,7 @@ def __len__(self): """ return int(self.subgroup_size()) - def __eq__(self, other): + def __eq__(self, other) -> bool: """ Check if two ``DiffieHellman`` instances have the same parameter set. @@ -282,10 +283,14 @@ def __eq__(self, other): sage: DH2 = DiffieHellman(5, 2) sage: DH1 == DH2 True + sage: DH1 == 5 + False """ - return self.parameters() == other.parameters() + if isinstance(other, DiffieHellman): + return self.parameters() == other.parameters() + return False - def __hash__(self): + def __hash__(self) -> int: """ Compute the hash value of a ``DiffieHellman`` instance. @@ -300,7 +305,7 @@ def __hash__(self): """ return hash((self._p, self._g)) - def _repr_(self): + def _repr_(self) -> str: """ Get the string representation of the ``DiffieHellman`` instance. @@ -311,9 +316,12 @@ def _repr_(self): sage: DH Diffie-Hellman key exchange over Finite Field of size 7 with generator 3 """ - return f'Diffie-Hellman key exchange over {self._field} with generator {self._g}' + return ('Diffie-Hellman key exchange over' + f'{self._field}' + 'with generator' + f'{self._g}') - def _latex_(self): + def _latex_(self) -> str: r""" Get the LaTeX representation of the ``DiffieHellman`` instance. @@ -324,4 +332,7 @@ def _latex_(self): sage: latex(DH) \text{Diffie-Hellman key exchange over }\Bold{F}_{7}\text{ with generator }3 """ - return f'\\text{{Diffie-Hellman key exchange over }}{self._field._latex_()}\\text{{ with generator }}{self._g}' + return ('\\text{Diffie-Hellman key exchange over }' + f'{self._field._latex_()}' + '\\text{ with generator }' + f'{self._g}') From babeb3c601a406f687c793a1e954ea1c70d5adbb Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Wed, 17 Jul 2024 11:27:45 -0600 Subject: [PATCH 17/29] String formatting --- src/sage/crypto/key_exchange/diffie_hellman.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index fe23f3b09d6..0a9a6962ad6 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -316,9 +316,9 @@ def _repr_(self) -> str: sage: DH Diffie-Hellman key exchange over Finite Field of size 7 with generator 3 """ - return ('Diffie-Hellman key exchange over' - f'{self._field}' - 'with generator' + return ('Diffie-Hellman key exchange over ' + f'{self._field} ' + 'with generator ' f'{self._g}') def _latex_(self) -> str: From dd098a197b0154a0e5abfb88676f577bc2000371 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Wed, 17 Jul 2024 11:59:05 -0600 Subject: [PATCH 18/29] Cleanup pass Added tests for KeyExchangeScheme base class. Added KeyExchangeScheme to docs because the intention is users can extend this class --- src/doc/en/reference/cryptography/index.rst | 1 + .../crypto/key_exchange/diffie_hellman.py | 4 +- src/sage/crypto/key_exchange/key_exchange.py | 65 ++++++++++++++++++- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/doc/en/reference/cryptography/index.rst b/src/doc/en/reference/cryptography/index.rst index 7f58b50ee5f..313081f8cd6 100644 --- a/src/doc/en/reference/cryptography/index.rst +++ b/src/doc/en/reference/cryptography/index.rst @@ -34,6 +34,7 @@ Cryptography sage/crypto/lattice sage/crypto/lwe + sage/crypto/key_exchange/key_exchange sage/crypto/key_exchange/diffie_hellman .. include:: ../footer.txt diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 0a9a6962ad6..aa28ce072ad 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -6,7 +6,7 @@ AUTHORS: -- Vincent Macri (2024-07-15): initial version +- Vincent Macri (2024-07-17): initial version """ # **************************************************************************** # Copyright (C) 2024 Vincent Macri @@ -174,7 +174,7 @@ def generator(self) -> IntegerMod_abstract: def parameters(self) -> tuple[Integer, IntegerMod_abstract]: """ - Output the parameters ``(p, g)`` for this ``DiffieHellman`` instance. + Get the parameters ``(p, g)`` for this ``DiffieHellman`` instance. EXAMPLES:: diff --git a/src/sage/crypto/key_exchange/key_exchange.py b/src/sage/crypto/key_exchange/key_exchange.py index c9dbb85adcc..89986d1020e 100644 --- a/src/sage/crypto/key_exchange/key_exchange.py +++ b/src/sage/crypto/key_exchange/key_exchange.py @@ -8,7 +8,7 @@ AUTHORS: -- Vincent Macri (2024-07-15): initial version +- Vincent Macri (2024-07-17): initial version """ # **************************************************************************** # Copyright (C) 2024 Vincent Macri @@ -24,19 +24,82 @@ from sage.structure.sage_object import SageObject class KeyExchangeScheme(SageObject): + """ + Abstract base class for key exchange schemes. + + Currently experimental and subject to change. + """ @experimental(37305) def __init__(self): + """ + Create a ``KeyExchangeScheme`` instance. + + TESTS:: + + sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: K = KeyExchangeScheme() + 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. + """ pass def generate_secret_key(self): + """ + Generate a secret key. + + TESTS:: + + sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: K = KeyExchangeScheme() + sage: K.generate_secret_key() + Traceback (most recent call last): + ... + NotImplementedError + """ raise NotImplementedError def generate_public_key(self, secret_key): + """ + Generate a public key using the given secret key. + + TESTS:: + + sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: K = KeyExchangeScheme() + sage: K.generate_public_key(None) + Traceback (most recent call last): + ... + NotImplementedError + """ raise NotImplementedError def compute_shared_secret(self, alice_pk, bob_sk): + """ + Compute the shared secret using the given public key and secret keys. + + TESTS:: + + sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: K = KeyExchangeScheme() + sage: K.compute_shared_secret(None, None) + Traceback (most recent call last): + ... + NotImplementedError + """ raise NotImplementedError def parameters(self): + """ + Get the parameters for the ``KeyExchangeScheme`` instance. + + TESTS:: + + sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: K = KeyExchangeScheme() + sage: K.parameters() + Traceback (most recent call last): + ... + NotImplementedError + """ raise NotImplementedError From 42159fcf2340c19c683ee7e7cc85bcbc94560d84 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Wed, 17 Jul 2024 13:55:46 -0600 Subject: [PATCH 19/29] Line length fixes --- src/sage/crypto/key_exchange/diffie_hellman.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index aa28ce072ad..0bafcece7ac 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -58,9 +58,9 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], .. 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! + 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: @@ -116,7 +116,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], raise ValueError('p must be at least 5') if proof: - # The modn implementation takes care of checking that ``p`` is prime + # The modn implementation checks that ``p`` is prime self._field = GF(p, impl='modn') else: with WithProof('arithmetic', False): @@ -216,7 +216,8 @@ def generate_public_key(self, secret_key: Integer) -> IntegerMod_abstract: """ return self._g**secret_key - def compute_shared_secret(self, pk: IntegerMod_abstract, sk: Integer) -> IntegerMod_abstract: + def compute_shared_secret(self, pk: IntegerMod_abstract, + sk: Integer) -> IntegerMod_abstract: """ Compute the shared secret using the given public key and secret keys. @@ -242,14 +243,16 @@ def subgroup_size(self) -> Integer: EXAMPLES: - This is an example of a ``DiffieHellman`` instance where the subgroup size is `(p - 1) / 2`:: + This is an example of a ``DiffieHellman`` instance where the subgroup + size is `(p - 1) / 2`:: sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(47, 2) sage: DH.subgroup_size() 23 - This is an example of a ``DiffieHellman`` instance where the subgroup size is `p - 1`:: + This is an example of a ``DiffieHellman`` instance where the subgroup + size is `p - 1`:: sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(47, 5) From 62985532250167d5d890dd76db802532b0af391d Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Thu, 18 Jul 2024 10:26:05 -0600 Subject: [PATCH 20/29] Use more standard wording --- src/sage/crypto/key_exchange/diffie_hellman.py | 6 +++--- src/sage/crypto/key_exchange/key_exchange.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 0bafcece7ac..459adbf15ba 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -1,8 +1,8 @@ r""" -Diffie-Hellman Public Key Exchange Scheme +Diffie-Hellman Key Exchange Scheme -This module contains a toy implementation of the Diffie-Hellman public key -exchange scheme. +This module contains a toy implementation of the Diffie-Hellman key exchange +scheme. AUTHORS: diff --git a/src/sage/crypto/key_exchange/key_exchange.py b/src/sage/crypto/key_exchange/key_exchange.py index 89986d1020e..39aab201b86 100644 --- a/src/sage/crypto/key_exchange/key_exchange.py +++ b/src/sage/crypto/key_exchange/key_exchange.py @@ -1,9 +1,9 @@ r""" -Public key exchange schemes. +Key exchange schemes. -This module contains base classes for public key exchange schemes. The classes -defined in this module should not be called directly. It is the responsibility -of child classes to implement specific cryptosystems. +This module contains base classes for key exchange schemes. The classes defined +in this module should not be called directly. It is the responsibility of child +classes to implement specific cryptosystems. AUTHORS: From 7801f9d72a15aa16b36c68877bf0e02d0197c70e Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Thu, 18 Jul 2024 10:58:15 -0600 Subject: [PATCH 21/29] Clearer wording --- src/sage/crypto/key_exchange/key_exchange.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/crypto/key_exchange/key_exchange.py b/src/sage/crypto/key_exchange/key_exchange.py index 39aab201b86..edc91e88fa0 100644 --- a/src/sage/crypto/key_exchange/key_exchange.py +++ b/src/sage/crypto/key_exchange/key_exchange.py @@ -3,7 +3,7 @@ This module contains base classes for key exchange schemes. The classes defined in this module should not be called directly. It is the responsibility of child -classes to implement specific cryptosystems. +classes to implement specific key exchange schemes. AUTHORS: From f74d913a2298e6d15fe37e0ae04cb32973ba385c Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 30 Jul 2024 11:21:51 -0600 Subject: [PATCH 22/29] Apply suggestions from code review Co-authored-by: grhkm21 <83517584+grhkm21@users.noreply.github.com> --- src/sage/crypto/key_exchange/diffie_hellman.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 459adbf15ba..d4352aef595 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -38,17 +38,17 @@ class DiffieHellman(KeyExchangeScheme): @experimental(37305) def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], proof: bool = True) -> None: - """ + r""" 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 + - ``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` + `\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 @@ -64,7 +64,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], REFERENCES: - For more information, see [PP2010]_, section 8.1. + For more information, see Section 8.1 of [PP2010]_. EXAMPLES:: From 474e09de8ad328b8c9b5c2da116ddba9e0547e3b Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 30 Jul 2024 11:32:33 -0600 Subject: [PATCH 23/29] Add reference to RFC --- src/doc/en/reference/references/index.rst | 4 ++++ src/sage/crypto/key_exchange/diffie_hellman.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 3dbb92ea31e..25351747116 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -3846,6 +3846,10 @@ REFERENCES: \M. Grötschel, \L Lovász, *Handbook of combinatorics*, Vol. 1, Chapter 18, 1995 +.. [KK2003] T. Kivinen and M. Kojo. *More Modular Exponential (MODP) + Diffie-Hellman groups for Internet Key Exchange (IKE)*, in RFC 3526. + Available at https://www.rfc-editor.org/rfc/rfc3526 + .. [KKMMNN1992] S-J. Kang, M. Kashiwara, K. C. Misra, T. Miwa, T. Nakashima, and A. Nakayashiki. *Affine crystals and vertex models*. Int. J. Mod. Phys. A, **7** (suppl. 1A), (1992) pp. 449-484. diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index d4352aef595..d4fed832ca8 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -74,8 +74,8 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], 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 - RFC3526:: + 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 = DiffieHellman(p, 2, proof=False) From 441fdfccfffed7950232188c48f7688af6f986c2 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 30 Jul 2024 11:58:11 -0600 Subject: [PATCH 24/29] Refactoring/cleanup --- src/doc/en/reference/cryptography/index.rst | 2 +- src/sage/crypto/all.py | 5 +++++ src/sage/crypto/key_exchange/all.py | 6 ++---- src/sage/crypto/key_exchange/diffie_hellman.py | 18 +----------------- ...{key_exchange.py => key_exchange_scheme.py} | 0 5 files changed, 9 insertions(+), 22 deletions(-) rename src/sage/crypto/key_exchange/{key_exchange.py => key_exchange_scheme.py} (100%) diff --git a/src/doc/en/reference/cryptography/index.rst b/src/doc/en/reference/cryptography/index.rst index 313081f8cd6..ef71153fc17 100644 --- a/src/doc/en/reference/cryptography/index.rst +++ b/src/doc/en/reference/cryptography/index.rst @@ -34,7 +34,7 @@ Cryptography sage/crypto/lattice sage/crypto/lwe - sage/crypto/key_exchange/key_exchange + sage/crypto/key_exchange/key_exchange_scheme sage/crypto/key_exchange/diffie_hellman .. include:: ../footer.txt diff --git a/src/sage/crypto/all.py b/src/sage/crypto/all.py index 811ee2c6a78..1353ec7837e 100644 --- a/src/sage/crypto/all.py +++ b/src/sage/crypto/all.py @@ -20,4 +20,9 @@ 'lfsr_autocorrelation', 'lfsr_connection_polynomial', ]) + +lazy_import('sage.crypto.key_exchange.all', ['KeyExchangeScheme', + 'DiffieHellman', + ]) + del lazy_import diff --git a/src/sage/crypto/key_exchange/all.py b/src/sage/crypto/key_exchange/all.py index d961ec5ed13..f5335aae439 100644 --- a/src/sage/crypto/key_exchange/all.py +++ b/src/sage/crypto/key_exchange/all.py @@ -1,4 +1,2 @@ -from sage.misc.lazy_import import lazy_import - -lazy_import('sage.crypto.key_exchange.diffie_hellman', 'DiffieHellman') -del lazy_import +from sage.crypto.key_exchange.diffie_hellman import DiffieHellman +from sage.crypto.key_exchange.key_exchange_scheme import KeyExchangeScheme diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index d4fed832ca8..22ead8fbb4b 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -20,7 +20,7 @@ from sage.misc.superseded import experimental -from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme +from sage.crypto.key_exchange.key_exchange_scheme import KeyExchangeScheme from sage.arith.misc import is_prime from sage.misc.prandom import randint @@ -68,7 +68,6 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], EXAMPLES:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = 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. @@ -90,7 +89,6 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], TESTS:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(3, 2) Traceback (most recent call last): ... @@ -139,7 +137,6 @@ def field(self) -> FiniteField_prime_modn: EXAMPLES:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(5, 2) sage: DH.field() Finite Field of size 5 @@ -152,7 +149,6 @@ def prime(self) -> Integer: EXAMPLES:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(7, 3) sage: DH.prime() 7 @@ -165,7 +161,6 @@ def generator(self) -> IntegerMod_abstract: EXAMPLES:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(7, 3) sage: DH.generator() 3 @@ -178,7 +173,6 @@ def parameters(self) -> tuple[Integer, IntegerMod_abstract]: EXAMPLES:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(7, 3) sage: DH.parameters() (7, 3) @@ -191,7 +185,6 @@ def generate_secret_key(self) -> Integer: TESTS: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(7, 2) sage: keys = [DH.generate_secret_key() for i in range(10)] sage: all(2 <= i <= 5 for i in keys) @@ -209,7 +202,6 @@ def generate_public_key(self, secret_key: Integer) -> IntegerMod_abstract: EXAMPLES:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(13, 2) sage: DH.generate_public_key(4) 3 @@ -229,7 +221,6 @@ def compute_shared_secret(self, pk: IntegerMod_abstract, EXAMPLES:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(17, 3) sage: DH.compute_shared_secret(13, 11) 4 @@ -246,7 +237,6 @@ def subgroup_size(self) -> Integer: This is an example of a ``DiffieHellman`` instance where the subgroup size is `(p - 1) / 2`:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(47, 2) sage: DH.subgroup_size() 23 @@ -254,7 +244,6 @@ def subgroup_size(self) -> Integer: This is an example of a ``DiffieHellman`` instance where the subgroup size is `p - 1`:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(47, 5) sage: DH.subgroup_size() 46 @@ -268,7 +257,6 @@ def __len__(self) -> int: TESTS:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(53, 9) sage: len(DH) 26 @@ -281,7 +269,6 @@ def __eq__(self, other) -> bool: TESTS:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH1 = DiffieHellman(5, 2) sage: DH2 = DiffieHellman(5, 2) sage: DH1 == DH2 @@ -299,7 +286,6 @@ def __hash__(self) -> int: TESTS:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH1 = DiffieHellman(7, 3) sage: DH2 = DiffieHellman(7, 3) sage: s = set([DH1, DH2]) @@ -314,7 +300,6 @@ def _repr_(self) -> str: TESTS:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(7, 3) sage: DH Diffie-Hellman key exchange over Finite Field of size 7 with generator 3 @@ -330,7 +315,6 @@ def _latex_(self) -> str: TESTS:: - sage: from sage.crypto.key_exchange.diffie_hellman import DiffieHellman sage: DH = DiffieHellman(7, 3) sage: latex(DH) \text{Diffie-Hellman key exchange over }\Bold{F}_{7}\text{ with generator }3 diff --git a/src/sage/crypto/key_exchange/key_exchange.py b/src/sage/crypto/key_exchange/key_exchange_scheme.py similarity index 100% rename from src/sage/crypto/key_exchange/key_exchange.py rename to src/sage/crypto/key_exchange/key_exchange_scheme.py From d58532b3f845caa869f751c10ab30f0acf03146f Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 30 Jul 2024 12:11:59 -0600 Subject: [PATCH 25/29] Import tweaks --- src/sage/crypto/all.py | 5 ++--- src/sage/crypto/key_exchange/all.py | 7 +++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/sage/crypto/all.py b/src/sage/crypto/all.py index 1353ec7837e..0ca12243e8d 100644 --- a/src/sage/crypto/all.py +++ b/src/sage/crypto/all.py @@ -21,8 +21,7 @@ 'lfsr_connection_polynomial', ]) -lazy_import('sage.crypto.key_exchange.all', ['KeyExchangeScheme', - 'DiffieHellman', - ]) + +from sage.crypto.key_exchange.all import * del lazy_import diff --git a/src/sage/crypto/key_exchange/all.py b/src/sage/crypto/key_exchange/all.py index f5335aae439..5ca055c786c 100644 --- a/src/sage/crypto/key_exchange/all.py +++ b/src/sage/crypto/key_exchange/all.py @@ -1,2 +1,5 @@ -from sage.crypto.key_exchange.diffie_hellman import DiffieHellman -from sage.crypto.key_exchange.key_exchange_scheme import KeyExchangeScheme +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.crypto.key_exchange.diffie_hellman', 'DiffieHellman') + +del lazy_import From cdb09622017f22533cafbf6e438a09df175fdb15 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 30 Jul 2024 12:13:38 -0600 Subject: [PATCH 26/29] Fix tests --- src/sage/crypto/key_exchange/key_exchange_scheme.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/crypto/key_exchange/key_exchange_scheme.py b/src/sage/crypto/key_exchange/key_exchange_scheme.py index edc91e88fa0..575f091c49b 100644 --- a/src/sage/crypto/key_exchange/key_exchange_scheme.py +++ b/src/sage/crypto/key_exchange/key_exchange_scheme.py @@ -37,7 +37,7 @@ def __init__(self): TESTS:: - sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: from sage.crypto.key_exchange.key_exchange_scheme import KeyExchangeScheme sage: K = KeyExchangeScheme() 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. @@ -50,7 +50,7 @@ def generate_secret_key(self): TESTS:: - sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: from sage.crypto.key_exchange.key_exchange_scheme import KeyExchangeScheme sage: K = KeyExchangeScheme() sage: K.generate_secret_key() Traceback (most recent call last): @@ -65,7 +65,7 @@ def generate_public_key(self, secret_key): TESTS:: - sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: from sage.crypto.key_exchange.key_exchange_scheme import KeyExchangeScheme sage: K = KeyExchangeScheme() sage: K.generate_public_key(None) Traceback (most recent call last): @@ -80,7 +80,7 @@ def compute_shared_secret(self, alice_pk, bob_sk): TESTS:: - sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: from sage.crypto.key_exchange.key_exchange_scheme import KeyExchangeScheme sage: K = KeyExchangeScheme() sage: K.compute_shared_secret(None, None) Traceback (most recent call last): @@ -95,7 +95,7 @@ def parameters(self): TESTS:: - sage: from sage.crypto.key_exchange.key_exchange import KeyExchangeScheme + sage: from sage.crypto.key_exchange.key_exchange_scheme import KeyExchangeScheme sage: K = KeyExchangeScheme() sage: K.parameters() Traceback (most recent call last): From e11ad4e603348c710f079e8d89cd1b3fe6c51519 Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 30 Jul 2024 13:13:39 -0600 Subject: [PATCH 27/29] Doc formatting and date update --- src/sage/crypto/key_exchange/diffie_hellman.py | 2 +- src/sage/crypto/key_exchange/key_exchange_scheme.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 22ead8fbb4b..9131bd911b5 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -6,7 +6,7 @@ AUTHORS: -- Vincent Macri (2024-07-17): initial version +- Vincent Macri (2024-07-30): initial version """ # **************************************************************************** # Copyright (C) 2024 Vincent Macri diff --git a/src/sage/crypto/key_exchange/key_exchange_scheme.py b/src/sage/crypto/key_exchange/key_exchange_scheme.py index 575f091c49b..d2ce3d7fa64 100644 --- a/src/sage/crypto/key_exchange/key_exchange_scheme.py +++ b/src/sage/crypto/key_exchange/key_exchange_scheme.py @@ -1,5 +1,5 @@ r""" -Key exchange schemes. +Key Exchange Scheme This module contains base classes for key exchange schemes. The classes defined in this module should not be called directly. It is the responsibility of child @@ -8,7 +8,7 @@ AUTHORS: -- Vincent Macri (2024-07-17): initial version +- Vincent Macri (2024-07-30): initial version """ # **************************************************************************** # Copyright (C) 2024 Vincent Macri From 5726da833fb7fd854e5833dfd4a40701608cb29d Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 30 Jul 2024 14:15:27 -0600 Subject: [PATCH 28/29] Formatting consistency --- src/sage/crypto/key_exchange/key_exchange_scheme.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/crypto/key_exchange/key_exchange_scheme.py b/src/sage/crypto/key_exchange/key_exchange_scheme.py index d2ce3d7fa64..ff250357eb1 100644 --- a/src/sage/crypto/key_exchange/key_exchange_scheme.py +++ b/src/sage/crypto/key_exchange/key_exchange_scheme.py @@ -1,5 +1,5 @@ r""" -Key Exchange Scheme +Key Exchange Schemes This module contains base classes for key exchange schemes. The classes defined in this module should not be called directly. It is the responsibility of child From fc1a4dca0c7f3e52138359f2249f85d946fc5e9e Mon Sep 17 00:00:00 2001 From: Vincent Macri Date: Tue, 30 Jul 2024 15:18:28 -0600 Subject: [PATCH 29/29] Use catalog file --- src/doc/en/reference/cryptography/index.rst | 1 + src/sage/crypto/all.py | 2 +- src/sage/crypto/key_exchange/all.py | 1 + src/sage/crypto/key_exchange/catalog.py | 23 ++++++++++ .../crypto/key_exchange/diffie_hellman.py | 44 +++++++++---------- 5 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 src/sage/crypto/key_exchange/catalog.py diff --git a/src/doc/en/reference/cryptography/index.rst b/src/doc/en/reference/cryptography/index.rst index ef71153fc17..8ab26473b5a 100644 --- a/src/doc/en/reference/cryptography/index.rst +++ b/src/doc/en/reference/cryptography/index.rst @@ -34,6 +34,7 @@ Cryptography sage/crypto/lattice sage/crypto/lwe + sage/crypto/key_exchange/catalog sage/crypto/key_exchange/key_exchange_scheme sage/crypto/key_exchange/diffie_hellman diff --git a/src/sage/crypto/all.py b/src/sage/crypto/all.py index 0ca12243e8d..cd6fd8cc95e 100644 --- a/src/sage/crypto/all.py +++ b/src/sage/crypto/all.py @@ -22,6 +22,6 @@ ]) -from sage.crypto.key_exchange.all import * +import sage.crypto.key_exchange.catalog as key_exchange del lazy_import diff --git a/src/sage/crypto/key_exchange/all.py b/src/sage/crypto/key_exchange/all.py index 5ca055c786c..820638a048f 100644 --- a/src/sage/crypto/key_exchange/all.py +++ b/src/sage/crypto/key_exchange/all.py @@ -1,5 +1,6 @@ from sage.misc.lazy_import import lazy_import lazy_import('sage.crypto.key_exchange.diffie_hellman', 'DiffieHellman') +lazy_import('sage.crypto.key_exchange.key_exchange_scheme', 'KeyExchangeScheme') del lazy_import diff --git a/src/sage/crypto/key_exchange/catalog.py b/src/sage/crypto/key_exchange/catalog.py new file mode 100644 index 00000000000..aa105371015 --- /dev/null +++ b/src/sage/crypto/key_exchange/catalog.py @@ -0,0 +1,23 @@ +""" +Index of key exchange schemes + +This catalogue includes implementations of key exchange schemes. + +Let ```` indicate pressing the :kbd:`Tab` key. So begin by typing +``key_exchange.`` to the see the currently implemented key exchange +schemes. + +This catalogue includes the following key exchange schemes: + +- :class:`sage.crypto.key_exchange.diffie_hellman.DiffieHellman` + +To import these names into the global namespace, use:: + + sage: from sage.crypto.key_exchange.catalog import * +""" + +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.crypto.key_exchange.diffie_hellman', 'DiffieHellman') + +del lazy_import diff --git a/src/sage/crypto/key_exchange/diffie_hellman.py b/src/sage/crypto/key_exchange/diffie_hellman.py index 9131bd911b5..bdd25affe3b 100644 --- a/src/sage/crypto/key_exchange/diffie_hellman.py +++ b/src/sage/crypto/key_exchange/diffie_hellman.py @@ -68,7 +68,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], EXAMPLES:: - sage: DH = DiffieHellman(13, 2) + 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. @@ -77,7 +77,7 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], (see [KK2003]_):: sage: p = 2^8192 - 2^8128 - 1 + 2^64 * (round(2^8062 * pi) + 4743158) - sage: DH = DiffieHellman(p, 2, proof=False) + 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() @@ -89,22 +89,22 @@ def __init__(self, p: Integer, g: Union[Integer, IntegerMod_abstract], TESTS:: - sage: DH = DiffieHellman(3, 2) + sage: DH = key_exchange.DiffieHellman(3, 2) Traceback (most recent call last): ... ValueError: p must be at least 5 - sage: DH = DiffieHellman(5, 0) + sage: DH = key_exchange.DiffieHellman(5, 0) Traceback (most recent call last): ... ValueError: g cannot be 0, 1, or p - 1 (mod p) - sage: DH = DiffieHellman(5, 1) + sage: DH = key_exchange.DiffieHellman(5, 1) Traceback (most recent call last): ... ValueError: g cannot be 0, 1, or p - 1 (mod p) - sage: DH = DiffieHellman(5, 4) + sage: DH = key_exchange.DiffieHellman(5, 4) Traceback (most recent call last): ... ValueError: g cannot be 0, 1, or p - 1 (mod p) @@ -137,7 +137,7 @@ def field(self) -> FiniteField_prime_modn: EXAMPLES:: - sage: DH = DiffieHellman(5, 2) + sage: DH = key_exchange.DiffieHellman(5, 2) sage: DH.field() Finite Field of size 5 """ @@ -149,7 +149,7 @@ def prime(self) -> Integer: EXAMPLES:: - sage: DH = DiffieHellman(7, 3) + sage: DH = key_exchange.DiffieHellman(7, 3) sage: DH.prime() 7 """ @@ -161,7 +161,7 @@ def generator(self) -> IntegerMod_abstract: EXAMPLES:: - sage: DH = DiffieHellman(7, 3) + sage: DH = key_exchange.DiffieHellman(7, 3) sage: DH.generator() 3 """ @@ -173,7 +173,7 @@ def parameters(self) -> tuple[Integer, IntegerMod_abstract]: EXAMPLES:: - sage: DH = DiffieHellman(7, 3) + sage: DH = key_exchange.DiffieHellman(7, 3) sage: DH.parameters() (7, 3) """ @@ -185,7 +185,7 @@ def generate_secret_key(self) -> Integer: TESTS: - sage: DH = DiffieHellman(7, 2) + sage: DH = key_exchange.DiffieHellman(7, 2) sage: keys = [DH.generate_secret_key() for i in range(10)] sage: all(2 <= i <= 5 for i in keys) True @@ -202,7 +202,7 @@ def generate_public_key(self, secret_key: Integer) -> IntegerMod_abstract: EXAMPLES:: - sage: DH = DiffieHellman(13, 2) + sage: DH = key_exchange.DiffieHellman(13, 2) sage: DH.generate_public_key(4) 3 """ @@ -221,7 +221,7 @@ def compute_shared_secret(self, pk: IntegerMod_abstract, EXAMPLES:: - sage: DH = DiffieHellman(17, 3) + sage: DH = key_exchange.DiffieHellman(17, 3) sage: DH.compute_shared_secret(13, 11) 4 """ @@ -237,14 +237,14 @@ def subgroup_size(self) -> Integer: This is an example of a ``DiffieHellman`` instance where the subgroup size is `(p - 1) / 2`:: - sage: DH = DiffieHellman(47, 2) + sage: DH = key_exchange.DiffieHellman(47, 2) sage: DH.subgroup_size() 23 This is an example of a ``DiffieHellman`` instance where the subgroup size is `p - 1`:: - sage: DH = DiffieHellman(47, 5) + sage: DH = key_exchange.DiffieHellman(47, 5) sage: DH.subgroup_size() 46 """ @@ -257,7 +257,7 @@ def __len__(self) -> int: TESTS:: - sage: DH = DiffieHellman(53, 9) + sage: DH = key_exchange.DiffieHellman(53, 9) sage: len(DH) 26 """ @@ -269,8 +269,8 @@ def __eq__(self, other) -> bool: TESTS:: - sage: DH1 = DiffieHellman(5, 2) - sage: DH2 = DiffieHellman(5, 2) + sage: DH1 = key_exchange.DiffieHellman(5, 2) + sage: DH2 = key_exchange.DiffieHellman(5, 2) sage: DH1 == DH2 True sage: DH1 == 5 @@ -286,8 +286,8 @@ def __hash__(self) -> int: TESTS:: - sage: DH1 = DiffieHellman(7, 3) - sage: DH2 = DiffieHellman(7, 3) + sage: DH1 = key_exchange.DiffieHellman(7, 3) + sage: DH2 = key_exchange.DiffieHellman(7, 3) sage: s = set([DH1, DH2]) sage: len(s) 1 @@ -300,7 +300,7 @@ def _repr_(self) -> str: TESTS:: - sage: DH = DiffieHellman(7, 3) + sage: DH = key_exchange.DiffieHellman(7, 3) sage: DH Diffie-Hellman key exchange over Finite Field of size 7 with generator 3 """ @@ -315,7 +315,7 @@ def _latex_(self) -> str: TESTS:: - sage: DH = DiffieHellman(7, 3) + sage: DH = key_exchange.DiffieHellman(7, 3) sage: latex(DH) \text{Diffie-Hellman key exchange over }\Bold{F}_{7}\text{ with generator }3 """