transcrypto 1.4.0__py3-none-any.whl → 1.6.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/base.py +98 -5
- transcrypto/profiler.py +14 -16
- transcrypto/safetrans.py +6 -9
- transcrypto/transcrypto.py +100 -92
- {transcrypto-1.4.0.dist-info → transcrypto-1.6.0.dist-info}/METADATA +2 -2
- {transcrypto-1.4.0.dist-info → transcrypto-1.6.0.dist-info}/RECORD +9 -9
- {transcrypto-1.4.0.dist-info → transcrypto-1.6.0.dist-info}/WHEEL +0 -0
- {transcrypto-1.4.0.dist-info → transcrypto-1.6.0.dist-info}/licenses/LICENSE +0 -0
- {transcrypto-1.4.0.dist-info → transcrypto-1.6.0.dist-info}/top_level.txt +0 -0
transcrypto/base.py
CHANGED
|
@@ -11,7 +11,7 @@ import argparse
|
|
|
11
11
|
import base64
|
|
12
12
|
import codecs
|
|
13
13
|
import dataclasses
|
|
14
|
-
|
|
14
|
+
import datetime
|
|
15
15
|
import enum
|
|
16
16
|
import functools
|
|
17
17
|
import hashlib
|
|
@@ -24,19 +24,21 @@ import pickle
|
|
|
24
24
|
import secrets
|
|
25
25
|
import sys
|
|
26
26
|
import time
|
|
27
|
+
import threading
|
|
27
28
|
from typing import Any, Callable, final, MutableSequence, Protocol, runtime_checkable
|
|
28
29
|
from typing import Sequence, Self, TypeVar
|
|
29
30
|
|
|
30
31
|
import numpy as np
|
|
32
|
+
from rich import console as rich_console
|
|
33
|
+
from rich import logging as rich_logging
|
|
31
34
|
from scipy import stats # type:ignore
|
|
32
35
|
import zstandard
|
|
33
36
|
|
|
34
37
|
__author__ = 'balparda@github.com'
|
|
35
|
-
__version__ = '1.
|
|
38
|
+
__version__ = '1.6.0' # 2026-01-15, Thu
|
|
36
39
|
__version_tuple__: tuple[int, ...] = tuple(int(v) for v in __version__.split('.'))
|
|
37
40
|
|
|
38
|
-
#
|
|
39
|
-
# datetime.datetime(2000, 1, 1, 0, 0, 0).replace(tzinfo=datetime.timezone.utc).timestamp())
|
|
41
|
+
# Data conversion utils
|
|
40
42
|
|
|
41
43
|
BytesToHex: Callable[[bytes], str] = lambda b: b.hex()
|
|
42
44
|
BytesToInt: Callable[[bytes], int] = lambda b: int.from_bytes(b, 'big', signed=False)
|
|
@@ -50,6 +52,28 @@ EncodedToBytes: Callable[[str], bytes] = lambda e: base64.urlsafe_b64decode(e.en
|
|
|
50
52
|
|
|
51
53
|
PadBytesTo: Callable[[bytes, int], bytes] = lambda b, i: b.rjust((i + 7) // 8, b'\x00')
|
|
52
54
|
|
|
55
|
+
# Time utils
|
|
56
|
+
|
|
57
|
+
MIN_TM = int(
|
|
58
|
+
datetime.datetime(2000, 1, 1, 0, 0, 0).replace(tzinfo=datetime.timezone.utc).timestamp())
|
|
59
|
+
TIME_FORMAT = '%Y/%b/%d-%H:%M:%S-UTC'
|
|
60
|
+
TimeStr: Callable[[int | float | None], str] = lambda tm: (
|
|
61
|
+
time.strftime(TIME_FORMAT, time.gmtime(tm)) if tm else '-')
|
|
62
|
+
Now: Callable[[], int] = lambda: int(time.time())
|
|
63
|
+
StrNow: Callable[[], str] = lambda: TimeStr(Now())
|
|
64
|
+
|
|
65
|
+
# Logging
|
|
66
|
+
_LOG_FORMAT_NO_PROCESS: str = '%(funcName)s: %(message)s'
|
|
67
|
+
_LOG_FORMAT_WITH_PROCESS: str = '%(processName)s/' + _LOG_FORMAT_NO_PROCESS
|
|
68
|
+
_LOG_FORMAT_DATETIME: str = '[%Y%m%d-%H:%M:%S]' # e.g., [20240131-13:45:30]
|
|
69
|
+
_LOG_LEVELS: list[int] = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]
|
|
70
|
+
_LOG_COMMON_PROVIDERS: set[str] = {
|
|
71
|
+
'werkzeug',
|
|
72
|
+
'gunicorn.error', 'gunicorn.access',
|
|
73
|
+
'uvicorn', 'uvicorn.error', 'uvicorn.access',
|
|
74
|
+
'django.server',
|
|
75
|
+
}
|
|
76
|
+
|
|
53
77
|
# SI prefix table, powers of 1000
|
|
54
78
|
_SI_PREFIXES: dict[int, str] = {
|
|
55
79
|
-6: 'a', # atto
|
|
@@ -106,6 +130,75 @@ class ImplementationError(Error, NotImplementedError):
|
|
|
106
130
|
"""This feature is not implemented yet (TransCrypto)."""
|
|
107
131
|
|
|
108
132
|
|
|
133
|
+
__console_lock = threading.RLock()
|
|
134
|
+
__console_singleton: rich_console.Console | None = None
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def Console() -> rich_console.Console:
|
|
138
|
+
"""Get the global console instance.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
rich.console.Console: The global console instance.
|
|
142
|
+
"""
|
|
143
|
+
with __console_lock:
|
|
144
|
+
if __console_singleton is None:
|
|
145
|
+
return rich_console.Console() # fallback console if InitLogging hasn't been called yet
|
|
146
|
+
return __console_singleton
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def ResetConsole() -> None:
|
|
150
|
+
"""Reset the global console instance."""
|
|
151
|
+
global __console_singleton # pylint: disable=global-statement
|
|
152
|
+
with __console_lock:
|
|
153
|
+
__console_singleton = None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def InitLogging(
|
|
157
|
+
verbosity: int, /, *,
|
|
158
|
+
include_process: bool = False, soft_wrap: bool = False) -> rich_console.Console:
|
|
159
|
+
"""Initialize logger (with RichHandler).
|
|
160
|
+
|
|
161
|
+
If you have a CLI app that uses this, its pytests should call `ResetConsole()` in a fixture, like:
|
|
162
|
+
|
|
163
|
+
from transcrypto import base
|
|
164
|
+
@pytest.fixture(autouse=True)
|
|
165
|
+
def _reset_base_logging():
|
|
166
|
+
base.ResetConsole()
|
|
167
|
+
yield
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
verbosity (int): Logging verbosity level.
|
|
171
|
+
include_process (bool, optional): Whether to include process name in log output.
|
|
172
|
+
soft_wrap (bool, optional): Whether to enable soft wrapping in the console.
|
|
173
|
+
Default is False, and it means rich will hard-wrap long lines (by adding '\n' chars).
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
rich.console.Console: The initialized console instance.
|
|
177
|
+
"""
|
|
178
|
+
global __console_singleton # pylint: disable=global-statement
|
|
179
|
+
with __console_lock:
|
|
180
|
+
if __console_singleton is not None:
|
|
181
|
+
return __console_singleton
|
|
182
|
+
logging_level: int = _LOG_LEVELS[max(0, min(verbosity, len(_LOG_LEVELS) - 1))]
|
|
183
|
+
console = rich_console.Console(soft_wrap=soft_wrap)
|
|
184
|
+
logging.basicConfig(
|
|
185
|
+
level=logging_level,
|
|
186
|
+
format=_LOG_FORMAT_WITH_PROCESS if include_process else _LOG_FORMAT_NO_PROCESS,
|
|
187
|
+
datefmt=_LOG_FORMAT_DATETIME,
|
|
188
|
+
handlers=[rich_logging.RichHandler( # we show name/line, but want time & level
|
|
189
|
+
console=console, rich_tracebacks=True, show_time=True, show_level=True, show_path=True)],
|
|
190
|
+
force=True) # force=True to override any previous logging config
|
|
191
|
+
logging.captureWarnings(True)
|
|
192
|
+
for name in _LOG_COMMON_PROVIDERS:
|
|
193
|
+
log: logging.Logger = logging.getLogger(name)
|
|
194
|
+
log.handlers.clear()
|
|
195
|
+
log.propagate = True
|
|
196
|
+
log.setLevel(logging_level)
|
|
197
|
+
__console_singleton = console # need a global statement to re-bind this one
|
|
198
|
+
logging.info(f'Logging initialized at level {logging.getLevelName(logging_level)}')
|
|
199
|
+
return console
|
|
200
|
+
|
|
201
|
+
|
|
109
202
|
def HumanizedBytes(inp_sz: int | float, /) -> str: # pylint: disable=too-many-return-statements
|
|
110
203
|
"""Convert a byte count into a human-readable string using binary prefixes (powers of 1024).
|
|
111
204
|
|
|
@@ -460,7 +553,7 @@ class Timer:
|
|
|
460
553
|
if self.emit_log:
|
|
461
554
|
logging.info(message)
|
|
462
555
|
if self.emit_print:
|
|
463
|
-
print(message)
|
|
556
|
+
Console().print(message)
|
|
464
557
|
|
|
465
558
|
def __exit__(
|
|
466
559
|
self, unused_exc_type: type[BaseException] | None,
|
transcrypto/profiler.py
CHANGED
|
@@ -16,11 +16,12 @@ doc md
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
import argparse
|
|
19
|
-
import logging
|
|
20
19
|
# import pdb
|
|
21
20
|
import sys
|
|
22
21
|
from typing import Callable
|
|
23
22
|
|
|
23
|
+
from rich import console as rich_console
|
|
24
|
+
|
|
24
25
|
from . import base, modmath, dsa
|
|
25
26
|
|
|
26
27
|
__author__ = 'balparda@github.com'
|
|
@@ -107,7 +108,8 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
107
108
|
|
|
108
109
|
def _PrimeProfiler(
|
|
109
110
|
prime_callable: Callable[[int], int],
|
|
110
|
-
repeats: int, n_bits_range: tuple[int, int, int], confidence: float,
|
|
111
|
+
repeats: int, n_bits_range: tuple[int, int, int], confidence: float,
|
|
112
|
+
console: rich_console.Console, /) -> None:
|
|
111
113
|
primes: dict[int, list[float]] = {}
|
|
112
114
|
for n_bits in range(*n_bits_range):
|
|
113
115
|
# investigate for size n_bits
|
|
@@ -120,7 +122,7 @@ def _PrimeProfiler(
|
|
|
120
122
|
# finished collecting n_bits-sized primes
|
|
121
123
|
measurements: str = base.HumanizedMeasurements(
|
|
122
124
|
primes[n_bits], parser=base.HumanizedSeconds, confidence=confidence)
|
|
123
|
-
print(f'{n_bits} → {measurements}')
|
|
125
|
+
console.print(f'{n_bits} → {measurements}')
|
|
124
126
|
|
|
125
127
|
|
|
126
128
|
def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-name,too-many-locals,too-many-branches,too-many-statements
|
|
@@ -129,11 +131,7 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
129
131
|
parser: argparse.ArgumentParser = _BuildParser()
|
|
130
132
|
args: argparse.Namespace = parser.parse_args(argv)
|
|
131
133
|
# take care of global options
|
|
132
|
-
|
|
133
|
-
logging.basicConfig(
|
|
134
|
-
level=levels[min(args.verbose, len(levels) - 1)], # type: ignore
|
|
135
|
-
format=getattr(base, 'LOG_FORMAT', '%(levelname)s:%(message)s'))
|
|
136
|
-
logging.captureWarnings(True)
|
|
134
|
+
console: rich_console.Console = base.InitLogging(args.verbose)
|
|
137
135
|
|
|
138
136
|
try:
|
|
139
137
|
# get the command, do basic checks and switch
|
|
@@ -149,16 +147,16 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
149
147
|
match command:
|
|
150
148
|
# -------- Primes ----------
|
|
151
149
|
case 'primes':
|
|
152
|
-
print(f'Starting {"SERIAL" if args.serial else "PARALLEL"} regular primes test')
|
|
150
|
+
console.print(f'Starting {"SERIAL" if args.serial else "PARALLEL"} regular primes test')
|
|
153
151
|
_PrimeProfiler(
|
|
154
152
|
lambda n: modmath.NBitRandomPrimes(n, serial=args.serial, n_primes=1).pop(),
|
|
155
|
-
repeats, bits, confidence / 100.0)
|
|
153
|
+
repeats, bits, confidence / 100.0, console)
|
|
156
154
|
|
|
157
155
|
case 'dsa':
|
|
158
|
-
print(f'Starting {"SERIAL" if args.serial else "PARALLEL"} DSA primes test')
|
|
156
|
+
console.print(f'Starting {"SERIAL" if args.serial else "PARALLEL"} DSA primes test')
|
|
159
157
|
_PrimeProfiler(
|
|
160
158
|
lambda n: dsa.NBitRandomDSAPrimes(n, n // 2, serial=args.serial)[0],
|
|
161
|
-
repeats, bits, confidence / 100.0)
|
|
159
|
+
repeats, bits, confidence / 100.0, console)
|
|
162
160
|
|
|
163
161
|
# -------- Documentation ----------
|
|
164
162
|
case 'doc':
|
|
@@ -166,7 +164,7 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
166
164
|
args.doc_command.lower().strip() if getattr(args, 'doc_command', '') else '')
|
|
167
165
|
match doc_command:
|
|
168
166
|
case 'md':
|
|
169
|
-
print(base.GenerateCLIMarkdown(
|
|
167
|
+
console.print(base.GenerateCLIMarkdown(
|
|
170
168
|
'profiler', _BuildParser(), description=(
|
|
171
169
|
'`profiler` is a command-line utility that provides stats on TransCrypto '
|
|
172
170
|
'performance.')))
|
|
@@ -177,12 +175,12 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
177
175
|
parser.print_help()
|
|
178
176
|
|
|
179
177
|
if command not in ('doc',):
|
|
180
|
-
print(f'Finished in {tmr}')
|
|
178
|
+
console.print(f'Finished in {tmr}')
|
|
181
179
|
|
|
182
180
|
except NotImplementedError as err:
|
|
183
|
-
print(f'Invalid command: {err}')
|
|
181
|
+
console.print(f'Invalid command: {err}')
|
|
184
182
|
except (base.Error, ValueError) as err:
|
|
185
|
-
print(str(err))
|
|
183
|
+
console.print(str(err))
|
|
186
184
|
|
|
187
185
|
return 0
|
|
188
186
|
|
transcrypto/safetrans.py
CHANGED
|
@@ -693,10 +693,11 @@ If you want, I can fill in concrete implementations next (e.g., Miller–Rabin f
|
|
|
693
693
|
from __future__ import annotations
|
|
694
694
|
|
|
695
695
|
import argparse
|
|
696
|
-
import logging
|
|
697
696
|
# import pdb
|
|
698
697
|
import sys
|
|
699
698
|
|
|
699
|
+
from rich import console as rich_console
|
|
700
|
+
|
|
700
701
|
from . import base
|
|
701
702
|
|
|
702
703
|
__author__ = 'balparda@github.com'
|
|
@@ -1185,11 +1186,7 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1185
1186
|
parser: argparse.ArgumentParser = _BuildParser()
|
|
1186
1187
|
args: argparse.Namespace = parser.parse_args(argv)
|
|
1187
1188
|
# take care of global options
|
|
1188
|
-
|
|
1189
|
-
logging.basicConfig(
|
|
1190
|
-
level=levels[min(args.verbose, len(levels) - 1)], # type: ignore
|
|
1191
|
-
format=getattr(base, 'LOG_FORMAT', '%(levelname)s:%(message)s'))
|
|
1192
|
-
logging.captureWarnings(True)
|
|
1189
|
+
console: rich_console.Console = base.InitLogging(args.verbose, soft_wrap=True)
|
|
1193
1190
|
|
|
1194
1191
|
try:
|
|
1195
1192
|
# get the command, do basic checks and switch
|
|
@@ -1205,7 +1202,7 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1205
1202
|
args.doc_command.lower().strip() if getattr(args, 'doc_command', '') else '')
|
|
1206
1203
|
match doc_command:
|
|
1207
1204
|
case 'md':
|
|
1208
|
-
print(base.GenerateCLIMarkdown(
|
|
1205
|
+
console.print(base.GenerateCLIMarkdown(
|
|
1209
1206
|
'safetrans', _BuildParser(), description=(
|
|
1210
1207
|
'`safetrans` is a command-line utility that provides ***safe*** crypto '
|
|
1211
1208
|
'primitives. It serves as a convenient wrapper over the Python APIs, '
|
|
@@ -1220,9 +1217,9 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1220
1217
|
parser.print_help()
|
|
1221
1218
|
|
|
1222
1219
|
except NotImplementedError as err:
|
|
1223
|
-
print(f'Invalid command: {err}')
|
|
1220
|
+
console.print(f'Invalid command: {err}')
|
|
1224
1221
|
except (base.Error, ValueError) as err:
|
|
1225
|
-
print(str(err))
|
|
1222
|
+
console.print(str(err))
|
|
1226
1223
|
|
|
1227
1224
|
return 0
|
|
1228
1225
|
|
transcrypto/transcrypto.py
CHANGED
|
@@ -31,6 +31,8 @@ import logging
|
|
|
31
31
|
import sys
|
|
32
32
|
from typing import Any, Iterable
|
|
33
33
|
|
|
34
|
+
from rich import console as rich_console
|
|
35
|
+
|
|
34
36
|
from . import base, modmath, rsa, sss, elgamal, dsa, aes
|
|
35
37
|
|
|
36
38
|
__author__ = 'balparda@github.com'
|
|
@@ -944,7 +946,8 @@ def _BuildParser() -> argparse.ArgumentParser: # pylint: disable=too-many-state
|
|
|
944
946
|
|
|
945
947
|
|
|
946
948
|
def AESCommand(
|
|
947
|
-
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
949
|
+
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
950
|
+
console: rich_console.Console, /) -> None:
|
|
948
951
|
"""Execute `aes` command."""
|
|
949
952
|
pt: bytes
|
|
950
953
|
ct: bytes
|
|
@@ -965,26 +968,26 @@ def AESCommand(
|
|
|
965
968
|
aes_key = aes.AESKey.FromStaticPassword(args.password)
|
|
966
969
|
if args.key_path:
|
|
967
970
|
_SaveObj(aes_key, args.key_path, args.protect or None)
|
|
968
|
-
print(f'AES key saved to {args.key_path!r}')
|
|
971
|
+
console.print(f'AES key saved to {args.key_path!r}')
|
|
969
972
|
else:
|
|
970
|
-
print(_BytesToText(aes_key.key256, out_format))
|
|
973
|
+
console.print(_BytesToText(aes_key.key256, out_format))
|
|
971
974
|
case 'encrypt':
|
|
972
975
|
pt = _BytesFromText(args.plaintext, in_format)
|
|
973
976
|
ct = aes_key.Encrypt(pt, associated_data=aad)
|
|
974
|
-
print(_BytesToText(ct, out_format))
|
|
977
|
+
console.print(_BytesToText(ct, out_format))
|
|
975
978
|
case 'decrypt':
|
|
976
979
|
ct = _BytesFromText(args.ciphertext, in_format)
|
|
977
980
|
pt = aes_key.Decrypt(ct, associated_data=aad)
|
|
978
|
-
print(_BytesToText(pt, out_format))
|
|
981
|
+
console.print(_BytesToText(pt, out_format))
|
|
979
982
|
case 'ecb':
|
|
980
983
|
ecb_cmd: str = args.aes_ecb_command.lower().strip() if args.aes_ecb_command else ''
|
|
981
984
|
match ecb_cmd:
|
|
982
985
|
case 'encrypt':
|
|
983
986
|
ecb: aes.AESKey.ECBEncoderClass = aes_key.ECBEncoder()
|
|
984
|
-
print(ecb.EncryptHex(args.plaintext))
|
|
987
|
+
console.print(ecb.EncryptHex(args.plaintext))
|
|
985
988
|
case 'decrypt':
|
|
986
989
|
ecb = aes_key.ECBEncoder()
|
|
987
|
-
print(ecb.DecryptHex(args.ciphertext))
|
|
990
|
+
console.print(ecb.DecryptHex(args.ciphertext))
|
|
988
991
|
case _:
|
|
989
992
|
raise NotImplementedError()
|
|
990
993
|
case _:
|
|
@@ -992,7 +995,8 @@ def AESCommand(
|
|
|
992
995
|
|
|
993
996
|
|
|
994
997
|
def RSACommand(
|
|
995
|
-
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
998
|
+
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
999
|
+
console: rich_console.Console, /) -> None:
|
|
996
1000
|
"""Execute `rsa` command."""
|
|
997
1001
|
c: int
|
|
998
1002
|
m: int
|
|
@@ -1010,53 +1014,54 @@ def RSACommand(
|
|
|
1010
1014
|
rsa_pub = rsa.RSAPublicKey.Copy(rsa_priv)
|
|
1011
1015
|
_SaveObj(rsa_priv, args.key_path + '.priv', args.protect or None)
|
|
1012
1016
|
_SaveObj(rsa_pub, args.key_path + '.pub', args.protect or None)
|
|
1013
|
-
print(f'RSA private/public keys saved to {args.key_path + ".priv/.pub"!r}')
|
|
1017
|
+
console.print(f'RSA private/public keys saved to {args.key_path + ".priv/.pub"!r}')
|
|
1014
1018
|
case 'rawencrypt':
|
|
1015
1019
|
rsa_pub = rsa.RSAPublicKey.Copy(
|
|
1016
1020
|
_LoadObj(args.key_path, args.protect or None, rsa.RSAPublicKey))
|
|
1017
1021
|
m = _ParseInt(args.message)
|
|
1018
|
-
print(rsa_pub.RawEncrypt(m))
|
|
1022
|
+
console.print(rsa_pub.RawEncrypt(m))
|
|
1019
1023
|
case 'rawdecrypt':
|
|
1020
1024
|
rsa_priv = _LoadObj(args.key_path, args.protect or None, rsa.RSAPrivateKey)
|
|
1021
1025
|
c = _ParseInt(args.ciphertext)
|
|
1022
|
-
print(rsa_priv.RawDecrypt(c))
|
|
1026
|
+
console.print(rsa_priv.RawDecrypt(c))
|
|
1023
1027
|
case 'rawsign':
|
|
1024
1028
|
rsa_priv = _LoadObj(args.key_path, args.protect or None, rsa.RSAPrivateKey)
|
|
1025
1029
|
m = _ParseInt(args.message)
|
|
1026
|
-
print(rsa_priv.RawSign(m))
|
|
1030
|
+
console.print(rsa_priv.RawSign(m))
|
|
1027
1031
|
case 'rawverify':
|
|
1028
1032
|
rsa_pub = rsa.RSAPublicKey.Copy(
|
|
1029
1033
|
_LoadObj(args.key_path, args.protect or None, rsa.RSAPublicKey))
|
|
1030
1034
|
m = _ParseInt(args.message)
|
|
1031
1035
|
sig: int = _ParseInt(args.signature)
|
|
1032
|
-
print('RSA signature: ' + ('OK' if rsa_pub.RawVerify(m, sig) else 'INVALID'))
|
|
1036
|
+
console.print('RSA signature: ' + ('OK' if rsa_pub.RawVerify(m, sig) else 'INVALID'))
|
|
1033
1037
|
case 'encrypt':
|
|
1034
1038
|
rsa_pub = _LoadObj(args.key_path, args.protect or None, rsa.RSAPublicKey)
|
|
1035
1039
|
pt = _BytesFromText(args.plaintext, in_format)
|
|
1036
1040
|
ct = rsa_pub.Encrypt(pt, associated_data=aad)
|
|
1037
|
-
print(_BytesToText(ct, out_format))
|
|
1041
|
+
console.print(_BytesToText(ct, out_format))
|
|
1038
1042
|
case 'decrypt':
|
|
1039
1043
|
rsa_priv = _LoadObj(args.key_path, args.protect or None, rsa.RSAPrivateKey)
|
|
1040
1044
|
ct = _BytesFromText(args.ciphertext, in_format)
|
|
1041
1045
|
pt = rsa_priv.Decrypt(ct, associated_data=aad)
|
|
1042
|
-
print(_BytesToText(pt, out_format))
|
|
1046
|
+
console.print(_BytesToText(pt, out_format))
|
|
1043
1047
|
case 'sign':
|
|
1044
1048
|
rsa_priv = _LoadObj(args.key_path, args.protect or None, rsa.RSAPrivateKey)
|
|
1045
1049
|
pt = _BytesFromText(args.message, in_format)
|
|
1046
1050
|
ct = rsa_priv.Sign(pt, associated_data=aad)
|
|
1047
|
-
print(_BytesToText(ct, out_format))
|
|
1051
|
+
console.print(_BytesToText(ct, out_format))
|
|
1048
1052
|
case 'verify':
|
|
1049
1053
|
rsa_pub = _LoadObj(args.key_path, args.protect or None, rsa.RSAPublicKey)
|
|
1050
1054
|
pt = _BytesFromText(args.message, in_format)
|
|
1051
1055
|
ct = _BytesFromText(args.signature, in_format)
|
|
1052
|
-
print(
|
|
1053
|
-
|
|
1056
|
+
console.print(
|
|
1057
|
+
'RSA signature: ' + ('OK' if rsa_pub.Verify(pt, ct, associated_data=aad) else 'INVALID'))
|
|
1054
1058
|
case _:
|
|
1055
1059
|
raise NotImplementedError()
|
|
1056
1060
|
|
|
1057
1061
|
|
|
1058
1062
|
def ElGamalCommand( # pylint: disable=too-many-statements
|
|
1059
|
-
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
1063
|
+
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
1064
|
+
console: rich_console.Console, /) -> None:
|
|
1060
1065
|
"""Execute `elgamal` command."""
|
|
1061
1066
|
c1: str
|
|
1062
1067
|
c2: str
|
|
@@ -1075,64 +1080,66 @@ def ElGamalCommand( # pylint: disable=too-many-statements
|
|
|
1075
1080
|
shared_eg: elgamal.ElGamalSharedPublicKey = elgamal.ElGamalSharedPublicKey.NewShared(
|
|
1076
1081
|
args.bits)
|
|
1077
1082
|
_SaveObj(shared_eg, args.key_path + '.shared', args.protect or None)
|
|
1078
|
-
print(f'El-Gamal shared key saved to {args.key_path + ".shared"!r}')
|
|
1083
|
+
console.print(f'El-Gamal shared key saved to {args.key_path + ".shared"!r}')
|
|
1079
1084
|
case 'new':
|
|
1080
1085
|
eg_priv = elgamal.ElGamalPrivateKey.New(
|
|
1081
1086
|
_LoadObj(args.key_path + '.shared', args.protect or None, elgamal.ElGamalSharedPublicKey))
|
|
1082
1087
|
eg_pub = elgamal.ElGamalPublicKey.Copy(eg_priv)
|
|
1083
1088
|
_SaveObj(eg_priv, args.key_path + '.priv', args.protect or None)
|
|
1084
1089
|
_SaveObj(eg_pub, args.key_path + '.pub', args.protect or None)
|
|
1085
|
-
print(f'El-Gamal private/public keys saved to {args.key_path + ".priv/.pub"!r}')
|
|
1090
|
+
console.print(f'El-Gamal private/public keys saved to {args.key_path + ".priv/.pub"!r}')
|
|
1086
1091
|
case 'rawencrypt':
|
|
1087
1092
|
eg_pub = elgamal.ElGamalPublicKey.Copy(
|
|
1088
1093
|
_LoadObj(args.key_path, args.protect or None, elgamal.ElGamalPublicKey))
|
|
1089
1094
|
m = _ParseInt(args.message)
|
|
1090
1095
|
ss = eg_pub.RawEncrypt(m)
|
|
1091
|
-
print(f'{ss[0]}:{ss[1]}')
|
|
1096
|
+
console.print(f'{ss[0]}:{ss[1]}')
|
|
1092
1097
|
case 'rawdecrypt':
|
|
1093
1098
|
eg_priv = _LoadObj(args.key_path, args.protect or None, elgamal.ElGamalPrivateKey)
|
|
1094
1099
|
c1, c2 = args.ciphertext.split(':')
|
|
1095
1100
|
ss = (_ParseInt(c1), _ParseInt(c2))
|
|
1096
|
-
print(eg_priv.RawDecrypt(ss))
|
|
1101
|
+
console.print(eg_priv.RawDecrypt(ss))
|
|
1097
1102
|
case 'rawsign':
|
|
1098
1103
|
eg_priv = _LoadObj(args.key_path, args.protect or None, elgamal.ElGamalPrivateKey)
|
|
1099
1104
|
m = _ParseInt(args.message)
|
|
1100
1105
|
ss = eg_priv.RawSign(m)
|
|
1101
|
-
print(f'{ss[0]}:{ss[1]}')
|
|
1106
|
+
console.print(f'{ss[0]}:{ss[1]}')
|
|
1102
1107
|
case 'rawverify':
|
|
1103
1108
|
eg_pub = elgamal.ElGamalPublicKey.Copy(
|
|
1104
1109
|
_LoadObj(args.key_path, args.protect or None, elgamal.ElGamalPublicKey))
|
|
1105
1110
|
m = _ParseInt(args.message)
|
|
1106
1111
|
c1, c2 = args.signature.split(':')
|
|
1107
1112
|
ss = (_ParseInt(c1), _ParseInt(c2))
|
|
1108
|
-
print('El-Gamal signature: ' + ('OK' if eg_pub.RawVerify(m, ss) else 'INVALID'))
|
|
1113
|
+
console.print('El-Gamal signature: ' + ('OK' if eg_pub.RawVerify(m, ss) else 'INVALID'))
|
|
1109
1114
|
case 'encrypt':
|
|
1110
1115
|
eg_pub = _LoadObj(args.key_path, args.protect or None, elgamal.ElGamalPublicKey)
|
|
1111
1116
|
pt = _BytesFromText(args.plaintext, in_format)
|
|
1112
1117
|
ct = eg_pub.Encrypt(pt, associated_data=aad)
|
|
1113
|
-
print(_BytesToText(ct, out_format))
|
|
1118
|
+
console.print(_BytesToText(ct, out_format))
|
|
1114
1119
|
case 'decrypt':
|
|
1115
1120
|
eg_priv = _LoadObj(args.key_path, args.protect or None, elgamal.ElGamalPrivateKey)
|
|
1116
1121
|
ct = _BytesFromText(args.ciphertext, in_format)
|
|
1117
1122
|
pt = eg_priv.Decrypt(ct, associated_data=aad)
|
|
1118
|
-
print(_BytesToText(pt, out_format))
|
|
1123
|
+
console.print(_BytesToText(pt, out_format))
|
|
1119
1124
|
case 'sign':
|
|
1120
1125
|
eg_priv = _LoadObj(args.key_path, args.protect or None, elgamal.ElGamalPrivateKey)
|
|
1121
1126
|
pt = _BytesFromText(args.message, in_format)
|
|
1122
1127
|
ct = eg_priv.Sign(pt, associated_data=aad)
|
|
1123
|
-
print(_BytesToText(ct, out_format))
|
|
1128
|
+
console.print(_BytesToText(ct, out_format))
|
|
1124
1129
|
case 'verify':
|
|
1125
1130
|
eg_pub = _LoadObj(args.key_path, args.protect or None, elgamal.ElGamalPublicKey)
|
|
1126
1131
|
pt = _BytesFromText(args.message, in_format)
|
|
1127
1132
|
ct = _BytesFromText(args.signature, in_format)
|
|
1128
|
-
print(
|
|
1129
|
-
|
|
1133
|
+
console.print(
|
|
1134
|
+
'El-Gamal signature: ' + ('OK' if eg_pub.Verify(pt, ct, associated_data=aad)
|
|
1135
|
+
else 'INVALID'))
|
|
1130
1136
|
case _:
|
|
1131
1137
|
raise NotImplementedError()
|
|
1132
1138
|
|
|
1133
1139
|
|
|
1134
1140
|
def DSACommand(
|
|
1135
|
-
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
1141
|
+
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
1142
|
+
console: rich_console.Console, /) -> None:
|
|
1136
1143
|
"""Execute `dsa` command."""
|
|
1137
1144
|
c1: str
|
|
1138
1145
|
c2: str
|
|
@@ -1151,43 +1158,44 @@ def DSACommand(
|
|
|
1151
1158
|
dsa_shared: dsa.DSASharedPublicKey = dsa.DSASharedPublicKey.NewShared(
|
|
1152
1159
|
args.p_bits, args.q_bits)
|
|
1153
1160
|
_SaveObj(dsa_shared, args.key_path + '.shared', args.protect or None)
|
|
1154
|
-
print(f'DSA shared key saved to {args.key_path + ".shared"!r}')
|
|
1161
|
+
console.print(f'DSA shared key saved to {args.key_path + ".shared"!r}')
|
|
1155
1162
|
case 'new':
|
|
1156
1163
|
dsa_priv = dsa.DSAPrivateKey.New(
|
|
1157
1164
|
_LoadObj(args.key_path + '.shared', args.protect or None, dsa.DSASharedPublicKey))
|
|
1158
1165
|
dsa_pub = dsa.DSAPublicKey.Copy(dsa_priv)
|
|
1159
1166
|
_SaveObj(dsa_priv, args.key_path + '.priv', args.protect or None)
|
|
1160
1167
|
_SaveObj(dsa_pub, args.key_path + '.pub', args.protect or None)
|
|
1161
|
-
print(f'DSA private/public keys saved to {args.key_path + ".priv/.pub"!r}')
|
|
1168
|
+
console.print(f'DSA private/public keys saved to {args.key_path + ".priv/.pub"!r}')
|
|
1162
1169
|
case 'rawsign':
|
|
1163
1170
|
dsa_priv = _LoadObj(args.key_path, args.protect or None, dsa.DSAPrivateKey)
|
|
1164
1171
|
m = _ParseInt(args.message) % dsa_priv.prime_seed
|
|
1165
1172
|
ss = dsa_priv.RawSign(m)
|
|
1166
|
-
print(f'{ss[0]}:{ss[1]}')
|
|
1173
|
+
console.print(f'{ss[0]}:{ss[1]}')
|
|
1167
1174
|
case 'rawverify':
|
|
1168
1175
|
dsa_pub = dsa.DSAPublicKey.Copy(
|
|
1169
1176
|
_LoadObj(args.key_path, args.protect or None, dsa.DSAPublicKey))
|
|
1170
1177
|
m = _ParseInt(args.message) % dsa_pub.prime_seed
|
|
1171
1178
|
c1, c2 = args.signature.split(':')
|
|
1172
1179
|
ss = (_ParseInt(c1), _ParseInt(c2))
|
|
1173
|
-
print('DSA signature: ' + ('OK' if dsa_pub.RawVerify(m, ss) else 'INVALID'))
|
|
1180
|
+
console.print('DSA signature: ' + ('OK' if dsa_pub.RawVerify(m, ss) else 'INVALID'))
|
|
1174
1181
|
case 'sign':
|
|
1175
1182
|
dsa_priv = _LoadObj(args.key_path, args.protect or None, dsa.DSAPrivateKey)
|
|
1176
1183
|
pt = _BytesFromText(args.message, in_format)
|
|
1177
1184
|
ct = dsa_priv.Sign(pt, associated_data=aad)
|
|
1178
|
-
print(_BytesToText(ct, out_format))
|
|
1185
|
+
console.print(_BytesToText(ct, out_format))
|
|
1179
1186
|
case 'verify':
|
|
1180
1187
|
dsa_pub = _LoadObj(args.key_path, args.protect or None, dsa.DSAPublicKey)
|
|
1181
1188
|
pt = _BytesFromText(args.message, in_format)
|
|
1182
1189
|
ct = _BytesFromText(args.signature, in_format)
|
|
1183
|
-
print(
|
|
1184
|
-
|
|
1190
|
+
console.print(
|
|
1191
|
+
'DSA signature: ' + ('OK' if dsa_pub.Verify(pt, ct, associated_data=aad) else 'INVALID'))
|
|
1185
1192
|
case _:
|
|
1186
1193
|
raise NotImplementedError()
|
|
1187
1194
|
|
|
1188
1195
|
|
|
1189
1196
|
def BidCommand(
|
|
1190
|
-
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
1197
|
+
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
1198
|
+
console: rich_console.Console, /) -> None:
|
|
1191
1199
|
"""Execute `bid` command."""
|
|
1192
1200
|
bid_cmd: str = args.bid_command.lower().strip() if args.bid_command else ''
|
|
1193
1201
|
match bid_cmd:
|
|
@@ -1197,22 +1205,23 @@ def BidCommand(
|
|
|
1197
1205
|
bid_pub: base.PublicBid512 = base.PublicBid512.Copy(bid_priv)
|
|
1198
1206
|
_SaveObj(bid_priv, args.key_path + '.priv', args.protect or None)
|
|
1199
1207
|
_SaveObj(bid_pub, args.key_path + '.pub', args.protect or None)
|
|
1200
|
-
print(f'Bid private/public commitments saved to {args.key_path + ".priv/.pub"!r}')
|
|
1208
|
+
console.print(f'Bid private/public commitments saved to {args.key_path + ".priv/.pub"!r}')
|
|
1201
1209
|
case 'verify':
|
|
1202
1210
|
bid_priv = _LoadObj(args.key_path + '.priv', args.protect or None, base.PrivateBid512)
|
|
1203
1211
|
bid_pub = _LoadObj(args.key_path + '.pub', args.protect or None, base.PublicBid512)
|
|
1204
1212
|
bid_pub_expect: base.PublicBid512 = base.PublicBid512.Copy(bid_priv)
|
|
1205
|
-
print('Bid commitment: ' + (
|
|
1213
|
+
console.print('Bid commitment: ' + (
|
|
1206
1214
|
'OK' if (bid_pub.VerifyBid(bid_priv.private_key, bid_priv.secret_bid) and
|
|
1207
1215
|
bid_pub == bid_pub_expect) else 'INVALID'))
|
|
1208
|
-
print('Bid secret:')
|
|
1209
|
-
print(_BytesToText(bid_priv.secret_bid, out_format))
|
|
1216
|
+
console.print('Bid secret:')
|
|
1217
|
+
console.print(_BytesToText(bid_priv.secret_bid, out_format))
|
|
1210
1218
|
case _:
|
|
1211
1219
|
raise NotImplementedError()
|
|
1212
1220
|
|
|
1213
1221
|
|
|
1214
1222
|
def SSSCommand(
|
|
1215
|
-
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
1223
|
+
args: argparse.Namespace, in_format: _StrBytesType, out_format: _StrBytesType,
|
|
1224
|
+
console: rich_console.Console, /) -> None:
|
|
1216
1225
|
"""Execute `sss` command."""
|
|
1217
1226
|
pt: bytes
|
|
1218
1227
|
sss_share: sss.ShamirSharePrivate
|
|
@@ -1226,40 +1235,43 @@ def SSSCommand(
|
|
|
1226
1235
|
sss_pub: sss.ShamirSharedSecretPublic = sss.ShamirSharedSecretPublic.Copy(sss_priv)
|
|
1227
1236
|
_SaveObj(sss_priv, args.key_path + '.priv', args.protect or None)
|
|
1228
1237
|
_SaveObj(sss_pub, args.key_path + '.pub', args.protect or None)
|
|
1229
|
-
print(f'SSS private/public keys saved to {args.key_path + ".priv/.pub"!r}')
|
|
1238
|
+
console.print(f'SSS private/public keys saved to {args.key_path + ".priv/.pub"!r}')
|
|
1230
1239
|
case 'rawshares':
|
|
1231
1240
|
sss_priv = _LoadObj(
|
|
1232
1241
|
args.key_path + '.priv', args.protect or None, sss.ShamirSharedSecretPrivate)
|
|
1233
1242
|
secret: int = _ParseInt(args.secret)
|
|
1234
1243
|
for i, sss_share in enumerate(sss_priv.RawShares(secret, max_shares=args.count)):
|
|
1235
1244
|
_SaveObj(sss_share, f'{args.key_path}.share.{i + 1}', args.protect or None)
|
|
1236
|
-
print(
|
|
1237
|
-
|
|
1245
|
+
console.print(
|
|
1246
|
+
f'SSS {args.count} individual (private) shares saved to '
|
|
1247
|
+
f'{args.key_path + ".share.1…" + str(args.count)!r}')
|
|
1238
1248
|
case 'rawrecover':
|
|
1239
1249
|
sss_pub = _LoadObj(args.key_path + '.pub', args.protect or None, sss.ShamirSharedSecretPublic)
|
|
1240
1250
|
subset = []
|
|
1241
1251
|
for fname in glob.glob(args.key_path + '.share.*'):
|
|
1242
1252
|
sss_share = _LoadObj(fname, args.protect or None, sss.ShamirSharePrivate)
|
|
1243
1253
|
subset.append(sss_share)
|
|
1244
|
-
print(f'Loaded SSS share: {fname!r}')
|
|
1245
|
-
print('Secret:')
|
|
1246
|
-
print(sss_pub.RawRecoverSecret(subset))
|
|
1254
|
+
console.print(f'Loaded SSS share: {fname!r}')
|
|
1255
|
+
console.print('Secret:')
|
|
1256
|
+
console.print(sss_pub.RawRecoverSecret(subset))
|
|
1247
1257
|
case 'rawverify':
|
|
1248
1258
|
sss_priv = _LoadObj(
|
|
1249
1259
|
args.key_path + '.priv', args.protect or None, sss.ShamirSharedSecretPrivate)
|
|
1250
1260
|
secret = _ParseInt(args.secret)
|
|
1251
1261
|
for fname in glob.glob(args.key_path + '.share.*'):
|
|
1252
1262
|
sss_share = _LoadObj(fname, args.protect or None, sss.ShamirSharePrivate)
|
|
1253
|
-
print(
|
|
1254
|
-
|
|
1263
|
+
console.print(
|
|
1264
|
+
f'SSS share {fname!r} verification: '
|
|
1265
|
+
f'{"OK" if sss_priv.RawVerifyShare(secret, sss_share) else "INVALID"}')
|
|
1255
1266
|
case 'shares':
|
|
1256
1267
|
sss_priv = _LoadObj(
|
|
1257
1268
|
args.key_path + '.priv', args.protect or None, sss.ShamirSharedSecretPrivate)
|
|
1258
1269
|
pt = _BytesFromText(args.secret, in_format)
|
|
1259
1270
|
for i, data_share in enumerate(sss_priv.MakeDataShares(pt, args.count)):
|
|
1260
1271
|
_SaveObj(data_share, f'{args.key_path}.share.{i + 1}', args.protect or None)
|
|
1261
|
-
print(
|
|
1262
|
-
|
|
1272
|
+
console.print(
|
|
1273
|
+
f'SSS {args.count} individual (private) shares saved to '
|
|
1274
|
+
f'{args.key_path + ".share.1…" + str(args.count)!r}')
|
|
1263
1275
|
case 'recover':
|
|
1264
1276
|
sss_pub = _LoadObj(args.key_path + '.pub', args.protect or None, sss.ShamirSharedSecretPublic)
|
|
1265
1277
|
subset, data_share = [], None
|
|
@@ -1268,12 +1280,12 @@ def SSSCommand(
|
|
|
1268
1280
|
subset.append(sss_share)
|
|
1269
1281
|
if isinstance(sss_share, sss.ShamirShareData):
|
|
1270
1282
|
data_share = sss_share
|
|
1271
|
-
print(f'Loaded SSS share: {fname!r}')
|
|
1283
|
+
console.print(f'Loaded SSS share: {fname!r}')
|
|
1272
1284
|
if data_share is None:
|
|
1273
1285
|
raise base.InputError('no data share found among the available shares')
|
|
1274
1286
|
pt = data_share.RecoverData(subset)
|
|
1275
|
-
print('Secret:')
|
|
1276
|
-
print(_BytesToText(pt, out_format))
|
|
1287
|
+
console.print('Secret:')
|
|
1288
|
+
console.print(_BytesToText(pt, out_format))
|
|
1277
1289
|
case _:
|
|
1278
1290
|
raise NotImplementedError()
|
|
1279
1291
|
|
|
@@ -1284,11 +1296,7 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1284
1296
|
parser: argparse.ArgumentParser = _BuildParser()
|
|
1285
1297
|
args: argparse.Namespace = parser.parse_args(argv)
|
|
1286
1298
|
# take care of global options
|
|
1287
|
-
|
|
1288
|
-
logging.basicConfig(
|
|
1289
|
-
level=levels[min(args.verbose, len(levels) - 1)], # type: ignore
|
|
1290
|
-
format=getattr(base, 'LOG_FORMAT', '%(levelname)s:%(message)s'))
|
|
1291
|
-
logging.captureWarnings(True)
|
|
1299
|
+
console: rich_console.Console = base.InitLogging(args.verbose, soft_wrap=True)
|
|
1292
1300
|
in_format: _StrBytesType = _StrBytesType.FromFlags(args.hex, args.b64, args.bin)
|
|
1293
1301
|
out_format: _StrBytesType = _StrBytesType.FromFlags(args.out_hex, args.out_b64, args.out_bin)
|
|
1294
1302
|
|
|
@@ -1311,51 +1319,51 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1311
1319
|
# -------- primes ----------
|
|
1312
1320
|
case 'isprime':
|
|
1313
1321
|
n = _ParseInt(args.n)
|
|
1314
|
-
print(modmath.IsPrime(n))
|
|
1322
|
+
console.print(modmath.IsPrime(n))
|
|
1315
1323
|
case 'primegen':
|
|
1316
1324
|
start: int = _ParseInt(args.start)
|
|
1317
1325
|
count: int = args.count
|
|
1318
1326
|
i = 0
|
|
1319
1327
|
for p in modmath.PrimeGenerator(start):
|
|
1320
|
-
print(p)
|
|
1328
|
+
console.print(p)
|
|
1321
1329
|
i += 1
|
|
1322
1330
|
if count and i >= count:
|
|
1323
1331
|
break
|
|
1324
1332
|
case 'mersenne':
|
|
1325
1333
|
for k, m_p, perfect in modmath.MersennePrimesGenerator(args.min_k):
|
|
1326
|
-
print(f'k={k} M={m_p} perfect={perfect}')
|
|
1334
|
+
console.print(f'k={k} M={m_p} perfect={perfect}')
|
|
1327
1335
|
if k > args.cutoff_k:
|
|
1328
1336
|
break
|
|
1329
1337
|
|
|
1330
1338
|
# -------- integer / modular ----------
|
|
1331
1339
|
case 'gcd':
|
|
1332
1340
|
a, b = _ParseInt(args.a), _ParseInt(args.b)
|
|
1333
|
-
print(base.GCD(a, b))
|
|
1341
|
+
console.print(base.GCD(a, b))
|
|
1334
1342
|
case 'xgcd':
|
|
1335
1343
|
a, b = _ParseInt(args.a), _ParseInt(args.b)
|
|
1336
|
-
print(base.ExtendedGCD(a, b))
|
|
1344
|
+
console.print(base.ExtendedGCD(a, b))
|
|
1337
1345
|
case 'mod':
|
|
1338
1346
|
mod_command: str = args.mod_command.lower().strip() if args.mod_command else ''
|
|
1339
1347
|
match mod_command:
|
|
1340
1348
|
case 'inv':
|
|
1341
1349
|
a, m = _ParseInt(args.a), _ParseInt(args.m)
|
|
1342
1350
|
try:
|
|
1343
|
-
print(modmath.ModInv(a, m))
|
|
1351
|
+
console.print(modmath.ModInv(a, m))
|
|
1344
1352
|
except modmath.ModularDivideError:
|
|
1345
|
-
print('<<INVALID>> no modular inverse exists (ModularDivideError)')
|
|
1353
|
+
console.print('<<INVALID>> no modular inverse exists (ModularDivideError)')
|
|
1346
1354
|
case 'div':
|
|
1347
1355
|
x, y, m = _ParseInt(args.x), _ParseInt(args.y), _ParseInt(args.m)
|
|
1348
1356
|
try:
|
|
1349
|
-
print(modmath.ModDiv(x, y, m))
|
|
1357
|
+
console.print(modmath.ModDiv(x, y, m))
|
|
1350
1358
|
except modmath.ModularDivideError:
|
|
1351
|
-
print('<<INVALID>> no modular inverse exists (ModularDivideError)')
|
|
1359
|
+
console.print('<<INVALID>> no modular inverse exists (ModularDivideError)')
|
|
1352
1360
|
case 'exp':
|
|
1353
1361
|
a, e, m = _ParseInt(args.a), _ParseInt(args.e), _ParseInt(args.m)
|
|
1354
|
-
print(modmath.ModExp(a, e, m))
|
|
1362
|
+
console.print(modmath.ModExp(a, e, m))
|
|
1355
1363
|
case 'poly':
|
|
1356
1364
|
x, m = _ParseInt(args.x), _ParseInt(args.m)
|
|
1357
1365
|
coeffs: list[int] = _ParseIntList(args.coeff)
|
|
1358
|
-
print(modmath.ModPolynomial(x, coeffs, m))
|
|
1366
|
+
console.print(modmath.ModPolynomial(x, coeffs, m))
|
|
1359
1367
|
case 'lagrange':
|
|
1360
1368
|
x, m = _ParseInt(args.x), _ParseInt(args.m)
|
|
1361
1369
|
pts: dict[int, int] = {}
|
|
@@ -1364,14 +1372,14 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1364
1372
|
for kv in args.pt:
|
|
1365
1373
|
k_s, v_s = kv.split(':', 1)
|
|
1366
1374
|
pts[_ParseInt(k_s)] = _ParseInt(v_s)
|
|
1367
|
-
print(modmath.ModLagrangeInterpolate(x, pts, m))
|
|
1375
|
+
console.print(modmath.ModLagrangeInterpolate(x, pts, m))
|
|
1368
1376
|
case 'crt':
|
|
1369
1377
|
crt_tuple: tuple[int, int, int, int] = (
|
|
1370
1378
|
_ParseInt(args.a1), _ParseInt(args.m1), _ParseInt(args.a2), _ParseInt(args.m2))
|
|
1371
1379
|
try:
|
|
1372
|
-
print(modmath.CRTPair(*crt_tuple))
|
|
1380
|
+
console.print(modmath.CRTPair(*crt_tuple))
|
|
1373
1381
|
except modmath.ModularDivideError:
|
|
1374
|
-
print('<<INVALID>> moduli m1/m2 not co-prime (ModularDivideError)')
|
|
1382
|
+
console.print('<<INVALID>> moduli m1/m2 not co-prime (ModularDivideError)')
|
|
1375
1383
|
case _:
|
|
1376
1384
|
raise NotImplementedError()
|
|
1377
1385
|
|
|
@@ -1380,13 +1388,13 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1380
1388
|
rand_cmd: str = args.rand_command.lower().strip() if args.rand_command else ''
|
|
1381
1389
|
match rand_cmd:
|
|
1382
1390
|
case 'bits':
|
|
1383
|
-
print(base.RandBits(args.bits))
|
|
1391
|
+
console.print(base.RandBits(args.bits))
|
|
1384
1392
|
case 'int':
|
|
1385
|
-
print(base.RandInt(_ParseInt(args.min), _ParseInt(args.max)))
|
|
1393
|
+
console.print(base.RandInt(_ParseInt(args.min), _ParseInt(args.max)))
|
|
1386
1394
|
case 'bytes':
|
|
1387
|
-
print(base.BytesToHex(base.RandBytes(args.n)))
|
|
1395
|
+
console.print(base.BytesToHex(base.RandBytes(args.n)))
|
|
1388
1396
|
case 'prime':
|
|
1389
|
-
print(modmath.NBitRandomPrimes(args.bits).pop())
|
|
1397
|
+
console.print(modmath.NBitRandomPrimes(args.bits).pop())
|
|
1390
1398
|
case _:
|
|
1391
1399
|
raise NotImplementedError()
|
|
1392
1400
|
case 'hash':
|
|
@@ -1395,35 +1403,35 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1395
1403
|
case 'sha256':
|
|
1396
1404
|
bt = _BytesFromText(args.data, in_format)
|
|
1397
1405
|
digest: bytes = base.Hash256(bt)
|
|
1398
|
-
print(_BytesToText(digest, out_format))
|
|
1406
|
+
console.print(_BytesToText(digest, out_format))
|
|
1399
1407
|
case 'sha512':
|
|
1400
1408
|
bt = _BytesFromText(args.data, in_format)
|
|
1401
1409
|
digest = base.Hash512(bt)
|
|
1402
|
-
print(_BytesToText(digest, out_format))
|
|
1410
|
+
console.print(_BytesToText(digest, out_format))
|
|
1403
1411
|
case 'file':
|
|
1404
1412
|
digest = base.FileHash(args.path, digest=args.digest)
|
|
1405
|
-
print(_BytesToText(digest, out_format))
|
|
1413
|
+
console.print(_BytesToText(digest, out_format))
|
|
1406
1414
|
case _:
|
|
1407
1415
|
raise NotImplementedError()
|
|
1408
1416
|
|
|
1409
1417
|
# -------- AES / RSA / El-Gamal / DSA / SSS ----------
|
|
1410
1418
|
case 'aes':
|
|
1411
|
-
AESCommand(args, in_format, out_format)
|
|
1419
|
+
AESCommand(args, in_format, out_format, console)
|
|
1412
1420
|
|
|
1413
1421
|
case 'rsa':
|
|
1414
|
-
RSACommand(args, in_format, out_format)
|
|
1422
|
+
RSACommand(args, in_format, out_format, console)
|
|
1415
1423
|
|
|
1416
1424
|
case 'elgamal':
|
|
1417
|
-
ElGamalCommand(args, in_format, out_format)
|
|
1425
|
+
ElGamalCommand(args, in_format, out_format, console)
|
|
1418
1426
|
|
|
1419
1427
|
case 'dsa':
|
|
1420
|
-
DSACommand(args, in_format, out_format)
|
|
1428
|
+
DSACommand(args, in_format, out_format, console)
|
|
1421
1429
|
|
|
1422
1430
|
case 'bid':
|
|
1423
|
-
BidCommand(args, in_format, out_format)
|
|
1431
|
+
BidCommand(args, in_format, out_format, console)
|
|
1424
1432
|
|
|
1425
1433
|
case 'sss':
|
|
1426
|
-
SSSCommand(args, in_format, out_format)
|
|
1434
|
+
SSSCommand(args, in_format, out_format, console)
|
|
1427
1435
|
|
|
1428
1436
|
# -------- Documentation ----------
|
|
1429
1437
|
case 'doc':
|
|
@@ -1431,7 +1439,7 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1431
1439
|
args.doc_command.lower().strip() if getattr(args, 'doc_command', '') else '')
|
|
1432
1440
|
match doc_command:
|
|
1433
1441
|
case 'md':
|
|
1434
|
-
print(base.GenerateCLIMarkdown(
|
|
1442
|
+
console.print(base.GenerateCLIMarkdown(
|
|
1435
1443
|
'transcrypto', _BuildParser(), description=(
|
|
1436
1444
|
'`transcrypto` is a command-line utility that provides access to all core '
|
|
1437
1445
|
'functionality described in this documentation. It serves as a convenient '
|
|
@@ -1446,9 +1454,9 @@ def main(argv: list[str] | None = None, /) -> int: # pylint: disable=invalid-na
|
|
|
1446
1454
|
parser.print_help()
|
|
1447
1455
|
|
|
1448
1456
|
except NotImplementedError as err:
|
|
1449
|
-
print(f'Invalid command: {err}')
|
|
1457
|
+
console.print(f'Invalid command: {err}')
|
|
1450
1458
|
except (base.Error, ValueError) as err:
|
|
1451
|
-
print(str(err))
|
|
1459
|
+
console.print(str(err))
|
|
1452
1460
|
|
|
1453
1461
|
return 0
|
|
1454
1462
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: transcrypto
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
4
4
|
Summary: Basic crypto primitives, not intended for actual use, but as a companion to --Criptografia, Métodos e Algoritmos--
|
|
5
5
|
Author-email: Daniel Balparda <balparda@github.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -984,7 +984,7 @@ deactivate
|
|
|
984
984
|
|
|
985
985
|
### Updating Dependencies
|
|
986
986
|
|
|
987
|
-
To update `poetry.lock` file to more current versions do `poetry update`, it will ignore the current lock, update, and rewrite the `poetry.lock` file.
|
|
987
|
+
To update `poetry.lock` file to more current versions do `poetry update`, it will ignore the current lock, update, and rewrite the `poetry.lock` file. If you have cache problems `poetry cache clear PyPI --all` will clean it.
|
|
988
988
|
|
|
989
989
|
To add a new dependency you should do:
|
|
990
990
|
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
transcrypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
transcrypto/aes.py,sha256=TRiON5hvtJoZFz1BaTlWtHOOnq_xK8iW13ajLsBPJ2M,11935
|
|
3
|
-
transcrypto/base.py,sha256=
|
|
3
|
+
transcrypto/base.py,sha256=HTuKgl_qz5gFLx62G0wTGLO5mW4YA5YlstuCusr9G74,63767
|
|
4
4
|
transcrypto/constants.py,sha256=rt7g7H3ga3r_U59YhewwtuFDzVLkB-Uzc9fEq91epX4,158419
|
|
5
5
|
transcrypto/dsa.py,sha256=dc6__0YS2B_xbN4UnhX120GMyWid6qg6iopEimTnoxs,20505
|
|
6
6
|
transcrypto/elgamal.py,sha256=uR0bJ7A13UrAZynW6QRWJZhe86ZvoozaO5U9rDpam_I,21350
|
|
7
7
|
transcrypto/modmath.py,sha256=RVwszAQA5kdMe5k1Fb3bQiO3NK0kujYeQHo76CVuWqc,21266
|
|
8
|
-
transcrypto/profiler.py,sha256=
|
|
8
|
+
transcrypto/profiler.py,sha256=nJRQzb_aSBtjKOO7naJS2EQim7dnWBJLtDihlhJvAG8,7628
|
|
9
9
|
transcrypto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
transcrypto/rsa.py,sha256=3SYUEGOdHn_8UbezzocyQA8bkytL7d_d9rudsv4Zx9A,24926
|
|
11
|
-
transcrypto/safetrans.py,sha256=
|
|
11
|
+
transcrypto/safetrans.py,sha256=JNeTeldkxdmB5Ca1t8ZKP5wrYkJ1jAal8AOKjy9H9vc,57011
|
|
12
12
|
transcrypto/sss.py,sha256=Jl7pa1fleNQ-1kvneaeO-B2PfM0ilNKTYw4vVJ5WGwc,17100
|
|
13
|
-
transcrypto/transcrypto.py,sha256=
|
|
14
|
-
transcrypto-1.
|
|
15
|
-
transcrypto-1.
|
|
16
|
-
transcrypto-1.
|
|
17
|
-
transcrypto-1.
|
|
18
|
-
transcrypto-1.
|
|
13
|
+
transcrypto/transcrypto.py,sha256=gQpFGzqTwEy2unct3ettopbdokzjyfTaW6BWy838XKc,72105
|
|
14
|
+
transcrypto-1.6.0.dist-info/licenses/LICENSE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174
|
|
15
|
+
transcrypto-1.6.0.dist-info/METADATA,sha256=5N1FL_NtQwHypHw65QeTjTDkWktZecuqbZzAGGCt2tg,37969
|
|
16
|
+
transcrypto-1.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
17
|
+
transcrypto-1.6.0.dist-info/top_level.txt,sha256=9IfB0nGtVzQbYok5QIYNOy3coDv2UKX2OZtlFyxFDDQ,12
|
|
18
|
+
transcrypto-1.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|