45 lines
1.7 KiB
Python
45 lines
1.7 KiB
Python
|
|
from secrets import randbelow, randbits
|
||
|
|
from core.prime_utils import is_prime
|
||
|
|
|
||
|
|
|
||
|
|
class ParamGenerator:
|
||
|
|
"""
|
||
|
|
Генератор параметров протокола Диффи–Хеллмана.
|
||
|
|
Возвращает тройку (p, q, g):
|
||
|
|
- p = 2*q + 1, где p и q простые
|
||
|
|
- g — корректный генератор для группы по модулю p
|
||
|
|
"""
|
||
|
|
|
||
|
|
@staticmethod
|
||
|
|
def generate() -> tuple[int, int, int]:
|
||
|
|
"""
|
||
|
|
Случайным образом выбирает размерность (кол-во бит) для q,
|
||
|
|
подбирает безопасное простое p и генератор g.
|
||
|
|
Возвращает (p, q, g).
|
||
|
|
"""
|
||
|
|
# Размер числа выбираем случайно от 8 до 16 бит (от 256 до 65 535)
|
||
|
|
bits = 8 + randbelow(9)
|
||
|
|
|
||
|
|
# Генерация безопасного простого
|
||
|
|
while True:
|
||
|
|
q = randbits(bits - 1) | 1 # нечётное число
|
||
|
|
if not is_prime(q):
|
||
|
|
continue
|
||
|
|
p = 2 * q + 1
|
||
|
|
if not is_prime(p):
|
||
|
|
continue
|
||
|
|
# Найдём генератор
|
||
|
|
g = ParamGenerator._find_generator(p, q)
|
||
|
|
return p, q, g
|
||
|
|
|
||
|
|
@staticmethod
|
||
|
|
def _find_generator(p: int, q: int) -> int:
|
||
|
|
"""
|
||
|
|
Ищет генератор g: минимальное число 2..p-2,
|
||
|
|
для которого g^q mod p != 1.
|
||
|
|
"""
|
||
|
|
for g in range(2, p - 1):
|
||
|
|
if pow(g, q, p) != 1:
|
||
|
|
return g
|
||
|
|
raise ValueError("Не удалось найти генератор для p")
|