-
-
Notifications
You must be signed in to change notification settings - Fork 767
Add framework for key exchange schemes and Diffie-Hellman #38374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
62787b2
0b2d8ab
2655712
73bffc6
c183db2
cc513e7
5ee6d0a
4cb006f
16d3d98
f0a8ea0
bacebe9
b12addd
6f7b5e2
f7b0744
6b86174
a97866a
babeb3c
dd098a1
42159fc
6ab21e9
6298553
7801f9d
7790037
f5491a2
f74d913
474e09d
441fdfc
d58532b
cdb0962
e11ad4e
5726da8
fc1a4dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| from sage.misc.lazy_import import lazy_import | ||
|
|
||
| lazy_import('sage.crypto.key_exchange.diffie_hellman', 'DiffieHellman') | ||
| del lazy_import | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Didn't think of this before, but seems like a good idea!
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just copied from the I'm now thinking I may have done this wrong (and maybe
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was doing it wrong. After the commit I just pushed, This does raise the question of how we want the schemes to be accessed by the user. Most people probably won't use this feature (although I guess that applies to most things in Sage) so maybe it makes sense to access it as something like Happy to change it to something like
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now I have it so
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For my PR of a similar nature, I created a
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think having
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's less questionable than I don't think it's too different than how After writing that I've convinced myself that it should be changed to And the reason I didn't consider putting it under
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think
Lol, it happens :)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, I realized that making it accessible under For now I think it's fine to leave it as
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay if it's too much irrelevant stuff for this PR then it's okay to leave it (and optionally make a new issue that hopefully someone gets to.) |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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. | ||
vincentmacri marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| AUTHORS: | ||
|
|
||
| - Vincent Macri (2024-07-15): initial version | ||
| """ | ||
| # **************************************************************************** | ||
| # Copyright (C) 2024 Vincent Macri <[email protected]> | ||
| # | ||
| # 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) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment on |
||
| 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` | ||
vincentmacri marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| .. 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 | ||
vincentmacri marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| security is needed! | ||
|
|
||
| REFERENCES: | ||
|
|
||
| For more information, see [PP2010]_, section 8.1. | ||
vincentmacri marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| 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. | ||
vincentmacri marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # 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}' | ||
vincentmacri marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def _latex_(self): | ||
| return f'\\text{{Diffie-Hellman key exchange over }}{self._field}\\text{{ with generator }}{self._g}' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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-15): initial version | ||
| """ | ||
| # **************************************************************************** | ||
| # Copyright (C) 2024 Vincent Macri <[email protected]> | ||
| # | ||
| # 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 | ||
Uh oh!
There was an error while loading. Please reload this page.