from __future__ import annotations from typing import Dict, Any from core.prime_number import PrimeNumber from core.private_key import PrivateKey class KeygenMode: MAX_BITS: int = 2**5 MIN_VALUE: int = 2 MAX_VALUE: int = (1 << MAX_BITS) - 1 MAX_ATTEMPTS: int = 1000 def run( self, *, p: int | None, q: int | None, min: int | None = None, max: int | None = None, bits: int | None = None, seed: int | None = None, ) -> Dict[str, Any]: if min is None: min = self.MIN_VALUE if max is None: max = self.MAX_VALUE self._validate_inputs(p, q, min, max, bits) P = self._generate_prime(p, min, max, bits, seed) Q = self._generate_distinct_prime(P, q, min, max, bits, seed) priv = PrivateKey(P, Q) pub = priv.make_public_key() return { "p": { "dec": P.value, "hex": hex(P.value), }, "q": { "dec": Q.value, "hex": hex(Q.value), }, "n": { "dec": priv.n, "hex": hex(priv.n), }, "phi": { "dec": priv.phi, "hex": hex(priv.phi), }, "e": { "dec": pub.e.value, "hex": hex(pub.e.value), }, "d": { "dec": priv.d, "hex": hex(priv.d), }, } # ----------------- helpers ----------------- def _validate_inputs( self, p: int | None, q: int | None, min: int, max: int, bits: int | None, ) -> None: if p is not None and q is not None and p == q: raise ValueError("p и q должны быть разными простыми числами.") if bits is not None and bits > self.MAX_BITS: raise ValueError(f"Максимальная длина простого: { self.MAX_BITS} бит.") if min > max: raise ValueError("min не может быть больше max.") if max > self.MAX_VALUE: raise ValueError( f"max не может превышать {self.MAX_VALUE} (ограничение { self.MAX_BITS} бит)." ) if min == max: raise ValueError("min и max не должны совпадать.") def _generate_prime( self, value: int | None, min: int, max: int, bits: int | None, seed: int | None, ) -> PrimeNumber: if value is not None: return PrimeNumber.from_value(value) if bits is not None: return PrimeNumber.random_bits(bits=bits, seed=seed) else: return PrimeNumber.random(min_value=min, max_value=max, seed=seed) return PrimeNumber.random_bits(bits=self.MAX_BITS, seed=seed) def _generate_distinct_prime( self, other: PrimeNumber, value: int | None, min: int, max: int, bits: int | None, seed: int | None, ) -> PrimeNumber: attempts = 0 while True: effective_seed = None if seed is None else seed + attempts candidate = self._generate_prime( value, min, max, bits, effective_seed) if candidate.value != other.value: return candidate attempts += 1 if attempts >= self.MAX_ATTEMPTS: raise RuntimeError( f"Не удалось сгенерировать q, отличное от p, за { self.MAX_ATTEMPTS} попыток." )