Files
2026-07-12 14:06:45 +04:00

134 lines
3.8 KiB
Python

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} попыток."
)