105 lines
4.1 KiB
Python
105 lines
4.1 KiB
Python
|
|
from argparse import ArgumentParser, RawDescriptionHelpFormatter
|
||
|
|
|
||
|
|
|
||
|
|
def _int_auto(x: str) -> int:
|
||
|
|
return int(x, 0)
|
||
|
|
|
||
|
|
|
||
|
|
def parse_args(argv=None):
|
||
|
|
ap = ArgumentParser(
|
||
|
|
description=(
|
||
|
|
"RSA Algorithm CLI with refactored argument handling.\n\n"
|
||
|
|
"Examples:\n"
|
||
|
|
" app.py keygen --bits 8\n"
|
||
|
|
" app.py encrypt --text \"RSA\" --e 17 --n 0xca1\n"
|
||
|
|
" app.py decrypt --c 0x357 --n 0xca1 --d 0xac1\n"
|
||
|
|
" app.py auto --text \"RSA\" --bits 8\n"
|
||
|
|
" app.py auto --m 65 --min 100 --max 1000\n"
|
||
|
|
),
|
||
|
|
formatter_class=RawDescriptionHelpFormatter,
|
||
|
|
)
|
||
|
|
|
||
|
|
sub = ap.add_subparsers(dest="cmd", required=True)
|
||
|
|
|
||
|
|
# -------- parents to deduplicate args --------
|
||
|
|
# Общие параметры генерации ключей (используются в keygen и auto)
|
||
|
|
parent_keygen = ArgumentParser(add_help=False)
|
||
|
|
parent_keygen.add_argument("--p", type=_int_auto, help="Простое число p.")
|
||
|
|
parent_keygen.add_argument("--q", type=_int_auto, help="Простое число q.")
|
||
|
|
parent_keygen.add_argument(
|
||
|
|
"--min",
|
||
|
|
type=int,
|
||
|
|
default=2,
|
||
|
|
help="Нижняя граница поиска простых (при случайной генерации диапазоном).",
|
||
|
|
)
|
||
|
|
parent_keygen.add_argument(
|
||
|
|
"--max",
|
||
|
|
type=int,
|
||
|
|
help="Верхняя граница поиска простых (при случайной генерации диапазоном).",
|
||
|
|
)
|
||
|
|
parent_keygen.add_argument(
|
||
|
|
"--bits",
|
||
|
|
type=int,
|
||
|
|
help="Количество бит для случайной генерации простых (альтернатива min/max).",
|
||
|
|
)
|
||
|
|
parent_keygen.add_argument(
|
||
|
|
"--seed", type=int, help="Seed для ГСЧ (опционально, для воспроизводимости)."
|
||
|
|
)
|
||
|
|
|
||
|
|
# Общий модуль n (используется в encrypt и decrypt)
|
||
|
|
parent_n = ArgumentParser(add_help=False)
|
||
|
|
parent_n.add_argument("--n", type=_int_auto,
|
||
|
|
required=True, help="Модуль n.")
|
||
|
|
|
||
|
|
# Общий ввод открытого сообщения (используется в encrypt и auto)
|
||
|
|
parent_plain = ArgumentParser(add_help=False)
|
||
|
|
plain_group = parent_plain.add_mutually_exclusive_group(required=True)
|
||
|
|
plain_group.add_argument(
|
||
|
|
"--text", type=str, help="Открытый текст (ASCII).")
|
||
|
|
plain_group.add_argument(
|
||
|
|
"--m", type=_int_auto, help="Открытое сообщение как неотрицательное целое."
|
||
|
|
)
|
||
|
|
|
||
|
|
# -------- keygen --------
|
||
|
|
sub.add_parser(
|
||
|
|
"keygen",
|
||
|
|
help="Сгенерировать приватный (p, q, d, n) и публичный (e, n) ключи.",
|
||
|
|
formatter_class=RawDescriptionHelpFormatter,
|
||
|
|
parents=[parent_keygen],
|
||
|
|
)
|
||
|
|
|
||
|
|
# -------- encrypt --------
|
||
|
|
sp_enc = sub.add_parser(
|
||
|
|
"encrypt",
|
||
|
|
help="Зашифровать сообщение публичным ключом (e, n).",
|
||
|
|
formatter_class=RawDescriptionHelpFormatter,
|
||
|
|
parents=[parent_n, parent_plain],
|
||
|
|
)
|
||
|
|
sp_enc.add_argument(
|
||
|
|
"--e", type=_int_auto, required=True, help="Публичная экспонента e (простое)."
|
||
|
|
)
|
||
|
|
|
||
|
|
# -------- decrypt --------
|
||
|
|
sp_dec = sub.add_parser(
|
||
|
|
"decrypt",
|
||
|
|
help="Расшифровать шифртекст приватным ключом (n, d).",
|
||
|
|
formatter_class=RawDescriptionHelpFormatter,
|
||
|
|
parents=[parent_n],
|
||
|
|
)
|
||
|
|
sp_dec.add_argument(
|
||
|
|
"--c", type=_int_auto, required=True, help="Шифртекст как неотрицательное целое."
|
||
|
|
)
|
||
|
|
sp_dec.add_argument(
|
||
|
|
"--d", type=_int_auto, required=True, help="Приватная экспонента d."
|
||
|
|
)
|
||
|
|
|
||
|
|
# -------- auto --------
|
||
|
|
sub.add_parser(
|
||
|
|
"auto",
|
||
|
|
help="Автоматический режим: как keygen + обязательный ввод сообщения.",
|
||
|
|
formatter_class=RawDescriptionHelpFormatter,
|
||
|
|
parents=[parent_keygen, parent_plain],
|
||
|
|
)
|
||
|
|
|
||
|
|
return ap.parse_args(argv)
|