transcrypto 1.2.0__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- transcrypto/aes.py +10 -2
- transcrypto/base.py +708 -100
- transcrypto/constants.py +1921 -0
- transcrypto/dsa.py +106 -49
- transcrypto/elgamal.py +14 -13
- transcrypto/modmath.py +108 -43
- transcrypto/profiler.py +191 -0
- transcrypto/rsa.py +17 -17
- transcrypto/safetrans.py +1231 -0
- transcrypto/sss.py +1 -3
- transcrypto/transcrypto.py +55 -206
- transcrypto-1.4.0.dist-info/METADATA +1071 -0
- transcrypto-1.4.0.dist-info/RECORD +18 -0
- transcrypto-1.2.0.dist-info/METADATA +0 -2515
- transcrypto-1.2.0.dist-info/RECORD +0 -15
- {transcrypto-1.2.0.dist-info → transcrypto-1.4.0.dist-info}/WHEEL +0 -0
- {transcrypto-1.2.0.dist-info → transcrypto-1.4.0.dist-info}/licenses/LICENSE +0 -0
- {transcrypto-1.2.0.dist-info → transcrypto-1.4.0.dist-info}/top_level.txt +0 -0
transcrypto/sss.py
CHANGED
|
@@ -314,9 +314,7 @@ class ShamirSharedSecretPrivate(ShamirSharedSecretPublic):
|
|
|
314
314
|
if bit_length < 10:
|
|
315
315
|
raise base.InputError(f'invalid bit length: {bit_length=}')
|
|
316
316
|
# make the primes
|
|
317
|
-
unique_primes: set[int] =
|
|
318
|
-
while len(unique_primes) < minimum_shares:
|
|
319
|
-
unique_primes.add(modmath.NBitRandomPrime(bit_length))
|
|
317
|
+
unique_primes: set[int] = modmath.NBitRandomPrimes(bit_length, n_primes=minimum_shares)
|
|
320
318
|
# get the largest prime for the modulus
|
|
321
319
|
ordered_primes: list[int] = list(unique_primes)
|
|
322
320
|
modulus: int = max(ordered_primes)
|
transcrypto/transcrypto.py
CHANGED
|
@@ -10,13 +10,15 @@ Notes on the layout (quick mental model):
|
|
|
10
10
|
|
|
11
11
|
isprime, primegen, mersenne
|
|
12
12
|
gcd, xgcd, and grouped mod inv|div|exp|poly|lagrange|crt
|
|
13
|
-
random bits|int|bytes|prime
|
|
13
|
+
random bits|int|bytes|prime
|
|
14
|
+
hash sha256|sha512|file
|
|
14
15
|
aes key frompass, aes encrypt|decrypt (GCM), aes ecb encrypt|decrypt
|
|
15
16
|
rsa new|encrypt|decrypt|sign|verify|rawencrypt|rawdecrypt|rawsign|rawverify
|
|
16
17
|
elgamal shared|new|encrypt|decrypt|sign|verify|rawencrypt|rawdecrypt|rawsign|rawverify
|
|
17
18
|
dsa shared|new|sign|verify|rawsign|rawverify
|
|
18
19
|
bid new|verify
|
|
19
20
|
sss new|shares|recover|rawshares|rawrecover|rawverify
|
|
21
|
+
doc md
|
|
20
22
|
"""
|
|
21
23
|
|
|
22
24
|
from __future__ import annotations
|
|
@@ -27,7 +29,7 @@ import glob
|
|
|
27
29
|
import logging
|
|
28
30
|
# import pdb
|
|
29
31
|
import sys
|
|
30
|
-
from typing import Any, Iterable
|
|
32
|
+
from typing import Any, Iterable
|
|
31
33
|
|
|
32
34
|
from . import base, modmath, rsa, sss, elgamal, dsa, aes
|
|
33
35
|
|
|
@@ -119,179 +121,6 @@ def _LoadObj(path: str, password: str | None, expect: type, /) -> Any:
|
|
|
119
121
|
return obj
|
|
120
122
|
|
|
121
123
|
|
|
122
|
-
def _FlagNames(a: argparse.Action, /) -> list[str]:
|
|
123
|
-
# Positional args have empty 'option_strings'; otherwise use them (e.g., ['-v','--verbose'])
|
|
124
|
-
if a.option_strings:
|
|
125
|
-
return list(a.option_strings)
|
|
126
|
-
if a.nargs:
|
|
127
|
-
if isinstance(a.metavar, str) and a.metavar:
|
|
128
|
-
# e.g., nargs=2, metavar='FILE'
|
|
129
|
-
return [a.metavar]
|
|
130
|
-
if isinstance(a.metavar, tuple):
|
|
131
|
-
# e.g., nargs=2, metavar=('FILE1', 'FILE2')
|
|
132
|
-
return list(a.metavar)
|
|
133
|
-
# Otherwise, it’s a positional arg with no flags, so return the destination name
|
|
134
|
-
return [a.dest]
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
def _ActionIsSubparser(a: argparse.Action, /) -> bool:
|
|
138
|
-
return isinstance(a, argparse._SubParsersAction) # type: ignore[attr-defined] # pylint: disable=protected-access
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def _FormatDefault(a: argparse.Action, /) -> str:
|
|
142
|
-
if a.default is argparse.SUPPRESS:
|
|
143
|
-
return ''
|
|
144
|
-
if isinstance(a.default, bool):
|
|
145
|
-
return ' (default: on)' if a.default else ''
|
|
146
|
-
if a.default in (None, '', 0, False):
|
|
147
|
-
return ''
|
|
148
|
-
return f' (default: {a.default})'
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
def _FormatChoices(a: argparse.Action, /) -> str:
|
|
152
|
-
return f' choices: {list(a.choices)}' if getattr(a, 'choices', None) else '' # type:ignore
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
def _FormatType(a: argparse.Action, /) -> str:
|
|
156
|
-
t: Any | None = getattr(a, 'type', None)
|
|
157
|
-
if t is None:
|
|
158
|
-
return ''
|
|
159
|
-
# Show clean type names (int, str, float); for callables, just say 'custom'
|
|
160
|
-
return f' type: {t.__name__ if hasattr(t, "__name__") else "custom"}'
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
def _FormatNArgs(a: argparse.Action, /) -> str:
|
|
164
|
-
return f' nargs: {a.nargs}' if getattr(a, 'nargs', None) not in (None, 0) else ''
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
def _RowsForActions(actions: Sequence[argparse.Action], /) -> list[tuple[str, str]]:
|
|
168
|
-
rows: list[tuple[str, str]] = []
|
|
169
|
-
for a in actions:
|
|
170
|
-
if _ActionIsSubparser(a):
|
|
171
|
-
continue
|
|
172
|
-
# skip the built-in help action; it’s implied
|
|
173
|
-
if getattr(a, 'help', '') == argparse.SUPPRESS or isinstance(a, argparse._HelpAction): # type: ignore[attr-defined] # pylint: disable=protected-access
|
|
174
|
-
continue
|
|
175
|
-
flags: str = ', '.join(_FlagNames(a))
|
|
176
|
-
meta: str = ''.join(
|
|
177
|
-
(_FormatType(a), _FormatNArgs(a), _FormatChoices(a), _FormatDefault(a))).strip()
|
|
178
|
-
desc: str = (a.help or '').strip()
|
|
179
|
-
if meta:
|
|
180
|
-
desc = f'{desc} [{meta}]' if desc else f'[{meta}]'
|
|
181
|
-
rows.append((flags, desc))
|
|
182
|
-
return rows
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
def _MarkdownTable(
|
|
186
|
-
rows: Sequence[tuple[str, str]],
|
|
187
|
-
headers: tuple[str, str] = ('Option/Arg', 'Description'), /) -> str:
|
|
188
|
-
if not rows:
|
|
189
|
-
return ''
|
|
190
|
-
out: list[str] = ['| ' + headers[0] + ' | ' + headers[1] + ' |', '|---|---|']
|
|
191
|
-
for left, right in rows:
|
|
192
|
-
out.append(f'| `{left}` | {right} |')
|
|
193
|
-
return '\n'.join(out)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
def _WalkSubcommands(
|
|
197
|
-
parser: argparse.ArgumentParser, path: list[str] | None = None, /) -> list[
|
|
198
|
-
tuple[list[str], argparse.ArgumentParser, Any]]:
|
|
199
|
-
path = path or []
|
|
200
|
-
items: list[tuple[list[str], argparse.ArgumentParser, Any]] = []
|
|
201
|
-
# sub_action = None
|
|
202
|
-
name: str
|
|
203
|
-
sp: argparse.ArgumentParser
|
|
204
|
-
for action in parser._actions: # type: ignore[attr-defined] # pylint: disable=protected-access
|
|
205
|
-
if _ActionIsSubparser(action):
|
|
206
|
-
# sub_action = a # type: ignore[assignment]
|
|
207
|
-
for name, sp in action.choices.items(): # type:ignore
|
|
208
|
-
items.append((path + [name], sp, action)) # type:ignore
|
|
209
|
-
items.extend(_WalkSubcommands(sp, path + [name])) # type:ignore
|
|
210
|
-
return items
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
def _HelpText(sub_parser: argparse.ArgumentParser, parent_sub_action: Any, /) -> str:
|
|
214
|
-
if parent_sub_action is not None:
|
|
215
|
-
for choice_action in parent_sub_action._choices_actions: # type: ignore # pylint: disable=protected-access
|
|
216
|
-
if choice_action.dest == sub_parser.prog.split()[-1]:
|
|
217
|
-
return choice_action.help or ''
|
|
218
|
-
return ''
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
def _GenerateCLIMarkdown() -> str: # pylint: disable=too-many-locals
|
|
222
|
-
"""Return a Markdown doc section that reflects the current _BuildParser() tree.
|
|
223
|
-
|
|
224
|
-
Will treat epilog strings as examples, splitting on '$$' to get multiple examples.
|
|
225
|
-
"""
|
|
226
|
-
parser: argparse.ArgumentParser = _BuildParser()
|
|
227
|
-
assert parser.prog == 'poetry run transcrypto', 'should never happen: module name changed?'
|
|
228
|
-
prog: str = 'transcrypto' # no '.py' needed because poetry run has an alias
|
|
229
|
-
lines: list[str] = ['']
|
|
230
|
-
# Header + global flags
|
|
231
|
-
lines.append('## Command-Line Interface\n')
|
|
232
|
-
lines.append(
|
|
233
|
-
f'`{prog}` is a command-line utility that provides access to all core functionality '
|
|
234
|
-
'described in this documentation. It serves as a convenient wrapper over the Python APIs, '
|
|
235
|
-
'enabling **cryptographic operations**, **number theory functions**, **secure randomness '
|
|
236
|
-
'generation**, **hashing**, **AES**, **RSA**, **El-Gamal**, **DSA**, **bidding**, **SSS**, '
|
|
237
|
-
'and other utilities without writing code.\n')
|
|
238
|
-
lines.append('Invoke with:\n')
|
|
239
|
-
lines.append('```bash')
|
|
240
|
-
lines.append(f'poetry run {prog} <command> [sub-command] [options...]')
|
|
241
|
-
lines.append('```\n')
|
|
242
|
-
# Global options table
|
|
243
|
-
global_rows: list[tuple[str, str]] = _RowsForActions(parser._actions) # type: ignore[attr-defined] # pylint: disable=protected-access
|
|
244
|
-
if global_rows:
|
|
245
|
-
lines.append('### Global Options\n')
|
|
246
|
-
lines.append(_MarkdownTable(global_rows))
|
|
247
|
-
lines.append('')
|
|
248
|
-
# Top-level commands summary
|
|
249
|
-
lines.append('### Top-Level Commands\n')
|
|
250
|
-
# Find top-level subparsers to list available commands
|
|
251
|
-
top_subs: list[argparse.Action] = [a for a in parser._actions if _ActionIsSubparser(a)] # type: ignore[attr-defined] # pylint: disable=protected-access
|
|
252
|
-
for action in top_subs:
|
|
253
|
-
for name, sp in action.choices.items(): # type: ignore[union-attr]
|
|
254
|
-
help_text: str = (sp.description or ' '.join(i.strip() for i in sp.format_usage().splitlines())).strip() # type:ignore
|
|
255
|
-
short: str = (sp.help if hasattr(sp, 'help') else '') or '' # type:ignore
|
|
256
|
-
help_text = short or help_text # type:ignore
|
|
257
|
-
help_text = help_text.replace('usage: ', '').strip() # type:ignore
|
|
258
|
-
lines.append(f'- **`{name}`** — `{help_text}`')
|
|
259
|
-
lines.append('')
|
|
260
|
-
if parser.epilog:
|
|
261
|
-
lines.append('```bash')
|
|
262
|
-
lines.append(parser.epilog)
|
|
263
|
-
lines.append('```\n')
|
|
264
|
-
# Detailed sections per (sub)command
|
|
265
|
-
for path, sub_parser, parent_sub_action in _WalkSubcommands(parser):
|
|
266
|
-
if len(path) == 1:
|
|
267
|
-
lines.append('---\n') # horizontal rule between top-level commands
|
|
268
|
-
header: str = ' '.join(path)
|
|
269
|
-
lines.append(f'###{"" if len(path) == 1 else "#"} `{header}`') # (header level 3 or 4)
|
|
270
|
-
# Usage block
|
|
271
|
-
help_text = _HelpText(sub_parser, parent_sub_action)
|
|
272
|
-
if help_text:
|
|
273
|
-
lines.append(f'\n{help_text}')
|
|
274
|
-
usage: str = sub_parser.format_usage().replace('usage: ', '').strip()
|
|
275
|
-
lines.append('\n```bash')
|
|
276
|
-
lines.append(str(usage))
|
|
277
|
-
lines.append('```\n')
|
|
278
|
-
# Options/args table
|
|
279
|
-
rows: list[tuple[str, str]] = _RowsForActions(sub_parser._actions) # type: ignore[attr-defined] # pylint: disable=protected-access
|
|
280
|
-
if rows:
|
|
281
|
-
lines.append(_MarkdownTable(rows))
|
|
282
|
-
lines.append('')
|
|
283
|
-
# Examples (if any) - stored in epilog argument
|
|
284
|
-
epilog: str = sub_parser.epilog.strip() if sub_parser.epilog else ''
|
|
285
|
-
if epilog:
|
|
286
|
-
lines.append('**Example:**\n')
|
|
287
|
-
lines.append('```bash')
|
|
288
|
-
for epilog_line in epilog.split('$$'):
|
|
289
|
-
lines.append(f'$ poetry run {prog} {epilog_line.strip()}')
|
|
290
|
-
lines.append('```\n')
|
|
291
|
-
# join all lines as the markdown string
|
|
292
|
-
return '\n'.join(lines)
|
|
293
|
-
|
|
294
|
-
|
|
295
124
|
def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-statements,too-many-locals
|
|
296
125
|
"""Construct the CLI argument parser (kept in sync with the docs)."""
|
|
297
126
|
# ========================= main parser ==========================================================
|
|
@@ -321,12 +150,12 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
321
150
|
' poetry run transcrypto mod crt 6 7 127 13\n\n'
|
|
322
151
|
' # --- Hashing ---\n'
|
|
323
152
|
' poetry run transcrypto hash sha256 xyz\n'
|
|
324
|
-
' poetry run transcrypto --b64 hash sha512 eHl6\n'
|
|
153
|
+
' poetry run transcrypto --b64 hash sha512 -- eHl6\n'
|
|
325
154
|
' poetry run transcrypto hash file /etc/passwd --digest sha512\n\n'
|
|
326
155
|
' # --- AES ---\n'
|
|
327
156
|
' poetry run transcrypto --out-b64 aes key "correct horse battery staple"\n'
|
|
328
|
-
' poetry run transcrypto --b64 --out-b64 aes encrypt -k "<b64key>" "secret"\n'
|
|
329
|
-
' poetry run transcrypto --b64 --out-b64 aes decrypt -k "<b64key>" "<ciphertext>"\n'
|
|
157
|
+
' poetry run transcrypto --b64 --out-b64 aes encrypt -k "<b64key>" -- "secret"\n'
|
|
158
|
+
' poetry run transcrypto --b64 --out-b64 aes decrypt -k "<b64key>" -- "<ciphertext>"\n'
|
|
330
159
|
' poetry run transcrypto aes ecb -k "<b64key>" encrypt "<128bithexblock>"\n' # cspell:disable-line
|
|
331
160
|
' poetry run transcrypto aes ecb -k "<b64key>" decrypt "<128bithexblock>"\n\n' # cspell:disable-line
|
|
332
161
|
' # --- RSA ---\n'
|
|
@@ -335,6 +164,10 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
335
164
|
' poetry run transcrypto -p rsa-key.priv rsa rawdecrypt <ciphertext>\n'
|
|
336
165
|
' poetry run transcrypto -p rsa-key.priv rsa rawsign <message>\n'
|
|
337
166
|
' poetry run transcrypto -p rsa-key.pub rsa rawverify <message> <signature>\n\n'
|
|
167
|
+
' poetry run transcrypto --bin --out-b64 -p rsa-key.pub rsa encrypt -a <aad> <plaintext>\n'
|
|
168
|
+
' poetry run transcrypto --b64 --out-bin -p rsa-key.priv rsa decrypt -a <aad> -- <ciphertext>\n'
|
|
169
|
+
' poetry run transcrypto --bin --out-b64 -p rsa-key.priv rsa sign <message>\n'
|
|
170
|
+
' poetry run transcrypto --b64 -p rsa-key.pub rsa verify -- <message> <signature>\n\n'
|
|
338
171
|
' # --- ElGamal ---\n'
|
|
339
172
|
' poetry run transcrypto -p eg-key elgamal shared --bits 2048\n'
|
|
340
173
|
' poetry run transcrypto -p eg-key elgamal new\n'
|
|
@@ -342,19 +175,27 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
342
175
|
' poetry run transcrypto -p eg-key.priv elgamal rawdecrypt <c1:c2>\n'
|
|
343
176
|
' poetry run transcrypto -p eg-key.priv elgamal rawsign <message>\n'
|
|
344
177
|
' poetry run transcrypto-p eg-key.pub elgamal rawverify <message> <s1:s2>\n\n'
|
|
178
|
+
' poetry run transcrypto --bin --out-b64 -p eg-key.pub elgamal encrypt <plaintext>\n'
|
|
179
|
+
' poetry run transcrypto --b64 --out-bin -p eg-key.priv elgamal decrypt -- <ciphertext>\n'
|
|
180
|
+
' poetry run transcrypto --bin --out-b64 -p eg-key.priv elgamal sign <message>\n'
|
|
181
|
+
' poetry run transcrypto --b64 -p eg-key.pub elgamal verify -- <message> <signature>\n\n'
|
|
345
182
|
' # --- DSA ---\n'
|
|
346
183
|
' poetry run transcrypto -p dsa-key dsa shared --p-bits 2048 --q-bits 256\n'
|
|
347
184
|
' poetry run transcrypto -p dsa-key dsa new\n'
|
|
348
185
|
' poetry run transcrypto -p dsa-key.priv dsa rawsign <message>\n'
|
|
349
186
|
' poetry run transcrypto -p dsa-key.pub dsa rawverify <message> <s1:s2>\n\n'
|
|
187
|
+
' poetry run transcrypto --bin --out-b64 -p dsa-key.priv dsa sign <message>\n'
|
|
188
|
+
' poetry run transcrypto --b64 -p dsa-key.pub dsa verify -- <message> <signature>\n\n'
|
|
350
189
|
' # --- Public Bid ---\n'
|
|
351
190
|
' poetry run transcrypto --bin bid new "tomorrow it will rain"\n'
|
|
352
191
|
' poetry run transcrypto --out-bin bid verify\n\n'
|
|
353
192
|
' # --- Shamir Secret Sharing (SSS) ---\n'
|
|
354
193
|
' poetry run transcrypto -p sss-key sss new 3 --bits 1024\n'
|
|
355
|
-
' poetry run transcrypto -p sss-key sss rawshares <secret>
|
|
194
|
+
' poetry run transcrypto -p sss-key sss rawshares <secret> <n>\n'
|
|
356
195
|
' poetry run transcrypto -p sss-key sss rawrecover\n'
|
|
357
196
|
' poetry run transcrypto -p sss-key sss rawverify <secret>'
|
|
197
|
+
' poetry run transcrypto --bin -p sss-key sss shares <secret> <n>\n'
|
|
198
|
+
' poetry run transcrypto --out-bin -p sss-key sss recover\n'
|
|
358
199
|
),
|
|
359
200
|
formatter_class=argparse.RawTextHelpFormatter)
|
|
360
201
|
sub = parser.add_subparsers(dest='command')
|
|
@@ -368,7 +209,10 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
368
209
|
# --hex/--b64/--bin for input mode (default hex)
|
|
369
210
|
in_grp = parser.add_mutually_exclusive_group()
|
|
370
211
|
in_grp.add_argument('--hex', action='store_true', help='Treat inputs as hex string (default)')
|
|
371
|
-
in_grp.add_argument(
|
|
212
|
+
in_grp.add_argument(
|
|
213
|
+
'--b64', action='store_true',
|
|
214
|
+
help=('Treat inputs as base64url; sometimes base64 will start with "-" and that can '
|
|
215
|
+
'conflict with flags, so use "--" before positional args if needed'))
|
|
372
216
|
in_grp.add_argument('--bin', action='store_true', help='Treat inputs as binary (bytes)')
|
|
373
217
|
|
|
374
218
|
# --out-hex/--out-b64/--out-bin for output mode (default hex)
|
|
@@ -557,7 +401,7 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
557
401
|
help='SHA-256 of input `data`.',
|
|
558
402
|
epilog=('--bin hash sha256 xyz\n'
|
|
559
403
|
'3608bca1e44ea6c4d268eb6db02260269892c0b42b86bbf1e77a6fa16c3c9282 $$'
|
|
560
|
-
'--b64 hash sha256 eHl6 # "xyz" in base-64\n'
|
|
404
|
+
'--b64 hash sha256 -- eHl6 # "xyz" in base-64\n'
|
|
561
405
|
'3608bca1e44ea6c4d268eb6db02260269892c0b42b86bbf1e77a6fa16c3c9282'))
|
|
562
406
|
p_h256.add_argument('data', type=str, help='Input data (raw text; or use --hex/--b64/--bin)')
|
|
563
407
|
|
|
@@ -568,7 +412,7 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
568
412
|
epilog=('--bin hash sha512 xyz\n'
|
|
569
413
|
'4a3ed8147e37876adc8f76328e5abcc1b470e6acfc18efea0135f983604953a5'
|
|
570
414
|
'8e183c1a6086e91ba3e821d926f5fdeb37761c7ca0328a963f5e92870675b728 $$'
|
|
571
|
-
'--b64 hash sha512 eHl6 # "xyz" in base-64\n'
|
|
415
|
+
'--b64 hash sha512 -- eHl6 # "xyz" in base-64\n'
|
|
572
416
|
'4a3ed8147e37876adc8f76328e5abcc1b470e6acfc18efea0135f983604953a5'
|
|
573
417
|
'8e183c1a6086e91ba3e821d926f5fdeb37761c7ca0328a963f5e92870675b728'))
|
|
574
418
|
p_h512.add_argument('data', type=str, help='Input data (raw text; or use --hex/--b64/--bin)')
|
|
@@ -614,10 +458,10 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
614
458
|
'can use `--bin`/`--hex`/`--b64` flags. Attention: if you provide `-a`/`--aad` '
|
|
615
459
|
'(associated data, AAD), you will need to provide the same AAD when decrypting '
|
|
616
460
|
'and it is NOT included in the `ciphertext`/CT returned by this method!'),
|
|
617
|
-
epilog=('--b64 --out-b64 aes encrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= '
|
|
461
|
+
epilog=('--b64 --out-b64 aes encrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -- ' # cspell:disable-line
|
|
618
462
|
'AAAAAAB4eXo=\nF2_ZLrUw5Y8oDnbTP5t5xCUWX8WtVILLD0teyUi_37_4KHeV-YowVA== $$ ' # cspell:disable-line
|
|
619
463
|
'--b64 --out-b64 aes encrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -a eHl6 ' # cspell:disable-line
|
|
620
|
-
'AAAAAAB4eXo=\nxOlAHPUPpeyZHId-f3VQ_QKKMxjIW0_FBo9WOfIBrzjn0VkVV6xTRA=='))
|
|
464
|
+
'-- AAAAAAB4eXo=\nxOlAHPUPpeyZHId-f3VQ_QKKMxjIW0_FBo9WOfIBrzjn0VkVV6xTRA==')) # cspell:disable-line
|
|
621
465
|
p_aes_enc.add_argument('plaintext', type=str, help='Input data to encrypt (PT)')
|
|
622
466
|
p_aes_enc.add_argument(
|
|
623
467
|
'-k', '--key', type=str, default='', help='Key if `-p`/`--key-path` wasn\'t used (32 bytes)')
|
|
@@ -632,10 +476,10 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
632
476
|
'`-p`/`--key-path` keyfile. All inputs are raw, or you '
|
|
633
477
|
'can use `--bin`/`--hex`/`--b64` flags. Attention: if you provided `-a`/`--aad` '
|
|
634
478
|
'(associated data, AAD) during encryption, you will need to provide the same AAD now!'),
|
|
635
|
-
epilog=('--b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= ' # cspell:disable-line
|
|
636
|
-
'F2_ZLrUw5Y8oDnbTP5t5xCUWX8WtVILLD0teyUi_37_4KHeV-YowVA==\nAAAAAAB4eXo= $$ '
|
|
637
|
-
'--b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= '
|
|
638
|
-
'-a eHl6 xOlAHPUPpeyZHId-f3VQ_QKKMxjIW0_FBo9WOfIBrzjn0VkVV6xTRA==\nAAAAAAB4eXo=')) # cspell:disable-line
|
|
479
|
+
epilog=('--b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -- ' # cspell:disable-line
|
|
480
|
+
'F2_ZLrUw5Y8oDnbTP5t5xCUWX8WtVILLD0teyUi_37_4KHeV-YowVA==\nAAAAAAB4eXo= $$ ' # cspell:disable-line
|
|
481
|
+
'--b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= ' # cspell:disable-line
|
|
482
|
+
'-a eHl6 -- xOlAHPUPpeyZHId-f3VQ_QKKMxjIW0_FBo9WOfIBrzjn0VkVV6xTRA==\nAAAAAAB4eXo=')) # cspell:disable-line
|
|
639
483
|
p_aes_dec.add_argument('ciphertext', type=str, help='Input data to decrypt (CT)')
|
|
640
484
|
p_aes_dec.add_argument(
|
|
641
485
|
'-k', '--key', type=str, default='', help='Key if `-p`/`--key-path` wasn\'t used (32 bytes)')
|
|
@@ -724,8 +568,8 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
724
568
|
p_rsa_dec_safe: argparse.ArgumentParser = rsa_sub.add_parser(
|
|
725
569
|
'decrypt',
|
|
726
570
|
help='Decrypt `ciphertext` with private key.',
|
|
727
|
-
epilog=('--b64 --out-bin -p rsa-key.priv rsa decrypt
|
|
728
|
-
'
|
|
571
|
+
epilog=('--b64 --out-bin -p rsa-key.priv rsa decrypt -a eHl6 -- '
|
|
572
|
+
'AO6knI6xwq6TGR…Qy22jiFhXi1eQ==\nabcde'))
|
|
729
573
|
p_rsa_dec_safe.add_argument('ciphertext', type=str, help='Ciphertext to decrypt')
|
|
730
574
|
p_rsa_dec_safe.add_argument(
|
|
731
575
|
'-a', '--aad', type=str, default='',
|
|
@@ -763,10 +607,10 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
763
607
|
p_rsa_ver_safe: argparse.ArgumentParser = rsa_sub.add_parser(
|
|
764
608
|
'verify',
|
|
765
609
|
help='Verify `signature` for `message` with public key.',
|
|
766
|
-
epilog=('--b64 -p rsa-key.pub rsa verify
|
|
767
|
-
'
|
|
768
|
-
'--b64 -p rsa-key.pub rsa verify
|
|
769
|
-
'
|
|
610
|
+
epilog=('--b64 -p rsa-key.pub rsa verify -- eHl6 '
|
|
611
|
+
'91TS7gC6LORiL…6RD23Aejsfxlw==\nRSA signature: OK $$ ' # cspell:disable-line
|
|
612
|
+
'--b64 -p rsa-key.pub rsa verify -- eLl6 '
|
|
613
|
+
'91TS7gC6LORiL…6RD23Aejsfxlw==\nRSA signature: INVALID')) # cspell:disable-line
|
|
770
614
|
p_rsa_ver_safe.add_argument('message', type=str, help='Message that was signed earlier')
|
|
771
615
|
p_rsa_ver_safe.add_argument('signature', type=str, help='Putative signature for `message`')
|
|
772
616
|
p_rsa_ver_safe.add_argument(
|
|
@@ -814,7 +658,7 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
814
658
|
p_eg_enc_safe: argparse.ArgumentParser = eg_sub.add_parser(
|
|
815
659
|
'encrypt',
|
|
816
660
|
help='Encrypt `message` with public key.',
|
|
817
|
-
epilog=('
|
|
661
|
+
epilog=('--bin --out-b64 -p eg-key.pub elgamal encrypt "abcde" -a "xyz"\n'
|
|
818
662
|
'CdFvoQ_IIPFPZLua…kqjhcUTspISxURg==')) # cspell:disable-line
|
|
819
663
|
p_eg_enc_safe.add_argument('plaintext', type=str, help='Message to encrypt')
|
|
820
664
|
p_eg_enc_safe.add_argument(
|
|
@@ -834,8 +678,8 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
834
678
|
p_eg_dec_safe: argparse.ArgumentParser = eg_sub.add_parser(
|
|
835
679
|
'decrypt',
|
|
836
680
|
help='Decrypt `ciphertext` with private key.',
|
|
837
|
-
epilog=('--b64 --out-bin -p eg-key.priv elgamal decrypt '
|
|
838
|
-
'
|
|
681
|
+
epilog=('--b64 --out-bin -p eg-key.priv elgamal decrypt -a eHl6 -- '
|
|
682
|
+
'CdFvoQ_IIPFPZLua…kqjhcUTspISxURg==\nabcde')) # cspell:disable-line
|
|
839
683
|
p_eg_dec_safe.add_argument('ciphertext', type=str, help='Ciphertext to decrypt')
|
|
840
684
|
p_eg_dec_safe.add_argument(
|
|
841
685
|
'-a', '--aad', type=str, default='',
|
|
@@ -877,9 +721,9 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
877
721
|
p_eg_ver_safe: argparse.ArgumentParser = eg_sub.add_parser(
|
|
878
722
|
'verify',
|
|
879
723
|
help='Verify `signature` for `message` with public key.',
|
|
880
|
-
epilog=('--b64 -p eg-key.pub elgamal verify
|
|
724
|
+
epilog=('--b64 -p eg-key.pub elgamal verify -- eHl6 Xl4hlYK8SHVGw…0fCKJE1XVzA==\n' # cspell:disable-line
|
|
881
725
|
'El-Gamal signature: OK $$ '
|
|
882
|
-
'--b64 -p eg-key.pub elgamal verify
|
|
726
|
+
'--b64 -p eg-key.pub elgamal verify -- eLl6 Xl4hlYK8SHVGw…0fCKJE1XVzA==\n' # cspell:disable-line
|
|
883
727
|
'El-Gamal signature: INVALID'))
|
|
884
728
|
p_eg_ver_safe.add_argument('message', type=str, help='Message that was signed earlier')
|
|
885
729
|
p_eg_ver_safe.add_argument('signature', type=str, help='Putative signature for `message`')
|
|
@@ -956,9 +800,9 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
956
800
|
p_dsa_verify_safe: argparse.ArgumentParser = dsa_sub.add_parser(
|
|
957
801
|
'verify',
|
|
958
802
|
help='Verify `signature` for `message` with public key.',
|
|
959
|
-
epilog=('--b64 -p dsa-key.pub dsa verify
|
|
803
|
+
epilog=('--b64 -p dsa-key.pub dsa verify -- eHl6 yq8InJVpViXh9…BD4par2XuA=\n'
|
|
960
804
|
'DSA signature: OK $$ '
|
|
961
|
-
'--b64 -p dsa-key.pub dsa verify
|
|
805
|
+
'--b64 -p dsa-key.pub dsa verify -- eLl6 yq8InJVpViXh9…BD4par2XuA=\n'
|
|
962
806
|
'DSA signature: INVALID'))
|
|
963
807
|
p_dsa_verify_safe.add_argument('message', type=str, help='Message that was signed earlier')
|
|
964
808
|
p_dsa_verify_safe.add_argument('signature', type=str, help='Putative signature for `message`')
|
|
@@ -1094,9 +938,7 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
1094
938
|
doc_sub.add_parser(
|
|
1095
939
|
'md',
|
|
1096
940
|
help='Emit Markdown docs for the CLI (see README.md section "Creating a New Version").',
|
|
1097
|
-
epilog=
|
|
1098
|
-
'$ ./tools/inject_md_includes.py\n'
|
|
1099
|
-
'inject: README.md updated with included content'))
|
|
941
|
+
epilog='doc md > transcrypto.md\n<<saves file>>')
|
|
1100
942
|
|
|
1101
943
|
return parser
|
|
1102
944
|
|
|
@@ -1544,7 +1386,7 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1544
1386
|
case 'bytes':
|
|
1545
1387
|
print(base.BytesToHex(base.RandBytes(args.n)))
|
|
1546
1388
|
case 'prime':
|
|
1547
|
-
print(modmath.
|
|
1389
|
+
print(modmath.NBitRandomPrimes(args.bits).pop())
|
|
1548
1390
|
case _:
|
|
1549
1391
|
raise NotImplementedError()
|
|
1550
1392
|
case 'hash':
|
|
@@ -1589,7 +1431,14 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1589
1431
|
args.doc_command.lower().strip() if getattr(args, 'doc_command', '') else '')
|
|
1590
1432
|
match doc_command:
|
|
1591
1433
|
case 'md':
|
|
1592
|
-
print(
|
|
1434
|
+
print(base.GenerateCLIMarkdown(
|
|
1435
|
+
'transcrypto', _BuildParser(), description=(
|
|
1436
|
+
'`transcrypto` is a command-line utility that provides access to all core '
|
|
1437
|
+
'functionality described in this documentation. It serves as a convenient '
|
|
1438
|
+
'wrapper over the Python APIs, enabling **cryptographic operations**, '
|
|
1439
|
+
'**number theory functions**, **secure randomness generation**, **hashing**, '
|
|
1440
|
+
'**AES**, **RSA**, **El-Gamal**, **DSA**, **bidding**, **SSS**, '
|
|
1441
|
+
'and other utilities without writing code.')))
|
|
1593
1442
|
case _:
|
|
1594
1443
|
raise NotImplementedError()
|
|
1595
1444
|
|