Initial commit
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict, Any
|
||||
|
||||
from modes.keygen import KeygenMode
|
||||
from modes.encrypt import EncryptMode
|
||||
from modes.decrypt import DecryptMode
|
||||
|
||||
|
||||
class AutoMode:
|
||||
"""
|
||||
Автоматический режим:
|
||||
1. Генерация ключей (p, q, n, e, d, phi).
|
||||
2. Шифрование текста или числа.
|
||||
3. Расшифрование результата обратно.
|
||||
"""
|
||||
|
||||
def run(
|
||||
self,
|
||||
*,
|
||||
text: str | None,
|
||||
m: int | None,
|
||||
p: int | None = None,
|
||||
q: int | None = None,
|
||||
min: int | None = None,
|
||||
max: int | None = None,
|
||||
bits: int | None = None,
|
||||
seed: int | None = None,
|
||||
) -> Dict[str, Any]:
|
||||
# 1. Генерация ключей
|
||||
keygen = KeygenMode()
|
||||
keys = keygen.run(
|
||||
p=p,
|
||||
q=q,
|
||||
min=min,
|
||||
max=max,
|
||||
bits=bits,
|
||||
seed=seed,
|
||||
)
|
||||
|
||||
n = keys["n"]["dec"]
|
||||
e = keys["e"]["dec"]
|
||||
d = keys["d"]["dec"]
|
||||
|
||||
# 2. Шифрование
|
||||
encrypt = EncryptMode()
|
||||
encrypted = encrypt.run(
|
||||
text=text,
|
||||
m=m,
|
||||
n=n,
|
||||
e=e,
|
||||
)
|
||||
|
||||
# 3. Расшифрование
|
||||
decrypt = DecryptMode()
|
||||
# В зависимости от формата encrypted["output"]
|
||||
if encrypted["mode"] == "text":
|
||||
ciphers = [item["cipher"] for item in encrypted["output"]]
|
||||
decrypted = decrypt.run(c=ciphers, n=n, d=d)
|
||||
else:
|
||||
cipher = encrypted["output"]["cipher"]
|
||||
decrypted = decrypt.run(c=cipher, n=n, d=d)
|
||||
|
||||
return {
|
||||
"keys": keys,
|
||||
"encrypted": encrypted,
|
||||
"decrypted": decrypted,
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
# modes/decrypt.py
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict, Any, List
|
||||
|
||||
|
||||
class DecryptMode:
|
||||
def run(
|
||||
self,
|
||||
*,
|
||||
c: int | List[int],
|
||||
n: int,
|
||||
d: int,
|
||||
) -> Dict[str, Any]:
|
||||
# Один блок
|
||||
if isinstance(c, int):
|
||||
plain = pow(c, d, n) # Дешифратор
|
||||
char = chr(plain) if 0 <= plain < 128 else None
|
||||
return {
|
||||
"mode": "int",
|
||||
"input": {
|
||||
"cipher": c,
|
||||
"hex_in": hex(c),
|
||||
},
|
||||
"output": {
|
||||
"ascii": plain,
|
||||
"char": char,
|
||||
"hex_out": hex(plain),
|
||||
},
|
||||
}
|
||||
|
||||
# Несколько блоков (список чисел)
|
||||
if isinstance(c, list):
|
||||
result: List[Dict[str, Any]] = []
|
||||
text = ""
|
||||
for block in c:
|
||||
plain = pow(block, d, n) # Дешифратор
|
||||
char = chr(plain) if 0 <= plain < 128 else None
|
||||
if char:
|
||||
text += char
|
||||
result.append({
|
||||
"cipher": block,
|
||||
"hex_in": hex(block),
|
||||
"ascii": plain,
|
||||
"char": char,
|
||||
"hex_out": hex(plain),
|
||||
})
|
||||
return {
|
||||
"mode": "list",
|
||||
"input": c,
|
||||
"output": result,
|
||||
"text": text,
|
||||
}
|
||||
|
||||
raise ValueError("c должен быть числом или списком чисел")
|
||||
@@ -0,0 +1,57 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict, Any, List
|
||||
|
||||
from core.public_key import PublicKey
|
||||
|
||||
from core.prime_number import PrimeNumber
|
||||
|
||||
|
||||
class EncryptMode:
|
||||
def run(
|
||||
self,
|
||||
*,
|
||||
text: str | None,
|
||||
m: int | None,
|
||||
n: int,
|
||||
e: int,
|
||||
) -> Dict[str, Any]:
|
||||
pub = PublicKey(n=n, e=PrimeNumber(e))
|
||||
|
||||
if text is not None:
|
||||
result: List[Dict[str, Any]] = []
|
||||
for ch in text:
|
||||
code = ord(ch)
|
||||
cipher = pub.encrypt(code)
|
||||
result.append({
|
||||
"char": ch,
|
||||
"ascii": code,
|
||||
"hex_in": hex(code),
|
||||
"cipher": cipher,
|
||||
"hex_out": hex(cipher),
|
||||
})
|
||||
return {
|
||||
"mode": "text",
|
||||
"input": text,
|
||||
"output": result,
|
||||
}
|
||||
|
||||
if m is not None:
|
||||
cipher = pub.encrypt(m)
|
||||
char = chr(m) if 0 <= m < 128 else None
|
||||
return {
|
||||
"mode": "int",
|
||||
"input": {
|
||||
"char": char,
|
||||
"ascii": m,
|
||||
"hex_in": hex(m),
|
||||
},
|
||||
"output": {
|
||||
"char": char,
|
||||
"ascii": m,
|
||||
"cipher": cipher,
|
||||
"hex_out": hex(cipher),
|
||||
},
|
||||
}
|
||||
|
||||
raise ValueError("Необходимо указать либо text, либо m")
|
||||
@@ -0,0 +1,133 @@
|
||||
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} попыток."
|
||||
)
|
||||
Reference in New Issue
Block a user