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)