transcrypto 1.1.2__tar.gz → 1.3.0__tar.gz

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.
Files changed (22) hide show
  1. {transcrypto-1.1.2/src/transcrypto.egg-info → transcrypto-1.3.0}/PKG-INFO +732 -427
  2. {transcrypto-1.1.2 → transcrypto-1.3.0}/README.md +731 -426
  3. {transcrypto-1.1.2 → transcrypto-1.3.0}/pyproject.toml +6 -3
  4. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto/aes.py +4 -3
  5. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto/base.py +84 -30
  6. transcrypto-1.3.0/src/transcrypto/dsa.py +513 -0
  7. transcrypto-1.3.0/src/transcrypto/elgamal.py +530 -0
  8. transcrypto-1.3.0/src/transcrypto/modmath.py +982 -0
  9. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto/rsa.py +220 -36
  10. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto/sss.py +160 -23
  11. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto/transcrypto.py +429 -191
  12. {transcrypto-1.1.2 → transcrypto-1.3.0/src/transcrypto.egg-info}/PKG-INFO +732 -427
  13. transcrypto-1.1.2/src/transcrypto/dsa.py +0 -336
  14. transcrypto-1.1.2/src/transcrypto/elgamal.py +0 -333
  15. transcrypto-1.1.2/src/transcrypto/modmath.py +0 -535
  16. {transcrypto-1.1.2 → transcrypto-1.3.0}/LICENSE +0 -0
  17. {transcrypto-1.1.2 → transcrypto-1.3.0}/setup.cfg +0 -0
  18. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto/__init__.py +0 -0
  19. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto/py.typed +0 -0
  20. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto.egg-info/SOURCES.txt +0 -0
  21. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto.egg-info/dependency_links.txt +0 -0
  22. {transcrypto-1.1.2 → transcrypto-1.3.0}/src/transcrypto.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: transcrypto
3
- Version: 1.1.2
3
+ Version: 1.3.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
@@ -61,69 +61,78 @@ Started in July/2025, by Daniel Balparda. Since version 1.0.2 it is PyPI package
61
61
  - [`aes ecb decrypt`](#aes-ecb-decrypt)
62
62
  - [`rsa`](#rsa)
63
63
  - [`rsa new`](#rsa-new)
64
+ - [`rsa rawencrypt`](#rsa-rawencrypt)
64
65
  - [`rsa encrypt`](#rsa-encrypt)
66
+ - [`rsa rawdecrypt`](#rsa-rawdecrypt)
65
67
  - [`rsa decrypt`](#rsa-decrypt)
68
+ - [`rsa rawsign`](#rsa-rawsign)
66
69
  - [`rsa sign`](#rsa-sign)
70
+ - [`rsa rawverify`](#rsa-rawverify)
67
71
  - [`rsa verify`](#rsa-verify)
68
72
  - [`elgamal`](#elgamal)
69
73
  - [`elgamal shared`](#elgamal-shared)
70
74
  - [`elgamal new`](#elgamal-new)
75
+ - [`elgamal rawencrypt`](#elgamal-rawencrypt)
71
76
  - [`elgamal encrypt`](#elgamal-encrypt)
77
+ - [`elgamal rawdecrypt`](#elgamal-rawdecrypt)
72
78
  - [`elgamal decrypt`](#elgamal-decrypt)
79
+ - [`elgamal rawsign`](#elgamal-rawsign)
73
80
  - [`elgamal sign`](#elgamal-sign)
81
+ - [`elgamal rawverify`](#elgamal-rawverify)
74
82
  - [`elgamal verify`](#elgamal-verify)
75
83
  - [`dsa`](#dsa)
76
84
  - [`dsa shared`](#dsa-shared)
77
85
  - [`dsa new`](#dsa-new)
86
+ - [`dsa rawsign`](#dsa-rawsign)
78
87
  - [`dsa sign`](#dsa-sign)
88
+ - [`dsa rawverify`](#dsa-rawverify)
79
89
  - [`dsa verify`](#dsa-verify)
80
90
  - [`bid`](#bid)
81
91
  - [`bid new`](#bid-new)
82
92
  - [`bid verify`](#bid-verify)
83
93
  - [`sss`](#sss)
84
94
  - [`sss new`](#sss-new)
95
+ - [`sss rawshares`](#sss-rawshares)
85
96
  - [`sss shares`](#sss-shares)
97
+ - [`sss rawrecover`](#sss-rawrecover)
86
98
  - [`sss recover`](#sss-recover)
87
- - [`sss verify`](#sss-verify)
99
+ - [`sss rawverify`](#sss-rawverify)
88
100
  - [`doc`](#doc)
89
101
  - [`doc md`](#doc-md)
90
102
  - [Base Library](#base-library)
91
103
  - [Humanized Sizes (IEC binary)](#humanized-sizes-iec-binary)
92
104
  - [Humanized Decimal Quantities (SI)](#humanized-decimal-quantities-si)
93
105
  - [Humanized Durations](#humanized-durations)
106
+ - [Execution Timing](#execution-timing)
107
+ - [Context manager](#context-manager)
108
+ - [Decorator](#decorator)
109
+ - [Manual use](#manual-use)
110
+ - [Key points](#key-points)
111
+ - [Serialization Pipeline](#serialization-pipeline)
112
+ - [Serialize](#serialize)
113
+ - [DeSerialize](#deserialize)
94
114
  - [Cryptographically Secure Randomness](#cryptographically-secure-randomness)
95
115
  - [Fixed-size random integers](#fixed-size-random-integers)
96
116
  - [Uniform random integers in a range](#uniform-random-integers-in-a-range)
97
117
  - [In-place secure shuffle](#in-place-secure-shuffle)
98
118
  - [Random byte strings](#random-byte-strings)
99
119
  - [Computing the Greatest Common Divisor](#computing-the-greatest-common-divisor)
120
+ - [Fast Modular Arithmetic](#fast-modular-arithmetic)
121
+ - [Chinese Remainder Theorem (CRT) – Pair](#chinese-remainder-theorem-crt--pair)
122
+ - [Modular Polynomials \& Lagrange Interpolation](#modular-polynomials--lagrange-interpolation)
123
+ - [Primality testing \& Prime generators, Mersenne primes](#primality-testing--prime-generators-mersenne-primes)
100
124
  - [Cryptographic Hashing](#cryptographic-hashing)
101
125
  - [SHA-256 hashing](#sha-256-hashing)
102
126
  - [SHA-512 hashing](#sha-512-hashing)
103
127
  - [File hashing](#file-hashing)
104
- - [Execution Timing](#execution-timing)
105
- - [Context manager](#context-manager)
106
- - [Decorator](#decorator)
107
- - [Manual use](#manual-use)
108
- - [Key points](#key-points)
109
128
  - [Symmetric Encryption Interface](#symmetric-encryption-interface)
110
- - [Serialization Pipeline](#serialization-pipeline)
111
- - [Serialize](#serialize)
112
- - [DeSerialize](#deserialize)
113
129
  - [Crypto Objects General Properties (`CryptoKey`)](#crypto-objects-general-properties-cryptokey)
114
130
  - [AES-256 Symmetric Encryption](#aes-256-symmetric-encryption)
115
131
  - [Key creation](#key-creation)
116
132
  - [AES-256 + GCM (default)](#aes-256--gcm-default)
117
133
  - [AES-256 + ECB (unsafe, fixed block only)](#aes-256--ecb-unsafe-fixed-block-only)
118
- - [Fast Modular Arithmetic](#fast-modular-arithmetic)
119
- - [Chinese Remainder Theorem (CRT) – Pair](#chinese-remainder-theorem-crt--pair)
120
- - [Modular Polynomials \& Lagrange Interpolation](#modular-polynomials--lagrange-interpolation)
121
- - [Primality testing \& Prime generators, Mersenne primes](#primality-testing--prime-generators-mersenne-primes)
122
134
  - [RSA (Rivest-Shamir-Adleman) Public Cryptography](#rsa-rivest-shamir-adleman-public-cryptography)
123
135
  - [El-Gamal Public-Key Cryptography](#el-gamal-public-key-cryptography)
124
- - [Shared Public Key](#shared-public-key)
125
- - [Public Key](#public-key)
126
- - [Private Key](#private-key)
127
136
  - [DSA (Digital Signature Algorithm)](#dsa-digital-signature-algorithm)
128
137
  - [Security notes](#security-notes)
129
138
  - [Advanced: custom primes generator](#advanced-custom-primes-generator)
@@ -144,13 +153,13 @@ Unless required by applicable law or agreed to in writing, software distributed
144
153
 
145
154
  ## Design assumptions / Disclaimers
146
155
 
147
- - The library is built to have reference, reliable, simple implementations of math and crypto primitives.
156
+ - The library is built to have reference, reliable, simple implementations of math and crypto primitives (e.g. `RawEncrypt()`/`RawSign()` and friends plus all the low-level primality and modular arithmetic). The issue is not that the library is unsafe, it is that the library is full of places that allow you to shoot yourself in the foot if you don't know what you are doing.
157
+ - The library also has advanced top-level methods that are cryptographically safe and might be used in real-world scenarios (e.g. `Encrypt()`/`Sign()` and friends).
148
158
  - All library methods' `int` are tailored to be efficient with arbitrarily large integers.
149
- - Everything **should work**, as the library is **extensively tested**, *but not necessarily the most efficient or safe for real-world cryptographic use.* For real-world crypto use *other optimized/safe libraries* that were built to be resistant to malicious attacks.
150
- - *All operations in this library may be vulnerable to timing attacks.*
151
- - There is some logging and error messages that were written to be clear but in real-life security applications could leak private secrets. Again, this library is not build to be crypto safe. It was built as a simple tested reference implementation.
159
+ - Everything **should work**, as the library is **extensively tested**, *but not necessarily the most efficient or safe for real-world cryptographic use.* For real-world crypto you might consider *other optimized/safe libraries* that were built to be resistant to malicious attacks.
160
+ - *All operations in this library may be vulnerable to timing attacks.* This may be a problem to your use-case or not depending on the situation.
152
161
 
153
- That being said, all care was taken that this is a good library with a solid implementation. *Have fun!*
162
+ All that being said, extreme care was taken that this is a good library with a solid safe implementation. *Have fun!*
154
163
 
155
164
  ## Install
156
165
 
@@ -188,7 +197,7 @@ poetry run transcrypto <command> [sub-command] [options...]
188
197
  |---|---|
189
198
  | `-v, --verbose` | Increase verbosity (use -v/-vv/-vvv/-vvvv for ERROR/WARN/INFO/DEBUG) |
190
199
  | `--hex` | Treat inputs as hex string (default) |
191
- | `--b64` | Treat inputs as base64url |
200
+ | `--b64` | Treat inputs as base64url; sometimes base64 will start with "-" and that can conflict with flags, so use "--" before positional args if needed |
192
201
  | `--bin` | Treat inputs as binary (bytes) |
193
202
  | `--out-hex` | Outputs as hex (default) |
194
203
  | `--out-b64` | Outputs as base64url |
@@ -207,11 +216,11 @@ poetry run transcrypto <command> [sub-command] [options...]
207
216
  - **`mod`** — `poetry run transcrypto mod [-h] {inv,div,exp,poly,lagrange,crt} ...`
208
217
  - **`hash`** — `poetry run transcrypto hash [-h] {sha256,sha512,file} ...`
209
218
  - **`aes`** — `poetry run transcrypto aes [-h] {key,encrypt,decrypt,ecb} ...`
210
- - **`rsa`** — `poetry run transcrypto rsa [-h] {new,encrypt,decrypt,sign,verify} ...`
211
- - **`elgamal`** — `poetry run transcrypto elgamal [-h]`
212
- - **`dsa`** — `poetry run transcrypto dsa [-h] {shared,new,sign,verify} ...`
219
+ - **`rsa`** — `poetry run transcrypto rsa [-h] {new,rawencrypt,encrypt,rawdecrypt,decrypt,rawsign,sign,rawverify,verify} ...`
220
+ - **`elgamal`** — `poetry run transcrypto elgamal [-h] {shared,new,rawencrypt,encrypt,rawdecrypt,decrypt,rawsign,sign,rawverify,verify} ...`
221
+ - **`dsa`** — `poetry run transcrypto dsa [-h] {shared,new,rawsign,sign,rawverify,verify} ...`
213
222
  - **`bid`** — `poetry run transcrypto bid [-h] {new,verify} ...`
214
- - **`sss`** — `poetry run transcrypto sss [-h] {new,shares,recover,verify} ...`
223
+ - **`sss`** — `poetry run transcrypto sss [-h] {new,rawshares,shares,rawrecover,recover,rawverify} ...`
215
224
  - **`doc`** — `poetry run transcrypto doc [-h] {md} ...`
216
225
 
217
226
  ```bash
@@ -240,36 +249,49 @@ Examples:
240
249
 
241
250
  # --- Hashing ---
242
251
  poetry run transcrypto hash sha256 xyz
243
- poetry run transcrypto --b64 hash sha512 eHl6
252
+ poetry run transcrypto --b64 hash sha512 -- eHl6
244
253
  poetry run transcrypto hash file /etc/passwd --digest sha512
245
254
 
246
255
  # --- AES ---
247
256
  poetry run transcrypto --out-b64 aes key "correct horse battery staple"
248
- poetry run transcrypto --b64 --out-b64 aes encrypt -k "<b64key>" "secret"
249
- poetry run transcrypto --b64 --out-b64 aes decrypt -k "<b64key>" "<ciphertext>"
257
+ poetry run transcrypto --b64 --out-b64 aes encrypt -k "<b64key>" -- "secret"
258
+ poetry run transcrypto --b64 --out-b64 aes decrypt -k "<b64key>" -- "<ciphertext>"
250
259
  poetry run transcrypto aes ecb -k "<b64key>" encrypt "<128bithexblock>"
251
260
  poetry run transcrypto aes ecb -k "<b64key>" decrypt "<128bithexblock>"
252
261
 
253
262
  # --- RSA ---
254
263
  poetry run transcrypto -p rsa-key rsa new --bits 2048
255
- poetry run transcrypto -p rsa-key.pub rsa encrypt <plaintext>
256
- poetry run transcrypto -p rsa-key.priv rsa decrypt <ciphertext>
257
- poetry run transcrypto -p rsa-key.priv rsa sign <message>
258
- poetry run transcrypto -p rsa-key.pub rsa verify <message> <signature>
264
+ poetry run transcrypto -p rsa-key.pub rsa rawencrypt <plaintext>
265
+ poetry run transcrypto -p rsa-key.priv rsa rawdecrypt <ciphertext>
266
+ poetry run transcrypto -p rsa-key.priv rsa rawsign <message>
267
+ poetry run transcrypto -p rsa-key.pub rsa rawverify <message> <signature>
268
+
269
+ poetry run transcrypto --bin --out-b64 -p rsa-key.pub rsa encrypt -a <aad> <plaintext>
270
+ poetry run transcrypto --b64 --out-bin -p rsa-key.priv rsa decrypt -a <aad> -- <ciphertext>
271
+ poetry run transcrypto --bin --out-b64 -p rsa-key.priv rsa sign <message>
272
+ poetry run transcrypto --b64 -p rsa-key.pub rsa verify -- <message> <signature>
259
273
 
260
274
  # --- ElGamal ---
261
275
  poetry run transcrypto -p eg-key elgamal shared --bits 2048
262
276
  poetry run transcrypto -p eg-key elgamal new
263
- poetry run transcrypto -p eg-key.pub elgamal encrypt <plaintext>
264
- poetry run transcrypto -p eg-key.priv elgamal decrypt <c1:c2>
265
- poetry run transcrypto -p eg-key.priv elgamal sign <message>
266
- poetry run transcrypto-p eg-key.pub elgamal verify <message> <s1:s2>
277
+ poetry run transcrypto -p eg-key.pub elgamal rawencrypt <plaintext>
278
+ poetry run transcrypto -p eg-key.priv elgamal rawdecrypt <c1:c2>
279
+ poetry run transcrypto -p eg-key.priv elgamal rawsign <message>
280
+ poetry run transcrypto-p eg-key.pub elgamal rawverify <message> <s1:s2>
281
+
282
+ poetry run transcrypto --bin --out-b64 -p eg-key.pub elgamal encrypt <plaintext>
283
+ poetry run transcrypto --b64 --out-bin -p eg-key.priv elgamal decrypt -- <ciphertext>
284
+ poetry run transcrypto --bin --out-b64 -p eg-key.priv elgamal sign <message>
285
+ poetry run transcrypto --b64 -p eg-key.pub elgamal verify -- <message> <signature>
267
286
 
268
287
  # --- DSA ---
269
288
  poetry run transcrypto -p dsa-key dsa shared --p-bits 2048 --q-bits 256
270
289
  poetry run transcrypto -p dsa-key dsa new
271
- poetry run transcrypto -p dsa-key.priv dsa sign <message>
272
- poetry run transcrypto -p dsa-key.pub dsa verify <message> <s1:s2>
290
+ poetry run transcrypto -p dsa-key.priv dsa rawsign <message>
291
+ poetry run transcrypto -p dsa-key.pub dsa rawverify <message> <s1:s2>
292
+
293
+ poetry run transcrypto --bin --out-b64 -p dsa-key.priv dsa sign <message>
294
+ poetry run transcrypto --b64 -p dsa-key.pub dsa verify -- <message> <signature>
273
295
 
274
296
  # --- Public Bid ---
275
297
  poetry run transcrypto --bin bid new "tomorrow it will rain"
@@ -277,9 +299,11 @@ Examples:
277
299
 
278
300
  # --- Shamir Secret Sharing (SSS) ---
279
301
  poetry run transcrypto -p sss-key sss new 3 --bits 1024
280
- poetry run transcrypto -p sss-key sss shares <secret> 5
281
- poetry run transcrypto -p sss-key sss recover
282
- poetry run transcrypto -p sss-key sss verify <secret>
302
+ poetry run transcrypto -p sss-key sss rawshares <secret> <n>
303
+ poetry run transcrypto -p sss-key sss rawrecover
304
+ poetry run transcrypto -p sss-key sss rawverify <secret> poetry run transcrypto --bin -p sss-key sss shares <secret> <n>
305
+ poetry run transcrypto --out-bin -p sss-key sss recover
306
+
283
307
  ```
284
308
 
285
309
  ---
@@ -674,7 +698,7 @@ poetry run transcrypto hash sha256 [-h] data
674
698
  ```bash
675
699
  $ poetry run transcrypto --bin hash sha256 xyz
676
700
  3608bca1e44ea6c4d268eb6db02260269892c0b42b86bbf1e77a6fa16c3c9282
677
- $ poetry run transcrypto --b64 hash sha256 eHl6 # "xyz" in base-64
701
+ $ poetry run transcrypto --b64 hash sha256 -- eHl6 # "xyz" in base-64
678
702
  3608bca1e44ea6c4d268eb6db02260269892c0b42b86bbf1e77a6fa16c3c9282
679
703
  ```
680
704
 
@@ -695,7 +719,7 @@ poetry run transcrypto hash sha512 [-h] data
695
719
  ```bash
696
720
  $ poetry run transcrypto --bin hash sha512 xyz
697
721
  4a3ed8147e37876adc8f76328e5abcc1b470e6acfc18efea0135f983604953a58e183c1a6086e91ba3e821d926f5fdeb37761c7ca0328a963f5e92870675b728
698
- $ poetry run transcrypto --b64 hash sha512 eHl6 # "xyz" in base-64
722
+ $ poetry run transcrypto --b64 hash sha512 -- eHl6 # "xyz" in base-64
699
723
  4a3ed8147e37876adc8f76328e5abcc1b470e6acfc18efea0135f983604953a58e183c1a6086e91ba3e821d926f5fdeb37761c7ca0328a963f5e92870675b728
700
724
  ```
701
725
 
@@ -767,9 +791,9 @@ poetry run transcrypto aes encrypt [-h] [-k KEY] [-a AAD] plaintext
767
791
  **Example:**
768
792
 
769
793
  ```bash
770
- $ poetry run transcrypto --b64 --out-b64 aes encrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= AAAAAAB4eXo=
794
+ $ poetry run transcrypto --b64 --out-b64 aes encrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -- AAAAAAB4eXo=
771
795
  F2_ZLrUw5Y8oDnbTP5t5xCUWX8WtVILLD0teyUi_37_4KHeV-YowVA==
772
- $ poetry run transcrypto --b64 --out-b64 aes encrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -a eHl6 AAAAAAB4eXo=
796
+ $ poetry run transcrypto --b64 --out-b64 aes encrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -a eHl6 -- AAAAAAB4eXo=
773
797
  xOlAHPUPpeyZHId-f3VQ_QKKMxjIW0_FBo9WOfIBrzjn0VkVV6xTRA==
774
798
  ```
775
799
 
@@ -790,9 +814,9 @@ poetry run transcrypto aes decrypt [-h] [-k KEY] [-a AAD] ciphertext
790
814
  **Example:**
791
815
 
792
816
  ```bash
793
- $ poetry run transcrypto --b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= F2_ZLrUw5Y8oDnbTP5t5xCUWX8WtVILLD0teyUi_37_4KHeV-YowVA==
817
+ $ poetry run transcrypto --b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -- F2_ZLrUw5Y8oDnbTP5t5xCUWX8WtVILLD0teyUi_37_4KHeV-YowVA==
794
818
  AAAAAAB4eXo=
795
- $ poetry run transcrypto --b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -a eHl6 xOlAHPUPpeyZHId-f3VQ_QKKMxjIW0_FBo9WOfIBrzjn0VkVV6xTRA==
819
+ $ poetry run transcrypto --b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -a eHl6 -- xOlAHPUPpeyZHId-f3VQ_QKKMxjIW0_FBo9WOfIBrzjn0VkVV6xTRA==
796
820
  AAAAAAB4eXo=
797
821
  ```
798
822
 
@@ -850,10 +874,11 @@ $ poetry run transcrypto --b64 aes ecb -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_
850
874
 
851
875
  ### `rsa`
852
876
 
853
- Raw RSA (Rivest-Shamir-Adleman) asymmetric cryptography over *integers* (BEWARE: no OAEP/PSS padding or validation). These are pedagogical/raw primitives; do not use for new protocols. No measures are taken here to prevent timing attacks. All methods require file key(s) as `-p`/`--key-path` (see provided examples).
877
+ RSA (Rivest-Shamir-Adleman) asymmetric cryptography. No measures are taken here to prevent timing attacks. All methods require file key(s) as `-p`/`--key-path` (see provided examples).
854
878
 
855
879
  ```bash
856
- poetry run transcrypto rsa [-h] {new,encrypt,decrypt,sign,verify} ...
880
+ poetry run transcrypto rsa [-h]
881
+ {new,rawencrypt,encrypt,rawdecrypt,decrypt,rawsign,sign,rawverify,verify} ...
857
882
  ```
858
883
 
859
884
  #### `rsa new`
@@ -875,12 +900,12 @@ $ poetry run transcrypto -p rsa-key rsa new --bits 64 # NEVER use such a small
875
900
  RSA private/public keys saved to 'rsa-key.priv/.pub'
876
901
  ```
877
902
 
878
- #### `rsa encrypt`
903
+ #### `rsa rawencrypt`
879
904
 
880
- Encrypt integer `message` with public key.
905
+ Raw encrypt *integer* `message` with public key (BEWARE: no OAEP/PSS padding or validation).
881
906
 
882
907
  ```bash
883
- poetry run transcrypto rsa encrypt [-h] message
908
+ poetry run transcrypto rsa rawencrypt [-h] message
884
909
  ```
885
910
 
886
911
  | Option/Arg | Description |
@@ -890,16 +915,36 @@ poetry run transcrypto rsa encrypt [-h] message
890
915
  **Example:**
891
916
 
892
917
  ```bash
893
- $ poetry run transcrypto -p rsa-key.pub rsa encrypt 999
918
+ $ poetry run transcrypto -p rsa-key.pub rsa rawencrypt 999
894
919
  6354905961171348600
895
920
  ```
896
921
 
897
- #### `rsa decrypt`
922
+ #### `rsa encrypt`
923
+
924
+ Encrypt `message` with public key.
925
+
926
+ ```bash
927
+ poetry run transcrypto rsa encrypt [-h] [-a AAD] plaintext
928
+ ```
929
+
930
+ | Option/Arg | Description |
931
+ |---|---|
932
+ | `plaintext` | Message to encrypt [type: str] |
933
+ | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
934
+
935
+ **Example:**
936
+
937
+ ```bash
938
+ $ poetry run transcrypto --bin --out-b64 -p rsa-key.pub rsa encrypt "abcde" -a "xyz"
939
+ AO6knI6xwq6TGR…Qy22jiFhXi1eQ==
940
+ ```
898
941
 
899
- Decrypt integer `ciphertext` with private key.
942
+ #### `rsa rawdecrypt`
943
+
944
+ Raw decrypt *integer* `ciphertext` with private key (BEWARE: no OAEP/PSS padding or validation).
900
945
 
901
946
  ```bash
902
- poetry run transcrypto rsa decrypt [-h] ciphertext
947
+ poetry run transcrypto rsa rawdecrypt [-h] ciphertext
903
948
  ```
904
949
 
905
950
  | Option/Arg | Description |
@@ -909,16 +954,36 @@ poetry run transcrypto rsa decrypt [-h] ciphertext
909
954
  **Example:**
910
955
 
911
956
  ```bash
912
- $ poetry run transcrypto -p rsa-key.priv rsa decrypt 6354905961171348600
957
+ $ poetry run transcrypto -p rsa-key.priv rsa rawdecrypt 6354905961171348600
913
958
  999
914
959
  ```
915
960
 
916
- #### `rsa sign`
961
+ #### `rsa decrypt`
962
+
963
+ Decrypt `ciphertext` with private key.
964
+
965
+ ```bash
966
+ poetry run transcrypto rsa decrypt [-h] [-a AAD] ciphertext
967
+ ```
968
+
969
+ | Option/Arg | Description |
970
+ |---|---|
971
+ | `ciphertext` | Ciphertext to decrypt [type: str] |
972
+ | `-a, --aad` | Associated data (optional; has to be exactly the same as used during encryption) [type: str] |
973
+
974
+ **Example:**
975
+
976
+ ```bash
977
+ $ poetry run transcrypto --b64 --out-bin -p rsa-key.priv rsa decrypt -a eHl6 -- AO6knI6xwq6TGR…Qy22jiFhXi1eQ==
978
+ abcde
979
+ ```
917
980
 
918
- Sign integer `message` with private key.
981
+ #### `rsa rawsign`
982
+
983
+ Raw sign *integer* `message` with private key (BEWARE: no OAEP/PSS padding or validation).
919
984
 
920
985
  ```bash
921
- poetry run transcrypto rsa sign [-h] message
986
+ poetry run transcrypto rsa rawsign [-h] message
922
987
  ```
923
988
 
924
989
  | Option/Arg | Description |
@@ -928,16 +993,36 @@ poetry run transcrypto rsa sign [-h] message
928
993
  **Example:**
929
994
 
930
995
  ```bash
931
- $ poetry run transcrypto -p rsa-key.priv rsa sign 999
996
+ $ poetry run transcrypto -p rsa-key.priv rsa rawsign 999
932
997
  7632909108672871784
933
998
  ```
934
999
 
935
- #### `rsa verify`
1000
+ #### `rsa sign`
1001
+
1002
+ Sign `message` with private key.
1003
+
1004
+ ```bash
1005
+ poetry run transcrypto rsa sign [-h] [-a AAD] message
1006
+ ```
1007
+
1008
+ | Option/Arg | Description |
1009
+ |---|---|
1010
+ | `message` | Message to sign [type: str] |
1011
+ | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
1012
+
1013
+ **Example:**
1014
+
1015
+ ```bash
1016
+ $ poetry run transcrypto --bin --out-b64 -p rsa-key.priv rsa sign "xyz"
1017
+ 91TS7gC6LORiL…6RD23Aejsfxlw==
1018
+ ```
936
1019
 
937
- Verify integer `signature` for integer `message` with public key.
1020
+ #### `rsa rawverify`
1021
+
1022
+ Raw verify *integer* `signature` for *integer* `message` with public key (BEWARE: no OAEP/PSS padding or validation).
938
1023
 
939
1024
  ```bash
940
- poetry run transcrypto rsa verify [-h] message signature
1025
+ poetry run transcrypto rsa rawverify [-h] message signature
941
1026
  ```
942
1027
 
943
1028
  | Option/Arg | Description |
@@ -948,9 +1033,32 @@ poetry run transcrypto rsa verify [-h] message signature
948
1033
  **Example:**
949
1034
 
950
1035
  ```bash
951
- $ poetry run transcrypto -p rsa-key.pub rsa verify 999 7632909108672871784
1036
+ $ poetry run transcrypto -p rsa-key.pub rsa rawverify 999 7632909108672871784
1037
+ RSA signature: OK
1038
+ $ poetry run transcrypto -p rsa-key.pub rsa rawverify 999 7632909108672871785
1039
+ RSA signature: INVALID
1040
+ ```
1041
+
1042
+ #### `rsa verify`
1043
+
1044
+ Verify `signature` for `message` with public key.
1045
+
1046
+ ```bash
1047
+ poetry run transcrypto rsa verify [-h] [-a AAD] message signature
1048
+ ```
1049
+
1050
+ | Option/Arg | Description |
1051
+ |---|---|
1052
+ | `message` | Message that was signed earlier [type: str] |
1053
+ | `signature` | Putative signature for `message` [type: str] |
1054
+ | `-a, --aad` | Associated data (optional; has to be exactly the same as used during signing) [type: str] |
1055
+
1056
+ **Example:**
1057
+
1058
+ ```bash
1059
+ $ poetry run transcrypto --b64 -p rsa-key.pub rsa verify -- eHl6 91TS7gC6LORiL…6RD23Aejsfxlw==
952
1060
  RSA signature: OK
953
- $ poetry run transcrypto -p rsa-key.pub rsa verify 999 7632909108672871785
1061
+ $ poetry run transcrypto --b64 -p rsa-key.pub rsa verify -- eLl6 91TS7gC6LORiL…6RD23Aejsfxlw==
954
1062
  RSA signature: INVALID
955
1063
  ```
956
1064
 
@@ -958,11 +1066,11 @@ RSA signature: INVALID
958
1066
 
959
1067
  ### `elgamal`
960
1068
 
961
- Raw El-Gamal asymmetric cryptography over *integers* (BEWARE: no ECIES-style KEM/DEM padding or validation). These are pedagogical/raw primitives; do not use for new protocols. No measures are taken here to prevent timing attacks. All methods require file key(s) as `-p`/`--key-path` (see provided examples).
1069
+ El-Gamal asymmetric cryptography. No measures are taken here to prevent timing attacks. All methods require file key(s) as `-p`/`--key-path` (see provided examples).
962
1070
 
963
1071
  ```bash
964
1072
  poetry run transcrypto elgamal [-h]
965
- {shared,new,encrypt,decrypt,sign,verify} ...
1073
+ {shared,new,rawencrypt,encrypt,rawdecrypt,decrypt,rawsign,sign,rawverify,verify} ...
966
1074
  ```
967
1075
 
968
1076
  #### `elgamal shared`
@@ -999,12 +1107,12 @@ $ poetry run transcrypto -p eg-key elgamal new
999
1107
  El-Gamal private/public keys saved to 'eg-key.priv/.pub'
1000
1108
  ```
1001
1109
 
1002
- #### `elgamal encrypt`
1110
+ #### `elgamal rawencrypt`
1003
1111
 
1004
- Encrypt integer `message` with public key.
1112
+ Raw encrypt *integer* `message` with public key (BEWARE: no ECIES-style KEM/DEM padding or validation).
1005
1113
 
1006
1114
  ```bash
1007
- poetry run transcrypto elgamal encrypt [-h] message
1115
+ poetry run transcrypto elgamal rawencrypt [-h] message
1008
1116
  ```
1009
1117
 
1010
1118
  | Option/Arg | Description |
@@ -1014,16 +1122,36 @@ poetry run transcrypto elgamal encrypt [-h] message
1014
1122
  **Example:**
1015
1123
 
1016
1124
  ```bash
1017
- $ poetry run transcrypto -p eg-key.pub elgamal encrypt 999
1125
+ $ poetry run transcrypto -p eg-key.pub elgamal rawencrypt 999
1018
1126
  2948854810728206041:15945988196340032688
1019
1127
  ```
1020
1128
 
1021
- #### `elgamal decrypt`
1129
+ #### `elgamal encrypt`
1130
+
1131
+ Encrypt `message` with public key.
1132
+
1133
+ ```bash
1134
+ poetry run transcrypto elgamal encrypt [-h] [-a AAD] plaintext
1135
+ ```
1022
1136
 
1023
- Decrypt integer `ciphertext` with private key.
1137
+ | Option/Arg | Description |
1138
+ |---|---|
1139
+ | `plaintext` | Message to encrypt [type: str] |
1140
+ | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
1141
+
1142
+ **Example:**
1143
+
1144
+ ```bash
1145
+ $ poetry run transcrypto --bin --out-b64 -p eg-key.pub elgamal encrypt "abcde" -a "xyz"
1146
+ CdFvoQ_IIPFPZLua…kqjhcUTspISxURg==
1147
+ ```
1148
+
1149
+ #### `elgamal rawdecrypt`
1150
+
1151
+ Raw decrypt *integer* `ciphertext` with private key (BEWARE: no ECIES-style KEM/DEM padding or validation).
1024
1152
 
1025
1153
  ```bash
1026
- poetry run transcrypto elgamal decrypt [-h] ciphertext
1154
+ poetry run transcrypto elgamal rawdecrypt [-h] ciphertext
1027
1155
  ```
1028
1156
 
1029
1157
  | Option/Arg | Description |
@@ -1033,16 +1161,36 @@ poetry run transcrypto elgamal decrypt [-h] ciphertext
1033
1161
  **Example:**
1034
1162
 
1035
1163
  ```bash
1036
- $ poetry run transcrypto -p eg-key.priv elgamal decrypt 2948854810728206041:15945988196340032688
1164
+ $ poetry run transcrypto -p eg-key.priv elgamal rawdecrypt 2948854810728206041:15945988196340032688
1037
1165
  999
1038
1166
  ```
1039
1167
 
1040
- #### `elgamal sign`
1168
+ #### `elgamal decrypt`
1169
+
1170
+ Decrypt `ciphertext` with private key.
1171
+
1172
+ ```bash
1173
+ poetry run transcrypto elgamal decrypt [-h] [-a AAD] ciphertext
1174
+ ```
1041
1175
 
1042
- Sign integer message with private key. Output will 2 integers in a `s1:s2` format.
1176
+ | Option/Arg | Description |
1177
+ |---|---|
1178
+ | `ciphertext` | Ciphertext to decrypt [type: str] |
1179
+ | `-a, --aad` | Associated data (optional; has to be exactly the same as used during encryption) [type: str] |
1180
+
1181
+ **Example:**
1182
+
1183
+ ```bash
1184
+ $ poetry run transcrypto --b64 --out-bin -p eg-key.priv elgamal decrypt -a eHl6 -- CdFvoQ_IIPFPZLua…kqjhcUTspISxURg==
1185
+ abcde
1186
+ ```
1187
+
1188
+ #### `elgamal rawsign`
1189
+
1190
+ Raw sign *integer* message with private key (BEWARE: no ECIES-style KEM/DEM padding or validation). Output will 2 *integers* in a `s1:s2` format.
1043
1191
 
1044
1192
  ```bash
1045
- poetry run transcrypto elgamal sign [-h] message
1193
+ poetry run transcrypto elgamal rawsign [-h] message
1046
1194
  ```
1047
1195
 
1048
1196
  | Option/Arg | Description |
@@ -1052,16 +1200,36 @@ poetry run transcrypto elgamal sign [-h] message
1052
1200
  **Example:**
1053
1201
 
1054
1202
  ```bash
1055
- $ poetry run transcrypto -p eg-key.priv elgamal sign 999
1203
+ $ poetry run transcrypto -p eg-key.priv elgamal rawsign 999
1056
1204
  4674885853217269088:14532144906178302633
1057
1205
  ```
1058
1206
 
1059
- #### `elgamal verify`
1207
+ #### `elgamal sign`
1208
+
1209
+ Sign message with private key.
1210
+
1211
+ ```bash
1212
+ poetry run transcrypto elgamal sign [-h] [-a AAD] message
1213
+ ```
1060
1214
 
1061
- Verify integer `signature` for integer `message` with public key.
1215
+ | Option/Arg | Description |
1216
+ |---|---|
1217
+ | `message` | Message to sign [type: str] |
1218
+ | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
1219
+
1220
+ **Example:**
1221
+
1222
+ ```bash
1223
+ $ poetry run transcrypto --bin --out-b64 -p eg-key.priv elgamal sign "xyz"
1224
+ Xl4hlYK8SHVGw…0fCKJE1XVzA==
1225
+ ```
1226
+
1227
+ #### `elgamal rawverify`
1228
+
1229
+ Raw verify *integer* `signature` for *integer* `message` with public key (BEWARE: no ECIES-style KEM/DEM padding or validation).
1062
1230
 
1063
1231
  ```bash
1064
- poetry run transcrypto elgamal verify [-h] message signature
1232
+ poetry run transcrypto elgamal rawverify [-h] message signature
1065
1233
  ```
1066
1234
 
1067
1235
  | Option/Arg | Description |
@@ -1072,9 +1240,32 @@ poetry run transcrypto elgamal verify [-h] message signature
1072
1240
  **Example:**
1073
1241
 
1074
1242
  ```bash
1075
- $ poetry run transcrypto -p eg-key.pub elgamal verify 999 4674885853217269088:14532144906178302633
1243
+ $ poetry run transcrypto -p eg-key.pub elgamal rawverify 999 4674885853217269088:14532144906178302633
1244
+ El-Gamal signature: OK
1245
+ $ poetry run transcrypto -p eg-key.pub elgamal rawverify 999 4674885853217269088:14532144906178302632
1246
+ El-Gamal signature: INVALID
1247
+ ```
1248
+
1249
+ #### `elgamal verify`
1250
+
1251
+ Verify `signature` for `message` with public key.
1252
+
1253
+ ```bash
1254
+ poetry run transcrypto elgamal verify [-h] [-a AAD] message signature
1255
+ ```
1256
+
1257
+ | Option/Arg | Description |
1258
+ |---|---|
1259
+ | `message` | Message that was signed earlier [type: str] |
1260
+ | `signature` | Putative signature for `message` [type: str] |
1261
+ | `-a, --aad` | Associated data (optional; has to be exactly the same as used during signing) [type: str] |
1262
+
1263
+ **Example:**
1264
+
1265
+ ```bash
1266
+ $ poetry run transcrypto --b64 -p eg-key.pub elgamal verify -- eHl6 Xl4hlYK8SHVGw…0fCKJE1XVzA==
1076
1267
  El-Gamal signature: OK
1077
- $ poetry run transcrypto -p eg-key.pub elgamal verify 999 4674885853217269088:14532144906178302632
1268
+ $ poetry run transcrypto --b64 -p eg-key.pub elgamal verify -- eLl6 Xl4hlYK8SHVGw…0fCKJE1XVzA==
1078
1269
  El-Gamal signature: INVALID
1079
1270
  ```
1080
1271
 
@@ -1082,15 +1273,16 @@ El-Gamal signature: INVALID
1082
1273
 
1083
1274
  ### `dsa`
1084
1275
 
1085
- Raw DSA (Digital Signature Algorithm) asymmetric signing over *integers* (BEWARE: no ECDSA/EdDSA padding or validation). These are pedagogical/raw primitives; do not use for new protocols. No measures are taken here to prevent timing attacks. All methods require file key(s) as `-p`/`--key-path` (see provided examples).
1276
+ DSA (Digital Signature Algorithm) asymmetric signing/verifying. No measures are taken here to prevent timing attacks. All methods require file key(s) as `-p`/`--key-path` (see provided examples).
1086
1277
 
1087
1278
  ```bash
1088
- poetry run transcrypto dsa [-h] {shared,new,sign,verify} ...
1279
+ poetry run transcrypto dsa [-h]
1280
+ {shared,new,rawsign,sign,rawverify,verify} ...
1089
1281
  ```
1090
1282
 
1091
1283
  #### `dsa shared`
1092
1284
 
1093
- Generate a shared DSA key with `p-bits`/`q-bits` prime modulus sizes, which is the first step in key generation. `q-bits` should be larger than the secrets that will be protected and `p-bits` should be much larger than `q-bits` (e.g. 3584/256). The shared key can safely be used by any number of users to generate their private/public key pairs (with the `new` command). The shared keys are "public". Requires `-p`/`--key-path` to set the basename for output files.
1285
+ Generate a shared DSA key with `p-bits`/`q-bits` prime modulus sizes, which is the first step in key generation. `q-bits` should be larger than the secrets that will be protected and `p-bits` should be much larger than `q-bits` (e.g. 4096/544). The shared key can safely be used by any number of users to generate their private/public key pairs (with the `new` command). The shared keys are "public". Requires `-p`/`--key-path` to set the basename for output files.
1094
1286
 
1095
1287
  ```bash
1096
1288
  poetry run transcrypto dsa shared [-h] [--p-bits P_BITS]
@@ -1099,8 +1291,8 @@ poetry run transcrypto dsa shared [-h] [--p-bits P_BITS]
1099
1291
 
1100
1292
  | Option/Arg | Description |
1101
1293
  |---|---|
1102
- | `--p-bits` | Prime modulus (`p`) size in bits; the default is a safe size [type: int (default: 3584)] |
1103
- | `--q-bits` | Prime modulus (`q`) size in bits; the default is a safe size ***IFF*** you are protecting symmetric keys or regular hashes [type: int (default: 256)] |
1294
+ | `--p-bits` | Prime modulus (`p`) size in bits; the default is a safe size [type: int (default: 4096)] |
1295
+ | `--q-bits` | Prime modulus (`q`) size in bits; the default is a safe size ***IFF*** you are protecting symmetric keys or regular hashes [type: int (default: 544)] |
1104
1296
 
1105
1297
  **Example:**
1106
1298
 
@@ -1124,12 +1316,12 @@ $ poetry run transcrypto -p dsa-key dsa new
1124
1316
  DSA private/public keys saved to 'dsa-key.priv/.pub'
1125
1317
  ```
1126
1318
 
1127
- #### `dsa sign`
1319
+ #### `dsa rawsign`
1128
1320
 
1129
- Sign integer message with private key. Output will 2 integers in a `s1:s2` format.
1321
+ Raw sign *integer* message with private key (BEWARE: no ECDSA/EdDSA padding or validation). Output will 2 *integers* in a `s1:s2` format.
1130
1322
 
1131
1323
  ```bash
1132
- poetry run transcrypto dsa sign [-h] message
1324
+ poetry run transcrypto dsa rawsign [-h] message
1133
1325
  ```
1134
1326
 
1135
1327
  | Option/Arg | Description |
@@ -1139,16 +1331,36 @@ poetry run transcrypto dsa sign [-h] message
1139
1331
  **Example:**
1140
1332
 
1141
1333
  ```bash
1142
- $ poetry run transcrypto -p dsa-key.priv dsa sign 999
1334
+ $ poetry run transcrypto -p dsa-key.priv dsa rawsign 999
1143
1335
  2395961484:3435572290
1144
1336
  ```
1145
1337
 
1146
- #### `dsa verify`
1338
+ #### `dsa sign`
1339
+
1340
+ Sign message with private key.
1341
+
1342
+ ```bash
1343
+ poetry run transcrypto dsa sign [-h] [-a AAD] message
1344
+ ```
1345
+
1346
+ | Option/Arg | Description |
1347
+ |---|---|
1348
+ | `message` | Message to sign [type: str] |
1349
+ | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
1350
+
1351
+ **Example:**
1352
+
1353
+ ```bash
1354
+ $ poetry run transcrypto --bin --out-b64 -p dsa-key.priv dsa sign "xyz"
1355
+ yq8InJVpViXh9…BD4par2XuA=
1356
+ ```
1147
1357
 
1148
- Verify integer `signature` for integer `message` with public key.
1358
+ #### `dsa rawverify`
1359
+
1360
+ Raw verify *integer* `signature` for *integer* `message` with public key (BEWARE: no ECDSA/EdDSA padding or validation).
1149
1361
 
1150
1362
  ```bash
1151
- poetry run transcrypto dsa verify [-h] message signature
1363
+ poetry run transcrypto dsa rawverify [-h] message signature
1152
1364
  ```
1153
1365
 
1154
1366
  | Option/Arg | Description |
@@ -1159,9 +1371,32 @@ poetry run transcrypto dsa verify [-h] message signature
1159
1371
  **Example:**
1160
1372
 
1161
1373
  ```bash
1162
- $ poetry run transcrypto -p dsa-key.pub dsa verify 999 2395961484:3435572290
1374
+ $ poetry run transcrypto -p dsa-key.pub dsa rawverify 999 2395961484:3435572290
1375
+ DSA signature: OK
1376
+ $ poetry run transcrypto -p dsa-key.pub dsa rawverify 999 2395961484:3435572291
1377
+ DSA signature: INVALID
1378
+ ```
1379
+
1380
+ #### `dsa verify`
1381
+
1382
+ Verify `signature` for `message` with public key.
1383
+
1384
+ ```bash
1385
+ poetry run transcrypto dsa verify [-h] [-a AAD] message signature
1386
+ ```
1387
+
1388
+ | Option/Arg | Description |
1389
+ |---|---|
1390
+ | `message` | Message that was signed earlier [type: str] |
1391
+ | `signature` | Putative signature for `message` [type: str] |
1392
+ | `-a, --aad` | Associated data (optional; has to be exactly the same as used during signing) [type: str] |
1393
+
1394
+ **Example:**
1395
+
1396
+ ```bash
1397
+ $ poetry run transcrypto --b64 -p dsa-key.pub dsa verify -- eHl6 yq8InJVpViXh9…BD4par2XuA=
1163
1398
  DSA signature: OK
1164
- $ poetry run transcrypto -p dsa-key.pub dsa verify 999 2395961484:3435572291
1399
+ $ poetry run transcrypto --b64 -p dsa-key.pub dsa verify -- eLl6 yq8InJVpViXh9…BD4par2XuA=
1165
1400
  DSA signature: INVALID
1166
1401
  ```
1167
1402
 
@@ -1215,10 +1450,11 @@ tomorrow it will rain
1215
1450
 
1216
1451
  ### `sss`
1217
1452
 
1218
- Raw SSS (Shamir Shared Secret) secret sharing crypto scheme over *integers* (BEWARE: no modern message wrapping, padding or validation). These are pedagogical/raw primitives; do not use for new protocols. No measures are taken here to prevent timing attacks. All methods require file key(s) as `-p`/`--key-path` (see provided examples).
1453
+ SSS (Shamir Shared Secret) secret sharing crypto scheme. No measures are taken here to prevent timing attacks. All methods require file key(s) as `-p`/`--key-path` (see provided examples).
1219
1454
 
1220
1455
  ```bash
1221
- poetry run transcrypto sss [-h] {new,shares,recover,verify} ...
1456
+ poetry run transcrypto sss [-h]
1457
+ {new,rawshares,shares,rawrecover,recover,rawverify} ...
1222
1458
  ```
1223
1459
 
1224
1460
  #### `sss new`
@@ -1241,9 +1477,30 @@ $ poetry run transcrypto -p sss-key sss new 3 --bits 64 # NEVER use such a smal
1241
1477
  SSS private/public keys saved to 'sss-key.priv/.pub'
1242
1478
  ```
1243
1479
 
1480
+ #### `sss rawshares`
1481
+
1482
+ Raw shares: Issue `count` private shares for an *integer* `secret` (BEWARE: no modern message wrapping, padding or validation).
1483
+
1484
+ ```bash
1485
+ poetry run transcrypto sss rawshares [-h] secret count
1486
+ ```
1487
+
1488
+ | Option/Arg | Description |
1489
+ |---|---|
1490
+ | `secret` | Integer secret to be protected, 1≤`secret`<*modulus* [type: str] |
1491
+ | `count` | How many shares to produce; must be ≥ `minimum` used in `new` command or else the `secret` would become unrecoverable [type: int] |
1492
+
1493
+ **Example:**
1494
+
1495
+ ```bash
1496
+ $ poetry run transcrypto -p sss-key sss rawshares 999 5
1497
+ SSS 5 individual (private) shares saved to 'sss-key.share.1…5'
1498
+ $ rm sss-key.share.2 sss-key.share.4 # this is to simulate only having shares 1,3,5
1499
+ ```
1500
+
1244
1501
  #### `sss shares`
1245
1502
 
1246
- Issue `count` private shares for an integer `secret`.
1503
+ Shares: Issue `count` private shares for a `secret`.
1247
1504
 
1248
1505
  ```bash
1249
1506
  poetry run transcrypto sss shares [-h] secret count
@@ -1251,17 +1508,36 @@ poetry run transcrypto sss shares [-h] secret count
1251
1508
 
1252
1509
  | Option/Arg | Description |
1253
1510
  |---|---|
1254
- | `secret` | Integer secret to be protected, 1≤`secret`<*modulus* [type: str] |
1511
+ | `secret` | Secret to be protected [type: str] |
1255
1512
  | `count` | How many shares to produce; must be ≥ `minimum` used in `new` command or else the `secret` would become unrecoverable [type: int] |
1256
1513
 
1257
1514
  **Example:**
1258
1515
 
1259
1516
  ```bash
1260
- $ poetry run transcrypto -p sss-key sss shares 999 5
1517
+ $ poetry run transcrypto --bin -p sss-key sss shares "abcde" 5
1261
1518
  SSS 5 individual (private) shares saved to 'sss-key.share.1…5'
1262
1519
  $ rm sss-key.share.2 sss-key.share.4 # this is to simulate only having shares 1,3,5
1263
1520
  ```
1264
1521
 
1522
+ #### `sss rawrecover`
1523
+
1524
+ Raw recover *integer* secret from shares; will use any available shares that were found (BEWARE: no modern message wrapping, padding or validation).
1525
+
1526
+ ```bash
1527
+ poetry run transcrypto sss rawrecover [-h]
1528
+ ```
1529
+
1530
+ **Example:**
1531
+
1532
+ ```bash
1533
+ $ poetry run transcrypto -p sss-key sss rawrecover
1534
+ Loaded SSS share: 'sss-key.share.3'
1535
+ Loaded SSS share: 'sss-key.share.5'
1536
+ Loaded SSS share: 'sss-key.share.1' # using only 3 shares: number 2/4 are missing
1537
+ Secret:
1538
+ 999
1539
+ ```
1540
+
1265
1541
  #### `sss recover`
1266
1542
 
1267
1543
  Recover secret from shares; will use any available shares that were found.
@@ -1273,34 +1549,34 @@ poetry run transcrypto sss recover [-h]
1273
1549
  **Example:**
1274
1550
 
1275
1551
  ```bash
1276
- $ poetry run transcrypto -p sss-key sss recover
1552
+ $ poetry run transcrypto --out-bin -p sss-key sss recover
1277
1553
  Loaded SSS share: 'sss-key.share.3'
1278
1554
  Loaded SSS share: 'sss-key.share.5'
1279
1555
  Loaded SSS share: 'sss-key.share.1' # using only 3 shares: number 2/4 are missing
1280
1556
  Secret:
1281
- 999
1557
+ abcde
1282
1558
  ```
1283
1559
 
1284
- #### `sss verify`
1560
+ #### `sss rawverify`
1285
1561
 
1286
- Verify shares against a secret (private params).
1562
+ Raw verify shares against a secret (private params; BEWARE: no modern message wrapping, padding or validation).
1287
1563
 
1288
1564
  ```bash
1289
- poetry run transcrypto sss verify [-h] secret
1565
+ poetry run transcrypto sss rawverify [-h] secret
1290
1566
  ```
1291
1567
 
1292
1568
  | Option/Arg | Description |
1293
1569
  |---|---|
1294
- | `secret` | Integer secret used to generate the shares, 1≤`secret`<*modulus* [type: str] |
1570
+ | `secret` | Integer secret used to generate the shares [type: str] |
1295
1571
 
1296
1572
  **Example:**
1297
1573
 
1298
1574
  ```bash
1299
- $ poetry run transcrypto -p sss-key sss verify 999
1575
+ $ poetry run transcrypto -p sss-key sss rawverify 999
1300
1576
  SSS share 'sss-key.share.3' verification: OK
1301
1577
  SSS share 'sss-key.share.5' verification: OK
1302
1578
  SSS share 'sss-key.share.1' verification: OK
1303
- $ poetry run transcrypto -p sss-key sss verify 998
1579
+ $ poetry run transcrypto -p sss-key sss rawverify 998
1304
1580
  SSS share 'sss-key.share.3' verification: INVALID
1305
1581
  SSS share 'sss-key.share.5' verification: INVALID
1306
1582
  SSS share 'sss-key.share.1' verification: INVALID
@@ -1396,169 +1672,39 @@ Chooses an appropriate time unit based on magnitude and formats with fixed preci
1396
1672
  - special case: `0 → '0.00 s'`
1397
1673
  - errors: negative or non-finite inputs raise `InputError`
1398
1674
 
1399
- #### Cryptographically Secure Randomness
1675
+ #### Execution Timing
1400
1676
 
1401
- These helpers live in `base` and wrap Python’s `secrets` with additional checks and guarantees for crypto use-cases.
1677
+ A flexible timing utility that works as a **context manager**, **decorator**, or **manual timer object**.
1402
1678
 
1403
1679
  ```py
1404
1680
  from transcrypto import base
1681
+ import time
1405
1682
  ```
1406
1683
 
1407
- ##### Fixed-size random integers
1684
+ ##### Context manager
1408
1685
 
1409
1686
  ```py
1410
- # Generate a 256-bit integer (first bit always set)
1411
- r = base.RandBits(256)
1412
- assert r.bit_length() == 256
1687
+ with base.Timer('Block timing'):
1688
+ time.sleep(1.2)
1689
+ # → logs: "Block timing: 1.20 s" (default via logging.info)
1413
1690
  ```
1414
1691
 
1415
- Produces a crypto-secure random integer with exactly `n_bits` bits (`≥ 8`). The most significant bit is guaranteed to be `1`, so entropy is \~`n_bits−1` — negligible for large crypto sizes.
1416
-
1417
- - errors: `n_bits < 8` → `InputError`
1692
+ Starts timing on entry, stops on exit, and reports elapsed time automatically.
1418
1693
 
1419
- ##### Uniform random integers in a range
1694
+ ##### Decorator
1420
1695
 
1421
1696
  ```py
1422
- # Uniform between [10, 20] inclusive
1423
- n = base.RandInt(10, 20)
1424
- assert 10 <= n <= 20
1425
- ```
1697
+ @base.Timer('Function timing')
1698
+ def slow_function():
1699
+ time.sleep(0.8)
1426
1700
 
1427
- Returns a crypto-secure integer uniformly distributed over the closed interval `[min_int, max_int]`.
1701
+ slow_function()
1702
+ # → logs: "Function timing: 0.80 s"
1703
+ ```
1428
1704
 
1429
- - constraints: `min_int 0` and `< max_int`
1430
- - errors: invalid bounds → `InputError`
1705
+ Wraps a function so that each call is automatically timed.
1431
1706
 
1432
- ##### In-place secure shuffle
1433
-
1434
- ```py
1435
- deck = list(range(10))
1436
- base.RandShuffle(deck)
1437
- print(deck) # securely shuffled order
1438
- ```
1439
-
1440
- Performs an in-place Fisher–Yates shuffle using `secrets.randbelow`. Suitable for sensitive data ordering.
1441
-
1442
- - constraints: sequence length ≥ 2
1443
- - errors: shorter sequences → `InputError`
1444
-
1445
- ##### Random byte strings
1446
-
1447
- ```py
1448
- # 32 random bytes
1449
- b = base.RandBytes(32)
1450
- assert len(b) == 32
1451
- ```
1452
-
1453
- Generates `n_bytes` of high-quality crypto-secure random data.
1454
-
1455
- - constraints: `n_bytes ≥ 1`
1456
- - errors: smaller values → `InputError`
1457
-
1458
- #### Computing the Greatest Common Divisor
1459
-
1460
- ```py
1461
- >>> from transcrypto import base
1462
- >>> base.GCD(462, 1071)
1463
- 21
1464
- >>> base.GCD(0, 17)
1465
- 17
1466
- ```
1467
-
1468
- The function is `O(log(min(a, b)))` and handles arbitrarily large integers. To find Bézout coefficients `(x, y)` such that `ax + by = gcd(a, b)` do:
1469
-
1470
- ```py
1471
- >>> base.ExtendedGCD(462, 1071)
1472
- (21, -2, 1)
1473
- >>> 462 * -2 + 1071 * 1
1474
- 21
1475
- ```
1476
-
1477
- Use-cases:
1478
-
1479
- - modular inverses: `inv = x % m` when `gcd(a, m) == 1`
1480
- - solving linear Diophantine equations
1481
- - RSA / ECC key generation internals
1482
-
1483
- #### Cryptographic Hashing
1484
-
1485
- Simple, fixed-output-size wrappers over Python’s `hashlib` for common digest operations, plus file hashing.
1486
-
1487
- ```py
1488
- from transcrypto import base
1489
- ```
1490
-
1491
- ##### SHA-256 hashing
1492
-
1493
- ```py
1494
- h = base.Hash256(b'hello world')
1495
- assert len(h) == 32 # bytes
1496
- print(h.hex()) # 64 hex chars
1497
- ```
1498
-
1499
- Computes the SHA-256 digest of a byte string, returning exactly 32 bytes (256 bits). Suitable for fingerprints, commitments, or internal crypto primitives.
1500
-
1501
- ##### SHA-512 hashing
1502
-
1503
- ```py
1504
- h = base.Hash512(b'hello world')
1505
- assert len(h) == 64 # bytes
1506
- print(h.hex()) # 128 hex chars
1507
- ```
1508
-
1509
- Computes the SHA-512 digest of a byte string, returning exactly 64 bytes (512 bits). Higher collision resistance and larger output space than SHA-256.
1510
-
1511
- ##### File hashing
1512
-
1513
- ```py
1514
- # Default SHA-256
1515
- fh = base.FileHash('/path/to/file')
1516
- print(fh.hex())
1517
-
1518
- # SHA-512
1519
- fh2 = base.FileHash('/path/to/file', digest='sha512')
1520
- ```
1521
-
1522
- Hashes a file from disk in streaming mode. By default uses SHA-256; `digest='sha512'` switches to SHA-512.
1523
-
1524
- - constraints:
1525
- - `digest` must be `'sha256'` or `'sha512'`
1526
- - `full_path` must exist
1527
- - errors: invalid digest or missing file → `InputError`
1528
-
1529
- #### Execution Timing
1530
-
1531
- A flexible timing utility that works as a **context manager**, **decorator**, or **manual timer object**.
1532
-
1533
- ```py
1534
- from transcrypto import base
1535
- import time
1536
- ```
1537
-
1538
- ##### Context manager
1539
-
1540
- ```py
1541
- with base.Timer('Block timing'):
1542
- time.sleep(1.2)
1543
- # → logs: "Block timing: 1.20 s" (default via logging.info)
1544
- ```
1545
-
1546
- Starts timing on entry, stops on exit, and reports elapsed time automatically.
1547
-
1548
- ##### Decorator
1549
-
1550
- ```py
1551
- @base.Timer('Function timing')
1552
- def slow_function():
1553
- time.sleep(0.8)
1554
-
1555
- slow_function()
1556
- # → logs: "Function timing: 0.80 s"
1557
- ```
1558
-
1559
- Wraps a function so that each call is automatically timed.
1560
-
1561
- ##### Manual use
1707
+ ##### Manual use
1562
1708
 
1563
1709
  ```py
1564
1710
  tm = base.Timer('Inline timing', emit_print=True)
@@ -1582,21 +1728,6 @@ Manual control over `Start()` and `Stop()` for precise measurement of custom int
1582
1728
  - Cannot stop an unstarted or already stopped timer
1583
1729
  (raises `Error`)
1584
1730
 
1585
- #### Symmetric Encryption Interface
1586
-
1587
- `SymmetricCrypto` is an abstract base class that defines the **byte-in / byte-out** contract for symmetric ciphers.
1588
-
1589
- - **Metadata handling** — if the algorithm uses a `nonce` or `tag`, the implementation must handle it internally (e.g., append it to ciphertext).
1590
- - **AEAD modes** — if supported, `associated_data` must be authenticated; otherwise, a non-`None` value should raise `InputError`.
1591
-
1592
- ```py
1593
- class MyAES(base.SymmetricCrypto):
1594
- def Encrypt(self, plaintext: bytes, *, associated_data=None) -> bytes:
1595
- ...
1596
- def Decrypt(self, ciphertext: bytes, *, associated_data=None) -> bytes:
1597
- ...
1598
- ```
1599
-
1600
1731
  #### Serialization Pipeline
1601
1732
 
1602
1733
  These helpers turn arbitrary Python objects into compressed and/or encrypted binary blobs, and back again — with detailed timing and size logging.
@@ -1679,114 +1810,89 @@ data/file → (decrypt) → (decompress if Zstd) → unpickle
1679
1810
  - `file_path` must exist; `data` must be at least 4 bytes.
1680
1811
  - Wrong key or corrupted data can raise `CryptoError`.
1681
1812
 
1682
- #### Crypto Objects General Properties (`CryptoKey`)
1683
-
1684
- Cryptographic objects all derive from the `CryptoKey` class and will all have some important characteristics:
1685
-
1686
- - Will be safe to log and print, i.e., implement safe `__str__()` and `__repr__()` methods (in actuality `repr` will be exactly the same as `str`). The `__str__()` should always fully print the public parts of the object and obfuscate the private ones. This obfuscation allows for some debugging, if needed, but if the secrets are "too short" then it can be defeated by brute force. For usual crypto defaults the obfuscation is fine. The obfuscation is the fist 4 bytes of the SHA-512 for the value followed by an ellipsis (e.g. `c9626f16…`).
1687
- - It will have a `_DebugDump()` method that **does print secrets** and can be used for **debugging only**.
1688
- - Can be easily serialized to `bytes` by the `blob` property and to base-64 encoded `str` by the `encoded` property.
1689
- - Can be serialized encrypted to `bytes` by the `Blob(key=[SymmetricCrypto])` method and to encrypted base-64 encoded `str` by the `Encoded(key=[SymmetricCrypto])` method.
1690
- - Can be instantiated back as an object from `str` or `bytes` using the `Load(data, key=[SymmetricCrypto] | None)` method. The `Load()` will decide how to build the object and will work universally with all the serialization options discussed above.
1813
+ #### Cryptographically Secure Randomness
1691
1814
 
1692
- Example:
1815
+ These helpers live in `base` and wrap Python’s `secrets` with additional checks and guarantees for crypto use-cases.
1693
1816
 
1694
- <!-- cspell:disable -->
1695
1817
  ```py
1696
- from transcrypto import base, rsa, aes
1818
+ from transcrypto import base
1819
+ ```
1697
1820
 
1698
- priv = rsa.RSAPrivateKey.New(512) # small key, but good for this example
1699
- print(str(priv)) # safe, no secrets
1700
- # ▶ RSAPrivateKey(RSAPublicKey(public_modulus=pQaoxy-QeXSds1k9WsGjJw==, encrypt_exp=AQAB), modulus_p=f18141aa…, modulus_q=67494eb9…, decrypt_exp=c96db24a…)
1821
+ ##### Fixed-size random integers
1701
1822
 
1702
- print(priv._DebugDump()) # UNSAFE: prints secrets
1703
- # RSAPrivateKey(public_modulus=219357196311600536151291741191131996967, encrypt_exp=65537, modulus_p=13221374197986739361, modulus_q=16591104148992527047, decrypt_exp=37805202135275158391322585315542443073, remainder_p=9522084656682089473, remainder_q=8975656462800098363, q_inverse_p=11965562396596149292)
1823
+ ```py
1824
+ # Generate a 256-bit integer (first bit always set)
1825
+ r = base.RandBits(256)
1826
+ assert r.bit_length() == 256
1827
+ ```
1704
1828
 
1705
- print(priv.blob)
1706
- # ▶ b"(\xb5/\xfd \x98\xc1\x04\x00\x80\x04\x95\x8d\x00\x00\x00\x00\x00\x00\x00\x8c\x0ftranscrypto.rsa\x94\x8c\rRSAPrivateKey\x94\x93\x94)\x81\x94]\x94(\x8a\x11'\xa3\xc1Z=Y\xb3\x9dty\x90/\xc7\xa8\x06\xa5\x00J\x01\x00\x01\x00\x8a\t\xa1\xc4\x83\x81\xc8\xc1{\xb7\x00\x8a\t\xc7\x8a5\xf0Qq?\xe6\x00\x8a\x10A$&\x82!\x1cy\x89r\xef\xeb\xa7_\x04q\x1c\x8a\t\x01\xbc\xbb\x8a\x8b=%\x84\x00\x8a\x08;\x94#s\xff\xef\x8f|\x8a\t,\x9c\xe2z\x9a7\x0e\xa6\x00eb."
1829
+ Produces a crypto-secure random integer with exactly `n_bits` bits (`≥ 8`). The most significant bit is guaranteed to be `1`, so entropy is \~`n_bits−1` — negligible for large crypto sizes.
1707
1830
 
1708
- print(priv.encoded)
1709
- # ▶ KLUv_WBwAIELAIAElWUBAAAAAAAAjA90cmFuc2NyeXB0by5yc2GUjA1SU0FQcml2YXRlS2V5lJOUKYGUXZQoikHf1EvsmZedAZve7TrLmobLAwuRIr_77TLG6G_0fsLGThERVJu075be8PLjUQYnLXcacZFQ5Fb1Iy1WtiE985euAEoBAAEAiiFR9ngiXMzkf41o5CRBY3h0D4DJVisDDhLmAWsiaHggzQCKIS_cmQ6MKXCtROtC7c_Mrsi9A-9NM8DksaHaRwvy6uTZAIpB4TVbsLxc41TEc19wIzpxbi9y5dW5gdfTkRQSSiz0ijmb8Xk3pyBfKAv8JbHp8Yv48gNZUfX67qq0J7yhJqeUoACKIbFb2kTNRzSqm3JRtjc2BPS-FnLFdadlFcV4-6IW7eqLAIogFZfzDN39gZLR9uTz4KHSTaqxWrJgP8-YYssjss6FlFKKIIItgCDv7ompNpY8gBs5bibN8XTsr-JOYSntDVT5Fe5vZWIu
1831
+ - errors: `n_bits < 8` → `InputError`
1710
1832
 
1711
- key = aes.AESKey(key256=b'x' * 32)
1712
- print(key)
1713
- # ▶ AESKey(key256=86a86df7…)
1833
+ ##### Uniform random integers in a range
1714
1834
 
1715
- encrypted = priv.Blob(key=key)
1716
- print(priv == rsa.RSAPrivateKey.Load(encrypted, key=key))
1717
- # True
1835
+ ```py
1836
+ # Uniform between [10, 20] inclusive
1837
+ n = base.RandInt(10, 20)
1838
+ assert 10 <= n <= 20
1718
1839
  ```
1719
- <!-- cspell:enable -->
1720
1840
 
1721
- #### AES-256 Symmetric Encryption
1841
+ Returns a crypto-secure integer uniformly distributed over the closed interval `[min_int, max_int]`.
1722
1842
 
1723
- Implements AES-256 in **GCM mode** for authenticated encryption and decryption, plus an **ECB mode** helper for fixed-size block encoding.
1724
- Also includes a high-iteration PBKDF2-based key derivation from static passwords.
1843
+ - constraints: `min_int 0` and `< max_int`
1844
+ - errors: invalid bounds `InputError`
1725
1845
 
1726
- ##### Key creation
1846
+ ##### In-place secure shuffle
1727
1847
 
1728
1848
  ```py
1729
- from transcrypto import aes
1730
-
1731
- # From raw bytes (must be exactly 32 bytes)
1732
- key = aes.AESKey(key256=b'\x00' * 32)
1733
-
1734
- # From a static password (slow, high-iteration PBKDF2-SHA256)
1735
- key = aes.AESKey.FromStaticPassword('correct horse battery staple')
1736
- print(key.encoded) # URL-safe Base64
1849
+ deck = list(range(10))
1850
+ base.RandShuffle(deck)
1851
+ print(deck) # securely shuffled order
1737
1852
  ```
1738
1853
 
1739
- - **Length**: `key256` must be exactly 32 bytes
1740
- - `FromStaticPassword()`:
1741
- - Uses PBKDF2-HMAC-SHA256 with **fixed** salt and \~2 million iterations
1742
- - Designed for **interactive** password entry, **not** for password databases
1743
-
1744
- ##### AES-256 + GCM (default)
1854
+ Performs an in-place Fisher–Yates shuffle using `secrets.randbelow`. Suitable for sensitive data ordering.
1745
1855
 
1746
- ```py
1747
- data = b'secret message'
1748
- aad = b'metadata'
1856
+ - constraints: sequence length ≥ 2
1857
+ - errors: shorter sequences → `InputError`
1749
1858
 
1750
- # Encrypt (returns IV + ciphertext + tag)
1751
- ct = key.Encrypt(data, associated_data=aad)
1859
+ ##### Random byte strings
1752
1860
 
1753
- # Decrypt
1754
- pt = key.Decrypt(ct, associated_data=aad)
1755
- assert pt == data
1861
+ ```py
1862
+ # 32 random bytes
1863
+ b = base.RandBytes(32)
1864
+ assert len(b) == 32
1756
1865
  ```
1757
1866
 
1758
- - **Security**:
1759
- - Random 128-bit IV (`iv`) per encryption
1760
- - Authenticated tag (128-bit) ensures integrity
1761
- - Optional `associated_data` is authenticated but not encrypted
1762
- - **Errors**:
1763
- - Tag mismatch or wrong key → `CryptoError`
1867
+ Generates `n_bytes` of high-quality crypto-secure random data.
1764
1868
 
1765
- ##### AES-256 + ECB (unsafe, fixed block only)
1869
+ - constraints: `n_bytes 1`
1870
+ - errors: smaller values → `InputError`
1871
+
1872
+ #### Computing the Greatest Common Divisor
1766
1873
 
1767
1874
  ```py
1768
- # ECB mode is for 16-byte block encoding ONLY
1769
- ecb = key.ECBEncoder()
1875
+ >>> from transcrypto import base
1876
+ >>> base.GCD(462, 1071)
1877
+ 21
1878
+ >>> base.GCD(0, 17)
1879
+ 17
1880
+ ```
1770
1881
 
1771
- block = b'16-byte string!!'
1772
- ct_block = ecb.Encrypt(block)
1773
- pt_block = ecb.Decrypt(ct_block)
1774
- assert pt_block == block
1882
+ The function is `O(log(min(a, b)))` and handles arbitrarily large integers. To find Bézout coefficients `(x, y)` such that `ax + by = gcd(a, b)` do:
1775
1883
 
1776
- # Hex helpers
1777
- hex_ct = ecb.EncryptHex('00112233445566778899aabbccddeeff')
1884
+ ```py
1885
+ >>> base.ExtendedGCD(462, 1071)
1886
+ (21, -2, 1)
1887
+ >>> 462 * -2 + 1071 * 1
1888
+ 21
1778
1889
  ```
1779
1890
 
1780
- - **ECB mode**:
1781
- - 16-byte plaintext ↔ 16-byte ciphertext
1782
- - No padding, no IV, no integrity — **do not use for general encryption**
1783
- - `associated_data` not supported
1784
-
1785
- Key points:
1891
+ Use-cases:
1786
1892
 
1787
- - **GCM mode** is secure for general use; ECB mode is for special low-level operations
1788
- - **Static password derivation** is intentionally slow to resist brute force
1789
- - All sizes and parameters are validated with `InputError` on misuse
1893
+ - modular inverses: `inv = x % m` when `gcd(a, m) == 1`
1894
+ - solving linear Diophantine equations
1895
+ - RSA / ECC key generation internals
1790
1896
 
1791
1897
  #### Fast Modular Arithmetic
1792
1898
 
@@ -1809,7 +1915,7 @@ assert (z * y) % m == x % m
1809
1915
  exp = modmath.ModExp(3, 10**20, m) # ≈ log₂(y) time, handles huge exponents
1810
1916
  ```
1811
1917
 
1812
- #### Chinese Remainder Theorem (CRT) – Pair
1918
+ ##### Chinese Remainder Theorem (CRT) – Pair
1813
1919
 
1814
1920
  ```py
1815
1921
  from transcrypto import modmath
@@ -1840,7 +1946,7 @@ x ≡ a2 (mod m2)
1840
1946
 
1841
1947
  This function is a 2-modulus variant; for multiple moduli, apply it iteratively or use a general CRT solver.
1842
1948
 
1843
- #### Modular Polynomials & Lagrange Interpolation
1949
+ ##### Modular Polynomials & Lagrange Interpolation
1844
1950
 
1845
1951
  ```py
1846
1952
  # f(t) = 7t³ − 3t² + 2t + 5 (coefficients constant-term first)
@@ -1868,7 +1974,7 @@ for p in modmath.PrimeGenerator(1_000_000):
1868
1974
  break
1869
1975
 
1870
1976
  # Secure random 384-bit prime (for RSA/ECC experiments)
1871
- p384 = modmath.NBitRandomPrime(384)
1977
+ p384 = modmath.NBitRandomPrimes(384).pop()
1872
1978
 
1873
1979
  for k, m_p, perfect in modmath.MersennePrimesGenerator(0):
1874
1980
  print(f'p = {k:>8} M = {m_p} perfect = {perfect}')
@@ -1876,6 +1982,176 @@ for k, m_p, perfect in modmath.MersennePrimesGenerator(0):
1876
1982
  break
1877
1983
  ```
1878
1984
 
1985
+ #### Cryptographic Hashing
1986
+
1987
+ Simple, fixed-output-size wrappers over Python’s `hashlib` for common digest operations, plus file hashing.
1988
+
1989
+ ```py
1990
+ from transcrypto import base
1991
+ ```
1992
+
1993
+ ##### SHA-256 hashing
1994
+
1995
+ ```py
1996
+ h = base.Hash256(b'hello world')
1997
+ assert len(h) == 32 # bytes
1998
+ print(h.hex()) # 64 hex chars
1999
+ ```
2000
+
2001
+ Computes the SHA-256 digest of a byte string, returning exactly 32 bytes (256 bits). Suitable for fingerprints, commitments, or internal crypto primitives.
2002
+
2003
+ ##### SHA-512 hashing
2004
+
2005
+ ```py
2006
+ h = base.Hash512(b'hello world')
2007
+ assert len(h) == 64 # bytes
2008
+ print(h.hex()) # 128 hex chars
2009
+ ```
2010
+
2011
+ Computes the SHA-512 digest of a byte string, returning exactly 64 bytes (512 bits). Higher collision resistance and larger output space than SHA-256.
2012
+
2013
+ ##### File hashing
2014
+
2015
+ ```py
2016
+ # Default SHA-256
2017
+ fh = base.FileHash('/path/to/file')
2018
+ print(fh.hex())
2019
+
2020
+ # SHA-512
2021
+ fh2 = base.FileHash('/path/to/file', digest='sha512')
2022
+ ```
2023
+
2024
+ Hashes a file from disk in streaming mode. By default uses SHA-256; `digest='sha512'` switches to SHA-512.
2025
+
2026
+ - constraints:
2027
+ - `digest` must be `'sha256'` or `'sha512'`
2028
+ - `full_path` must exist
2029
+ - errors: invalid digest or missing file → `InputError`
2030
+
2031
+ #### Symmetric Encryption Interface
2032
+
2033
+ `SymmetricCrypto` is an abstract base class that defines the **byte-in / byte-out** contract for symmetric ciphers.
2034
+
2035
+ - **Metadata handling** — if the algorithm uses a `nonce` or `tag`, the implementation must handle it internally (e.g., append it to ciphertext).
2036
+ - **AEAD modes** — if supported, `associated_data` must be authenticated; otherwise, a non-`None` value should raise `InputError`.
2037
+
2038
+ ```py
2039
+ class MyAES(base.SymmetricCrypto):
2040
+ def Encrypt(self, plaintext: bytes, *, associated_data=None) -> bytes:
2041
+ ...
2042
+ def Decrypt(self, ciphertext: bytes, *, associated_data=None) -> bytes:
2043
+ ...
2044
+ ```
2045
+
2046
+ #### Crypto Objects General Properties (`CryptoKey`)
2047
+
2048
+ Cryptographic objects all derive from the `CryptoKey` class and will all have some important characteristics:
2049
+
2050
+ - Will be safe to log and print, i.e., implement safe `__str__()` and `__repr__()` methods (in actuality `repr` will be exactly the same as `str`). The `__str__()` should always fully print the public parts of the object and obfuscate the private ones. This obfuscation allows for some debugging, if needed, but if the secrets are "too short" then it can be defeated by brute force. For usual crypto defaults the obfuscation is fine. The obfuscation is the fist 4 bytes of the SHA-512 for the value followed by an ellipsis (e.g. `c9626f16…`).
2051
+ - It will have a `_DebugDump()` method that **does print secrets** and can be used for **debugging only**.
2052
+ - Can be easily serialized to `bytes` by the `blob` property and to base-64 encoded `str` by the `encoded` property.
2053
+ - Can be serialized encrypted to `bytes` by the `Blob(key=[SymmetricCrypto])` method and to encrypted base-64 encoded `str` by the `Encoded(key=[SymmetricCrypto])` method.
2054
+ - Can be instantiated back as an object from `str` or `bytes` using the `Load(data, key=[SymmetricCrypto] | None)` method. The `Load()` will decide how to build the object and will work universally with all the serialization options discussed above.
2055
+
2056
+ Example:
2057
+
2058
+ <!-- cspell:disable -->
2059
+ ```py
2060
+ from transcrypto import base, rsa, aes
2061
+
2062
+ priv = rsa.RSAPrivateKey.New(512) # small key, but good for this example
2063
+ print(str(priv)) # safe, no secrets
2064
+ # ▶ RSAPrivateKey(RSAPublicKey(public_modulus=pQaoxy-QeXSds1k9WsGjJw==, encrypt_exp=AQAB), modulus_p=f18141aa…, modulus_q=67494eb9…, decrypt_exp=c96db24a…)
2065
+
2066
+ print(priv._DebugDump()) # UNSAFE: prints secrets
2067
+ # ▶ RSAPrivateKey(public_modulus=219357196311600536151291741191131996967, encrypt_exp=65537, modulus_p=13221374197986739361, modulus_q=16591104148992527047, decrypt_exp=37805202135275158391322585315542443073, remainder_p=9522084656682089473, remainder_q=8975656462800098363, q_inverse_p=11965562396596149292)
2068
+
2069
+ print(priv.blob)
2070
+ # ▶ b"(\xb5/\xfd \x98\xc1\x04\x00\x80\x04\x95\x8d\x00\x00\x00\x00\x00\x00\x00\x8c\x0ftranscrypto.rsa\x94\x8c\rRSAPrivateKey\x94\x93\x94)\x81\x94]\x94(\x8a\x11'\xa3\xc1Z=Y\xb3\x9dty\x90/\xc7\xa8\x06\xa5\x00J\x01\x00\x01\x00\x8a\t\xa1\xc4\x83\x81\xc8\xc1{\xb7\x00\x8a\t\xc7\x8a5\xf0Qq?\xe6\x00\x8a\x10A$&\x82!\x1cy\x89r\xef\xeb\xa7_\x04q\x1c\x8a\t\x01\xbc\xbb\x8a\x8b=%\x84\x00\x8a\x08;\x94#s\xff\xef\x8f|\x8a\t,\x9c\xe2z\x9a7\x0e\xa6\x00eb."
2071
+
2072
+ print(priv.encoded)
2073
+ # ▶ KLUv_WBwAIELAIAElWUBAAAAAAAAjA90cmFuc2NyeXB0by5yc2GUjA1SU0FQcml2YXRlS2V5lJOUKYGUXZQoikHf1EvsmZedAZve7TrLmobLAwuRIr_77TLG6G_0fsLGThERVJu075be8PLjUQYnLXcacZFQ5Fb1Iy1WtiE985euAEoBAAEAiiFR9ngiXMzkf41o5CRBY3h0D4DJVisDDhLmAWsiaHggzQCKIS_cmQ6MKXCtROtC7c_Mrsi9A-9NM8DksaHaRwvy6uTZAIpB4TVbsLxc41TEc19wIzpxbi9y5dW5gdfTkRQSSiz0ijmb8Xk3pyBfKAv8JbHp8Yv48gNZUfX67qq0J7yhJqeUoACKIbFb2kTNRzSqm3JRtjc2BPS-FnLFdadlFcV4-6IW7eqLAIogFZfzDN39gZLR9uTz4KHSTaqxWrJgP8-YYssjss6FlFKKIIItgCDv7ompNpY8gBs5bibN8XTsr-JOYSntDVT5Fe5vZWIu
2074
+
2075
+ key = aes.AESKey(key256=b'x' * 32)
2076
+ print(key)
2077
+ # ▶ AESKey(key256=86a86df7…)
2078
+
2079
+ encrypted = priv.Blob(key=key)
2080
+ print(priv == rsa.RSAPrivateKey.Load(encrypted, key=key))
2081
+ # ▶ True
2082
+ ```
2083
+ <!-- cspell:enable -->
2084
+
2085
+ #### AES-256 Symmetric Encryption
2086
+
2087
+ Implements AES-256 in **GCM mode** for authenticated encryption and decryption, plus an **ECB mode** helper for fixed-size block encoding.
2088
+ Also includes a high-iteration PBKDF2-based key derivation from static passwords.
2089
+
2090
+ ##### Key creation
2091
+
2092
+ ```py
2093
+ from transcrypto import aes
2094
+
2095
+ # From raw bytes (must be exactly 32 bytes)
2096
+ key = aes.AESKey(key256=b'\x00' * 32)
2097
+
2098
+ # From a static password (slow, high-iteration PBKDF2-SHA256)
2099
+ key = aes.AESKey.FromStaticPassword('correct horse battery staple')
2100
+ print(key.encoded) # URL-safe Base64
2101
+ ```
2102
+
2103
+ - **Length**: `key256` must be exactly 32 bytes
2104
+ - `FromStaticPassword()`:
2105
+ - Uses PBKDF2-HMAC-SHA256 with **fixed** salt and \~2 million iterations
2106
+ - Designed for **interactive** password entry, **not** for password databases
2107
+
2108
+ ##### AES-256 + GCM (default)
2109
+
2110
+ ```py
2111
+ data = b'secret message'
2112
+ aad = b'metadata'
2113
+
2114
+ # Encrypt (returns IV + ciphertext + tag)
2115
+ ct = key.Encrypt(data, associated_data=aad)
2116
+
2117
+ # Decrypt
2118
+ pt = key.Decrypt(ct, associated_data=aad)
2119
+ assert pt == data
2120
+ ```
2121
+
2122
+ - **Security**:
2123
+ - Random 128-bit IV (`iv`) per encryption
2124
+ - Authenticated tag (128-bit) ensures integrity
2125
+ - Optional `associated_data` is authenticated but not encrypted
2126
+ - **Errors**:
2127
+ - Tag mismatch or wrong key → `CryptoError`
2128
+
2129
+ ##### AES-256 + ECB (unsafe, fixed block only)
2130
+
2131
+ ```py
2132
+ # ECB mode is for 16-byte block encoding ONLY
2133
+ ecb = key.ECBEncoder()
2134
+
2135
+ block = b'16-byte string!!'
2136
+ ct_block = ecb.Encrypt(block)
2137
+ pt_block = ecb.Decrypt(ct_block)
2138
+ assert pt_block == block
2139
+
2140
+ # Hex helpers
2141
+ hex_ct = ecb.EncryptHex('00112233445566778899aabbccddeeff')
2142
+ ```
2143
+
2144
+ - **ECB mode**:
2145
+ - 16-byte plaintext ↔ 16-byte ciphertext
2146
+ - No padding, no IV, no integrity — **do not use for general encryption**
2147
+ - `associated_data` not supported
2148
+
2149
+ Key points:
2150
+
2151
+ - **GCM mode** is secure for general use; ECB mode is for special low-level operations
2152
+ - **Static password derivation** is intentionally slow to resist brute force
2153
+ - All sizes and parameters are validated with `InputError` on misuse
2154
+
1879
2155
  #### RSA (Rivest-Shamir-Adleman) Public Cryptography
1880
2156
 
1881
2157
  <https://en.wikipedia.org/wiki/RSA_cryptosystem>
@@ -1888,28 +2164,38 @@ By default and deliberate choice the *encryption exponent* will be either 7 or 6
1888
2164
  from transcrypto import rsa
1889
2165
 
1890
2166
  # Generate a key pair
1891
- priv = rsa.RSAPrivateKey.New(2048) # 2048-bit modulus
1892
- pub = rsa.RSAPublicKey.Copy(priv) # public half
2167
+ priv = rsa.RSAPrivateKey.New(2048) # 2048-bit modulus
2168
+ pub = rsa.RSAPublicKey.Copy(priv) # public half
1893
2169
  print(priv.public_modulus.bit_length()) # 2048
1894
2170
 
1895
- #Encrypt & decrypt
2171
+ # Safe Encrypt & decrypt
2172
+ msg = b'xyz'
2173
+ cipher = pub.Encrypt(msg, associated_data=b'aad')
2174
+ plain = priv.Decrypt(cipher, associated_data=b'aad')
2175
+ assert plain == msg
2176
+
2177
+ # Safe Sign & verify
2178
+ signature = priv.Sign(msg) # can also have associated_data, optionally
2179
+ assert pub.Verify(msg, signature)
2180
+
2181
+ # Raw Encrypt & decrypt
1896
2182
  msg = 123456789 # (Zero is forbidden by design; smallest valid message is 1.)
1897
- cipher = pub.Encrypt(msg)
1898
- plain = priv.Decrypt(cipher)
2183
+ cipher = pub.RawEncrypt(msg)
2184
+ plain = priv.RawDecrypt(cipher)
1899
2185
  assert plain == msg
1900
2186
 
1901
- # Sign & verify
1902
- signature = priv.Sign(msg)
1903
- assert pub.VerifySignature(msg, signature)
2187
+ # Raw Sign & verify
2188
+ signature = priv.RawSign(msg)
2189
+ assert pub.RawVerify(msg, signature)
1904
2190
 
1905
2191
  # Blind signatures (obfuscation pair) - only works on raw RSA
1906
2192
  pair = rsa.RSAObfuscationPair.New(pub)
1907
2193
 
1908
2194
  blind_msg = pair.ObfuscateMessage(msg) # what you send to signer
1909
- blind_sig = priv.Sign(blind_msg) # signer’s output
2195
+ blind_sig = priv.RawSign(blind_msg) # signer’s output
1910
2196
 
1911
2197
  sig = pair.RevealOriginalSignature(msg, blind_sig)
1912
- assert pub.VerifySignature(msg, sig)
2198
+ assert pub.RawVerify(msg, sig)
1913
2199
  ```
1914
2200
 
1915
2201
  #### El-Gamal Public-Key Cryptography
@@ -1919,61 +2205,39 @@ assert pub.VerifySignature(msg, sig)
1919
2205
  This is **raw El-Gamal** over a prime field — no padding, no hashing — and is **not** DSA.
1920
2206
  For real-world deployments, use a high-level library with authenticated encryption and proper encoding.
1921
2207
 
1922
- ##### Shared Public Key
1923
-
1924
2208
  ```py
1925
2209
  from transcrypto import elgamal
1926
2210
 
1927
- # Shared parameters (prime modulus, group base) for a group
2211
+ # Shared parameters (prime modulus, group base) for a group
1928
2212
  shared = elgamal.ElGamalSharedPublicKey.New(256)
1929
2213
  print(shared.prime_modulus)
1930
2214
  print(shared.group_base)
1931
- ```
1932
-
1933
- - `prime_modulus`: large prime `p ≥ 7`
1934
- - `group_base`: integer `3 ≤ g < p`
1935
- - Used to derive individual public/private keys.
1936
2215
 
1937
- ##### Public Key
1938
-
1939
- ```py
1940
- # ➋ Public key from private
2216
+ # Public key from private
1941
2217
  priv = elgamal.ElGamalPrivateKey.New(shared)
1942
2218
  pub = elgamal.ElGamalPublicKey.Copy(priv)
1943
2219
 
1944
- # Encryption
1945
- msg = 42
1946
- cipher = pub.Encrypt(msg)
1947
- plain = priv.Decrypt(cipher)
2220
+ # Safe Encrypt & decrypt
2221
+ msg = b'xyz'
2222
+ cipher = pub.Encrypt(msg, associated_data=b'aad')
2223
+ plain = priv.Decrypt(cipher, associated_data=b'aad')
1948
2224
  assert plain == msg
1949
2225
 
1950
- # Signature verify
1951
- sig = priv.Sign(msg)
1952
- assert pub.VerifySignature(msg, sig)
1953
- ```
2226
+ # Safe Sign & verify
2227
+ signature = priv.Sign(msg) # can also have associated_data, optionally
2228
+ assert pub.Verify(msg, signature)
1954
2229
 
1955
- - `Encrypt(message)` → `(c1, c2)`, both in `[2, p-1]`
1956
- - `VerifySignature(message, signature)` → `True` or `False`
1957
- - `Copy()` extracts public portion from a private key
1958
-
1959
- ##### Private Key
1960
-
1961
- ```py
1962
- # ➌ Private key generation
1963
- priv = elgamal.ElGamalPrivateKey.New(shared)
1964
-
1965
- # Decryption
1966
- plain = priv.Decrypt(cipher)
2230
+ # Raw Encryption
2231
+ msg = 42
2232
+ cipher = pub.RawEncrypt(msg)
2233
+ plain = priv.RawDecrypt(cipher)
2234
+ assert plain == msg
1967
2235
 
1968
- # Signing
1969
- sig = priv.Sign(msg)
1970
- assert pub.VerifySignature(msg, sig)
2236
+ # Raw Signature verify
2237
+ sig = priv.RawSign(msg)
2238
+ assert pub.RawVerify(msg, sig)
1971
2239
  ```
1972
2240
 
1973
- - `decrypt_exp`: secret exponent `3 ≤ e < p`
1974
- - `Decrypt((c1, c2))` recovers `m`
1975
- - `Sign(m)` returns `(s1, s2)`; both satisfy the modulus constraints
1976
-
1977
2241
  Key points:
1978
2242
 
1979
2243
  - **Security parameters**:
@@ -1997,20 +2261,25 @@ This is **raw DSA** over a prime field — **no hashing or padding**. You sign/v
1997
2261
  ```py
1998
2262
  from transcrypto import dsa
1999
2263
 
2000
- # Shared parameters (p, q, g)
2264
+ # Shared parameters (p, q, g)
2001
2265
  shared = dsa.DSASharedPublicKey.New(p_bits=1024, q_bits=160)
2002
2266
  print(shared.prime_modulus) # p
2003
2267
  print(shared.prime_seed) # q (q | p-1)
2004
2268
  print(shared.group_base) # g
2005
2269
 
2006
- # Individual key pair
2270
+ # Individual key pair
2007
2271
  priv = dsa.DSAPrivateKey.New(shared)
2008
2272
  pub = dsa.DSAPublicKey.Copy(priv)
2009
2273
 
2010
- # Sign & verify (message must be 1 ≤ m < q)
2274
+ # Safe Sign & verify
2275
+ msg = b'xyz'
2276
+ signature = priv.Sign(msg) # can also have associated_data, optionally
2277
+ assert pub.Verify(msg, signature)
2278
+
2279
+ # Raw Sign & verify (message must be 1 ≤ m < q)
2011
2280
  msg = 123456789 % shared.prime_seed
2012
- sig = priv.Sign(msg)
2013
- assert pub.VerifySignature(msg, sig)
2281
+ sig = priv.RawSign(msg)
2282
+ assert pub.RawVerify(msg, sig)
2014
2283
  ```
2015
2284
 
2016
2285
  - ranges:
@@ -2044,13 +2313,13 @@ This is a way of bidding on some commitment (the `secret`) that can be cryptogra
2044
2313
  from transcrypto import base
2045
2314
 
2046
2315
  # Generate the private and public bids
2047
- bid_priv = base.PrivateBid.New(secret) # this one you keep private
2048
- bid_pub = base.PublicBid.Copy(bid_priv) # this one you publish
2316
+ bid_priv = base.PrivateBid512.New(secret) # this one you keep private
2317
+ bid_pub = base.PublicBid512.Copy(bid_priv) # this one you publish
2049
2318
 
2050
2319
  # Checking that a bid is genuine requires the public bid and knowing the nonce and the secret:
2051
2320
  print(bid_pub.VerifyBid(private_key, secret_bid)) # these come from a divulged private bid
2052
2321
  # of course, you want to also make sure the provided private data matches your version of it, e.g.:
2053
- bid_pub_expected = base.PublicBid.Copy(bid_priv)
2322
+ bid_pub_expected = base.PublicBid512.Copy(bid_priv)
2054
2323
  print(bid_pub == bid_pub_expected)
2055
2324
  ```
2056
2325
 
@@ -2063,8 +2332,8 @@ This is the information-theoretic SSS but with no authentication or binding betw
2063
2332
  ```py
2064
2333
  from transcrypto import sss
2065
2334
 
2066
- # Generate parameters: at least 3 of 5 shares needed,
2067
- # coefficients & modulus are 128-bit primes
2335
+ # Generate parameters: at least 3 of 5 shares needed,
2336
+ # coefficients & modulus are 128-bit primes
2068
2337
  priv = sss.ShamirSharedSecretPrivate.New(minimum_shares=3, bit_length=128)
2069
2338
  pub = sss.ShamirSharedSecretPublic.Copy(priv) # what you publish
2070
2339
 
@@ -2072,11 +2341,19 @@ print(f'threshold : {pub.minimum}')
2072
2341
  print(f'prime mod : {pub.modulus}')
2073
2342
  print(f'poly coefficients: {priv.polynomial}') # keep these private!
2074
2343
 
2075
- #Issuing shares
2344
+ # Safe Issuing shares
2345
+
2346
+ secret = b'xyz'
2347
+ # Generate 5 shares, each has a copy of the encrypted secret
2348
+ five_shares = priv.MakeDataShares(secret, 5)
2349
+ for sh in five_shares:
2350
+ print(sh)
2351
+
2352
+ # Raw Issuing shares
2076
2353
 
2077
2354
  secret = 0xC0FFEE
2078
2355
  # Generate an unlimited stream; here we take 5
2079
- five_shares = list(priv.Shares(secret, max_shares=5))
2356
+ five_shares = list(priv.RawShares(secret, max_shares=5))
2080
2357
  for sh in five_shares:
2081
2358
  print(f'share {sh.share_key} → {sh.share_value}')
2082
2359
  ```
@@ -2084,10 +2361,18 @@ for sh in five_shares:
2084
2361
  A single share object looks like `sss.ShamirSharePrivate(minimum=3, modulus=..., share_key=42, share_value=123456789)`.
2085
2362
 
2086
2363
  ```py
2087
- #Re-constructing the secret
2364
+ # Safe Re-constructing the secret
2365
+ secret = b'xyz'
2366
+ five_shares = priv.MakeDataShares(secret, 5)
2367
+ subset = five_shares[:3] # any 3 distinct shares
2368
+ recovered = subset[0].RecoverData(subset) # each share has the encrypted data, so you ask it to join with the others
2369
+ assert recovered == secret
2088
2370
 
2371
+ # Raw Re-constructing the secret
2372
+ secret = 0xC0FFEE
2373
+ five_shares = list(priv.RawShares(secret, max_shares=5))
2089
2374
  subset = five_shares[:3] # any 3 distinct shares
2090
- recovered = pub.RecoverSecret(subset)
2375
+ recovered = pub.RawRecoverSecret(subset)
2091
2376
  assert recovered == secret
2092
2377
  ```
2093
2378
 
@@ -2095,23 +2380,23 @@ If you supply fewer than minimum shares you get a `CryptoError`, unless you expl
2095
2380
 
2096
2381
  ```py
2097
2382
  try:
2098
- pub.RecoverSecret(five_shares[:2]) # raises
2383
+ pub.RawRecoverSecret(five_shares[:2]) # raises
2099
2384
  except Exception as e:
2100
2385
  print(e) # "unrecoverable secret …"
2101
2386
 
2102
2387
  # Force the interpolation even with 2 points (gives a wrong secret, of course)
2103
- print(pub.RecoverSecret(five_shares[:2], force_recover=True))
2388
+ print(pub.RawRecoverSecret(five_shares[:2], force_recover=True))
2104
2389
 
2105
2390
  # Checking that a share is genuine
2106
2391
 
2107
2392
  share = five_shares[0]
2108
- ok = priv.VerifyShare(secret, share) # ▶ True
2393
+ ok = priv.RawVerifyShare(secret, share) # ▶ True
2109
2394
  tampered = sss.ShamirSharePrivate(
2110
2395
  minimum=share.minimum,
2111
2396
  modulus=share.modulus,
2112
2397
  share_key=share.share_key,
2113
2398
  share_value=(share.share_value + 1) % share.modulus)
2114
- print(priv.VerifyShare(secret, tampered)) # ▶ False
2399
+ print(priv.RawVerifyShare(secret, tampered)) # ▶ False
2115
2400
  ```
2116
2401
 
2117
2402
  ## Appendix: Development Instructions
@@ -2179,7 +2464,7 @@ To activate like a regular environment do:
2179
2464
  ```sh
2180
2465
  poetry env activate
2181
2466
  # will print activation command which you next execute, or you can do:
2182
- source .env/bin/activate # if .env is local to the project
2467
+ source .venv/bin/activate # if .venv is local to the project
2183
2468
  source "$(poetry env info --path)/bin/activate" # for other paths
2184
2469
 
2185
2470
  pytest # or other commands
@@ -2247,11 +2532,31 @@ poetry run transcrypto doc md > CLI.md
2247
2532
  You can find the 10 top slowest tests by running:
2248
2533
 
2249
2534
  ```sh
2250
- poetry run pytest -vvv -q --durations=10
2535
+ poetry run pytest -vvv -q --durations=30
2536
+
2537
+ poetry run pytest -vvv -q --durations=30 -m "not slow" # find slow > 0.1s
2538
+ poetry run pytest -vvv -q --durations=30 -m "not veryslow" # find veryslow > 1s
2539
+
2540
+ poetry run pytest -vvv -q --durations=30 -m slow # check
2541
+ poetry run pytest -vvv -q --durations=30 -m veryslow # check
2251
2542
  ```
2252
2543
 
2253
- You can search for flaky tests by running all tests 100 times:
2544
+ You can search for flaky tests by running all tests 100 times, or more:
2254
2545
 
2255
2546
  ```sh
2256
2547
  poetry run pytest --flake-finder --flake-runs=100
2548
+ poetry run pytest --flake-finder --flake-runs=500 -m "not veryslow"
2549
+ poetry run pytest --flake-finder --flake-runs=10000 -m "not slow"
2257
2550
  ```
2551
+
2552
+ You can instrument your code to find bottlenecks:
2553
+
2554
+ ```sh
2555
+ $ source .venv/bin/activate
2556
+ $ which transcrypto
2557
+ /path/to/.venv/bin/transcrypto # place this in the command below:
2558
+ $ pyinstrument -r html -o dsa_shared.html -- /path/to/.venv/bin/transcrypto -p rsa-key rsa new
2559
+ $ deactivate
2560
+ ```
2561
+
2562
+ Hint: 85%+ is inside `MillerRabinIsPrime()`/`ModExp()`...