transcrypto 1.2.0__py3-none-any.whl → 1.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2515 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: transcrypto
3
- Version: 1.2.0
4
- Summary: Basic crypto primitives, not intended for actual use, but as a companion to --Criptografia, Métodos e Algoritmos--
5
- Author-email: Daniel Balparda <balparda@github.com>
6
- License-Expression: Apache-2.0
7
- Project-URL: Homepage, https://github.com/balparda/transcrypto
8
- Project-URL: PyPI, https://pypi.org/project/transcrypto/
9
- Classifier: Programming Language :: Python :: 3
10
- Classifier: Programming Language :: Python :: 3.13
11
- Classifier: Operating System :: OS Independent
12
- Classifier: Topic :: Utilities
13
- Classifier: Topic :: Security :: Cryptography
14
- Requires-Python: >=3.13.5
15
- Description-Content-Type: text/markdown
16
- License-File: LICENSE
17
- Dynamic: license-file
18
-
19
- # TransCrypto
20
-
21
- Basic cryptography primitives implementation, a companion to *"Criptografia, Métodos e Algoritmos"*.
22
-
23
- Started in July/2025, by Daniel Balparda. Since version 1.0.2 it is PyPI package:
24
-
25
- <https://pypi.org/project/transcrypto/>
26
-
27
- - [TransCrypto](#transcrypto)
28
- - [License](#license)
29
- - [Design assumptions / Disclaimers](#design-assumptions--disclaimers)
30
- - [Install](#install)
31
- - [Command-Line Interface](#command-line-interface)
32
- - [Global Options](#global-options)
33
- - [Top-Level Commands](#top-level-commands)
34
- - [`random`](#random)
35
- - [`random bits`](#random-bits)
36
- - [`random int`](#random-int)
37
- - [`random bytes`](#random-bytes)
38
- - [`random prime`](#random-prime)
39
- - [`isprime`](#isprime)
40
- - [`primegen`](#primegen)
41
- - [`mersenne`](#mersenne)
42
- - [`gcd`](#gcd)
43
- - [`xgcd`](#xgcd)
44
- - [`mod`](#mod)
45
- - [`mod inv`](#mod-inv)
46
- - [`mod div`](#mod-div)
47
- - [`mod exp`](#mod-exp)
48
- - [`mod poly`](#mod-poly)
49
- - [`mod lagrange`](#mod-lagrange)
50
- - [`mod crt`](#mod-crt)
51
- - [`hash`](#hash)
52
- - [`hash sha256`](#hash-sha256)
53
- - [`hash sha512`](#hash-sha512)
54
- - [`hash file`](#hash-file)
55
- - [`aes`](#aes)
56
- - [`aes key`](#aes-key)
57
- - [`aes encrypt`](#aes-encrypt)
58
- - [`aes decrypt`](#aes-decrypt)
59
- - [`aes ecb`](#aes-ecb)
60
- - [`aes ecb encrypt`](#aes-ecb-encrypt)
61
- - [`aes ecb decrypt`](#aes-ecb-decrypt)
62
- - [`rsa`](#rsa)
63
- - [`rsa new`](#rsa-new)
64
- - [`rsa rawencrypt`](#rsa-rawencrypt)
65
- - [`rsa rawdecrypt`](#rsa-rawdecrypt)
66
- - [`rsa rawsign`](#rsa-rawsign)
67
- - [`rsa rawverify`](#rsa-rawverify)
68
- - [`elgamal`](#elgamal)
69
- - [`elgamal shared`](#elgamal-shared)
70
- - [`elgamal new`](#elgamal-new)
71
- - [`elgamal rawencrypt`](#elgamal-rawencrypt)
72
- - [`elgamal rawdecrypt`](#elgamal-rawdecrypt)
73
- - [`elgamal rawsign`](#elgamal-rawsign)
74
- - [`elgamal rawverify`](#elgamal-rawverify)
75
- - [`dsa`](#dsa)
76
- - [`dsa shared`](#dsa-shared)
77
- - [`dsa new`](#dsa-new)
78
- - [`dsa rawsign`](#dsa-rawsign)
79
- - [`dsa rawverify`](#dsa-rawverify)
80
- - [`bid`](#bid)
81
- - [`bid new`](#bid-new)
82
- - [`bid verify`](#bid-verify)
83
- - [`sss`](#sss)
84
- - [`sss new`](#sss-new)
85
- - [`sss rawshares`](#sss-rawshares)
86
- - [`sss rawrecover`](#sss-rawrecover)
87
- - [`sss rawverify`](#sss-rawverify)
88
- - [`doc`](#doc)
89
- - [`doc md`](#doc-md)
90
- - [Base Library](#base-library)
91
- - [Humanized Sizes (IEC binary)](#humanized-sizes-iec-binary)
92
- - [Humanized Decimal Quantities (SI)](#humanized-decimal-quantities-si)
93
- - [Humanized Durations](#humanized-durations)
94
- - [Execution Timing](#execution-timing)
95
- - [Context manager](#context-manager)
96
- - [Decorator](#decorator)
97
- - [Manual use](#manual-use)
98
- - [Key points](#key-points)
99
- - [Serialization Pipeline](#serialization-pipeline)
100
- - [Serialize](#serialize)
101
- - [DeSerialize](#deserialize)
102
- - [Cryptographically Secure Randomness](#cryptographically-secure-randomness)
103
- - [Fixed-size random integers](#fixed-size-random-integers)
104
- - [Uniform random integers in a range](#uniform-random-integers-in-a-range)
105
- - [In-place secure shuffle](#in-place-secure-shuffle)
106
- - [Random byte strings](#random-byte-strings)
107
- - [Computing the Greatest Common Divisor](#computing-the-greatest-common-divisor)
108
- - [Fast Modular Arithmetic](#fast-modular-arithmetic)
109
- - [Chinese Remainder Theorem (CRT) – Pair](#chinese-remainder-theorem-crt--pair)
110
- - [Modular Polynomials \& Lagrange Interpolation](#modular-polynomials--lagrange-interpolation)
111
- - [Primality testing \& Prime generators, Mersenne primes](#primality-testing--prime-generators-mersenne-primes)
112
- - [Cryptographic Hashing](#cryptographic-hashing)
113
- - [SHA-256 hashing](#sha-256-hashing)
114
- - [SHA-512 hashing](#sha-512-hashing)
115
- - [File hashing](#file-hashing)
116
- - [Symmetric Encryption Interface](#symmetric-encryption-interface)
117
- - [Crypto Objects General Properties (`CryptoKey`)](#crypto-objects-general-properties-cryptokey)
118
- - [AES-256 Symmetric Encryption](#aes-256-symmetric-encryption)
119
- - [Key creation](#key-creation)
120
- - [AES-256 + GCM (default)](#aes-256--gcm-default)
121
- - [AES-256 + ECB (unsafe, fixed block only)](#aes-256--ecb-unsafe-fixed-block-only)
122
- - [RSA (Rivest-Shamir-Adleman) Public Cryptography](#rsa-rivest-shamir-adleman-public-cryptography)
123
- - [El-Gamal Public-Key Cryptography](#el-gamal-public-key-cryptography)
124
- - [DSA (Digital Signature Algorithm)](#dsa-digital-signature-algorithm)
125
- - [Security notes](#security-notes)
126
- - [Advanced: custom primes generator](#advanced-custom-primes-generator)
127
- - [Public Bidding](#public-bidding)
128
- - [SSS (Shamir Shared Secret)](#sss-shamir-shared-secret)
129
- - [Appendix: Development Instructions](#appendix-development-instructions)
130
- - [Setup](#setup)
131
- - [Updating Dependencies](#updating-dependencies)
132
- - [Creating a New Version](#creating-a-new-version)
133
-
134
- ## License
135
-
136
- Copyright 2025 Daniel Balparda <balparda@github.com>
137
-
138
- Licensed under the ***Apache License, Version 2.0*** (the "License"); you may not use this file except in compliance with the License. You may obtain a [copy of the License here](http://www.apache.org/licenses/LICENSE-2.0).
139
-
140
- Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
141
-
142
- ## Design assumptions / Disclaimers
143
-
144
- - 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.
145
- - 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).
146
- - All library methods' `int` are tailored to be efficient with arbitrarily large integers.
147
- - 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.
148
- - *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.
149
-
150
- All that being said, extreme care was taken that this is a good library with a solid safe implementation. *Have fun!*
151
-
152
- ## Install
153
-
154
- To use in your project just do:
155
-
156
- ```sh
157
- pip3 install transcrypto
158
- ```
159
-
160
- and then `from transcrypto import rsa` (or other parts of the library) for using it.
161
-
162
- Known dependencies:
163
-
164
- - [zstandard](https://pypi.org/project/zstandard/) ([docs](https://python-zstandard.readthedocs.org/))
165
- - [cryptography](https://pypi.org/project/cryptography/) ([docs](https://cryptography.io/en/latest/))
166
-
167
- <!-- cspell:disable -->
168
-
169
- <!-- (auto-generated; do not edit between START/END) -->
170
- <!-- INCLUDE:CLI.md START -->
171
-
172
- ## Command-Line Interface
173
-
174
- `transcrypto` is a command-line utility that provides access to all core functionality described in this documentation. It serves as a convenient wrapper over the Python APIs, enabling **cryptographic operations**, **number theory functions**, **secure randomness generation**, **hashing**, **AES**, **RSA**, **El-Gamal**, **DSA**, **bidding**, **SSS**, and other utilities without writing code.
175
-
176
- Invoke with:
177
-
178
- ```bash
179
- poetry run transcrypto <command> [sub-command] [options...]
180
- ```
181
-
182
- ### Global Options
183
-
184
- | Option/Arg | Description |
185
- |---|---|
186
- | `-v, --verbose` | Increase verbosity (use -v/-vv/-vvv/-vvvv for ERROR/WARN/INFO/DEBUG) |
187
- | `--hex` | Treat inputs as hex string (default) |
188
- | `--b64` | Treat inputs as base64url |
189
- | `--bin` | Treat inputs as binary (bytes) |
190
- | `--out-hex` | Outputs as hex (default) |
191
- | `--out-b64` | Outputs as base64url |
192
- | `--out-bin` | Outputs as binary (bytes) |
193
- | `-p, --key-path` | File path to serialized key object, if key is needed for operation [type: str] |
194
- | `--protect` | Password to encrypt/decrypt key file if using the `-p`/`--key-path` option [type: str] |
195
-
196
- ### Top-Level Commands
197
-
198
- - **`random`** — `poetry run transcrypto random [-h] {bits,int,bytes,prime} ...`
199
- - **`isprime`** — `poetry run transcrypto isprime [-h] n`
200
- - **`primegen`** — `poetry run transcrypto primegen [-h] [-c COUNT] start`
201
- - **`mersenne`** — `poetry run transcrypto mersenne [-h] [-k MIN_K] [-C CUTOFF_K]`
202
- - **`gcd`** — `poetry run transcrypto gcd [-h] a b`
203
- - **`xgcd`** — `poetry run transcrypto xgcd [-h] a b`
204
- - **`mod`** — `poetry run transcrypto mod [-h] {inv,div,exp,poly,lagrange,crt} ...`
205
- - **`hash`** — `poetry run transcrypto hash [-h] {sha256,sha512,file} ...`
206
- - **`aes`** — `poetry run transcrypto aes [-h] {key,encrypt,decrypt,ecb} ...`
207
- - **`rsa`** — `poetry run transcrypto rsa [-h] {new,rawencrypt,encrypt,rawdecrypt,decrypt,rawsign,sign,rawverify,verify} ...`
208
- - **`elgamal`** — `poetry run transcrypto elgamal [-h] {shared,new,rawencrypt,encrypt,rawdecrypt,decrypt,rawsign,sign,rawverify,verify} ...`
209
- - **`dsa`** — `poetry run transcrypto dsa [-h] {shared,new,rawsign,sign,rawverify,verify} ...`
210
- - **`bid`** — `poetry run transcrypto bid [-h] {new,verify} ...`
211
- - **`sss`** — `poetry run transcrypto sss [-h] {new,rawshares,shares,rawrecover,recover,rawverify} ...`
212
- - **`doc`** — `poetry run transcrypto doc [-h] {md} ...`
213
-
214
- ```bash
215
- Examples:
216
-
217
- # --- Randomness ---
218
- poetry run transcrypto random bits 16
219
- poetry run transcrypto random int 1000 2000
220
- poetry run transcrypto random bytes 32
221
- poetry run transcrypto random prime 64
222
-
223
- # --- Primes ---
224
- poetry run transcrypto isprime 428568761
225
- poetry run transcrypto primegen 100 -c 3
226
- poetry run transcrypto mersenne -k 2 -C 17
227
-
228
- # --- Integer / Modular Math ---
229
- poetry run transcrypto gcd 462 1071
230
- poetry run transcrypto xgcd 127 13
231
- poetry run transcrypto mod inv 17 97
232
- poetry run transcrypto mod div 6 127 13
233
- poetry run transcrypto mod exp 438 234 127
234
- poetry run transcrypto mod poly 12 17 10 20 30
235
- poetry run transcrypto mod lagrange 5 13 2:4 6:3 7:1
236
- poetry run transcrypto mod crt 6 7 127 13
237
-
238
- # --- Hashing ---
239
- poetry run transcrypto hash sha256 xyz
240
- poetry run transcrypto --b64 hash sha512 eHl6
241
- poetry run transcrypto hash file /etc/passwd --digest sha512
242
-
243
- # --- AES ---
244
- poetry run transcrypto --out-b64 aes key "correct horse battery staple"
245
- poetry run transcrypto --b64 --out-b64 aes encrypt -k "<b64key>" "secret"
246
- poetry run transcrypto --b64 --out-b64 aes decrypt -k "<b64key>" "<ciphertext>"
247
- poetry run transcrypto aes ecb -k "<b64key>" encrypt "<128bithexblock>"
248
- poetry run transcrypto aes ecb -k "<b64key>" decrypt "<128bithexblock>"
249
-
250
- # --- RSA ---
251
- poetry run transcrypto -p rsa-key rsa new --bits 2048
252
- poetry run transcrypto -p rsa-key.pub rsa rawencrypt <plaintext>
253
- poetry run transcrypto -p rsa-key.priv rsa rawdecrypt <ciphertext>
254
- poetry run transcrypto -p rsa-key.priv rsa rawsign <message>
255
- poetry run transcrypto -p rsa-key.pub rsa rawverify <message> <signature>
256
-
257
- # --- ElGamal ---
258
- poetry run transcrypto -p eg-key elgamal shared --bits 2048
259
- poetry run transcrypto -p eg-key elgamal new
260
- poetry run transcrypto -p eg-key.pub elgamal rawencrypt <plaintext>
261
- poetry run transcrypto -p eg-key.priv elgamal rawdecrypt <c1:c2>
262
- poetry run transcrypto -p eg-key.priv elgamal rawsign <message>
263
- poetry run transcrypto-p eg-key.pub elgamal rawverify <message> <s1:s2>
264
-
265
- # --- DSA ---
266
- poetry run transcrypto -p dsa-key dsa shared --p-bits 2048 --q-bits 256
267
- poetry run transcrypto -p dsa-key dsa new
268
- poetry run transcrypto -p dsa-key.priv dsa rawsign <message>
269
- poetry run transcrypto -p dsa-key.pub dsa rawverify <message> <s1:s2>
270
-
271
- # --- Public Bid ---
272
- poetry run transcrypto --bin bid new "tomorrow it will rain"
273
- poetry run transcrypto --out-bin bid verify
274
-
275
- # --- Shamir Secret Sharing (SSS) ---
276
- poetry run transcrypto -p sss-key sss new 3 --bits 1024
277
- poetry run transcrypto -p sss-key sss rawshares <secret> 5
278
- poetry run transcrypto -p sss-key sss rawrecover
279
- poetry run transcrypto -p sss-key sss rawverify <secret>
280
- ```
281
-
282
- ---
283
-
284
- ### `random`
285
-
286
- Cryptographically secure randomness, from the OS CSPRNG.
287
-
288
- ```bash
289
- poetry run transcrypto random [-h] {bits,int,bytes,prime} ...
290
- ```
291
-
292
- #### `random bits`
293
-
294
- Random integer with exact bit length = `bits` (MSB will be 1).
295
-
296
- ```bash
297
- poetry run transcrypto random bits [-h] bits
298
- ```
299
-
300
- | Option/Arg | Description |
301
- |---|---|
302
- | `bits` | Number of bits, ≥ 8 [type: int] |
303
-
304
- **Example:**
305
-
306
- ```bash
307
- $ poetry run transcrypto random bits 16
308
- 36650
309
- ```
310
-
311
- #### `random int`
312
-
313
- Uniform random integer in `[min, max]` range, inclusive.
314
-
315
- ```bash
316
- poetry run transcrypto random int [-h] min max
317
- ```
318
-
319
- | Option/Arg | Description |
320
- |---|---|
321
- | `min` | Minimum, ≥ 0 [type: str] |
322
- | `max` | Maximum, > `min` [type: str] |
323
-
324
- **Example:**
325
-
326
- ```bash
327
- $ poetry run transcrypto random int 1000 2000
328
- 1628
329
- ```
330
-
331
- #### `random bytes`
332
-
333
- Generates `n` cryptographically secure random bytes.
334
-
335
- ```bash
336
- poetry run transcrypto random bytes [-h] n
337
- ```
338
-
339
- | Option/Arg | Description |
340
- |---|---|
341
- | `n` | Number of bytes, ≥ 1 [type: int] |
342
-
343
- **Example:**
344
-
345
- ```bash
346
- $ poetry run transcrypto random bytes 32
347
- 6c6f1f88cb93c4323285a2224373d6e59c72a9c2b82e20d1c376df4ffbe9507f
348
- ```
349
-
350
- #### `random prime`
351
-
352
- Generate a random prime with exact bit length = `bits` (MSB will be 1).
353
-
354
- ```bash
355
- poetry run transcrypto random prime [-h] bits
356
- ```
357
-
358
- | Option/Arg | Description |
359
- |---|---|
360
- | `bits` | Bit length, ≥ 11 [type: int] |
361
-
362
- **Example:**
363
-
364
- ```bash
365
- $ poetry run transcrypto random prime 32
366
- 2365910551
367
- ```
368
-
369
- ---
370
-
371
- ### `isprime`
372
-
373
- Primality test with safe defaults, useful for any integer size.
374
-
375
- ```bash
376
- poetry run transcrypto isprime [-h] n
377
- ```
378
-
379
- | Option/Arg | Description |
380
- |---|---|
381
- | `n` | Integer to test, ≥ 1 [type: str] |
382
-
383
- **Example:**
384
-
385
- ```bash
386
- $ poetry run transcrypto isprime 2305843009213693951
387
- True
388
- $ poetry run transcrypto isprime 2305843009213693953
389
- False
390
- ```
391
-
392
- ---
393
-
394
- ### `primegen`
395
-
396
- Generate (stream) primes ≥ `start` (prints a limited `count` by default).
397
-
398
- ```bash
399
- poetry run transcrypto primegen [-h] [-c COUNT] start
400
- ```
401
-
402
- | Option/Arg | Description |
403
- |---|---|
404
- | `start` | Starting integer (inclusive) [type: str] |
405
- | `-c, --count` | How many to print (0 = unlimited) [type: int (default: 10)] |
406
-
407
- **Example:**
408
-
409
- ```bash
410
- $ poetry run transcrypto primegen 100 -c 3
411
- 101
412
- 103
413
- 107
414
- ```
415
-
416
- ---
417
-
418
- ### `mersenne`
419
-
420
- Generate (stream) Mersenne prime exponents `k`, also outputting `2^k-1` (the Mersenne prime, `M`) and `M×2^(k-1)` (the associated perfect number), starting at `min-k` and stopping once `k` > `cutoff-k`.
421
-
422
- ```bash
423
- poetry run transcrypto mersenne [-h] [-k MIN_K] [-C CUTOFF_K]
424
- ```
425
-
426
- | Option/Arg | Description |
427
- |---|---|
428
- | `-k, --min-k` | Starting exponent `k`, ≥ 1 [type: int (default: 1)] |
429
- | `-C, --cutoff-k` | Stop once `k` > `cutoff-k` [type: int (default: 10000)] |
430
-
431
- **Example:**
432
-
433
- ```bash
434
- $ poetry run transcrypto mersenne -k 0 -C 15
435
- k=2 M=3 perfect=6
436
- k=3 M=7 perfect=28
437
- k=5 M=31 perfect=496
438
- k=7 M=127 perfect=8128
439
- k=13 M=8191 perfect=33550336
440
- k=17 M=131071 perfect=8589869056
441
- ```
442
-
443
- ---
444
-
445
- ### `gcd`
446
-
447
- Greatest Common Divisor (GCD) of integers `a` and `b`.
448
-
449
- ```bash
450
- poetry run transcrypto gcd [-h] a b
451
- ```
452
-
453
- | Option/Arg | Description |
454
- |---|---|
455
- | `a` | Integer, ≥ 0 [type: str] |
456
- | `b` | Integer, ≥ 0 (can't be both zero) [type: str] |
457
-
458
- **Example:**
459
-
460
- ```bash
461
- $ poetry run transcrypto gcd 462 1071
462
- 21
463
- $ poetry run transcrypto gcd 0 5
464
- 5
465
- $ poetry run transcrypto gcd 127 13
466
- 1
467
- ```
468
-
469
- ---
470
-
471
- ### `xgcd`
472
-
473
- Extended Greatest Common Divisor (x-GCD) of integers `a` and `b`, will return `(g, x, y)` where `a×x+b×y==g`.
474
-
475
- ```bash
476
- poetry run transcrypto xgcd [-h] a b
477
- ```
478
-
479
- | Option/Arg | Description |
480
- |---|---|
481
- | `a` | Integer, ≥ 0 [type: str] |
482
- | `b` | Integer, ≥ 0 (can't be both zero) [type: str] |
483
-
484
- **Example:**
485
-
486
- ```bash
487
- $ poetry run transcrypto xgcd 462 1071
488
- (21, 7, -3)
489
- $ poetry run transcrypto xgcd 0 5
490
- (5, 0, 1)
491
- $ poetry run transcrypto xgcd 127 13
492
- (1, 4, -39)
493
- ```
494
-
495
- ---
496
-
497
- ### `mod`
498
-
499
- Modular arithmetic helpers.
500
-
501
- ```bash
502
- poetry run transcrypto mod [-h] {inv,div,exp,poly,lagrange,crt} ...
503
- ```
504
-
505
- #### `mod inv`
506
-
507
- Modular inverse: find integer 0≤`i`<`m` such that `a×i ≡ 1 (mod m)`. Will only work if `gcd(a,m)==1`, else will fail with a message.
508
-
509
- ```bash
510
- poetry run transcrypto mod inv [-h] a m
511
- ```
512
-
513
- | Option/Arg | Description |
514
- |---|---|
515
- | `a` | Integer to invert [type: str] |
516
- | `m` | Modulus `m`, ≥ 2 [type: str] |
517
-
518
- **Example:**
519
-
520
- ```bash
521
- $ poetry run transcrypto mod inv 127 13
522
- 4
523
- $ poetry run transcrypto mod inv 17 3120
524
- 2753
525
- $ poetry run transcrypto mod inv 462 1071
526
- <<INVALID>> no modular inverse exists (ModularDivideError)
527
- ```
528
-
529
- #### `mod div`
530
-
531
- Modular division: find integer 0≤`z`<`m` such that `z×y ≡ x (mod m)`. Will only work if `gcd(y,m)==1` and `y!=0`, else will fail with a message.
532
-
533
- ```bash
534
- poetry run transcrypto mod div [-h] x y m
535
- ```
536
-
537
- | Option/Arg | Description |
538
- |---|---|
539
- | `x` | Integer [type: str] |
540
- | `y` | Integer, cannot be zero [type: str] |
541
- | `m` | Modulus `m`, ≥ 2 [type: str] |
542
-
543
- **Example:**
544
-
545
- ```bash
546
- $ poetry run transcrypto mod div 6 127 13
547
- 11
548
- $ poetry run transcrypto mod div 6 0 13
549
- <<INVALID>> no modular inverse exists (ModularDivideError)
550
- ```
551
-
552
- #### `mod exp`
553
-
554
- Modular exponentiation: `a^e mod m`. Efficient, can handle huge values.
555
-
556
- ```bash
557
- poetry run transcrypto mod exp [-h] a e m
558
- ```
559
-
560
- | Option/Arg | Description |
561
- |---|---|
562
- | `a` | Integer [type: str] |
563
- | `e` | Integer, ≥ 0 [type: str] |
564
- | `m` | Modulus `m`, ≥ 2 [type: str] |
565
-
566
- **Example:**
567
-
568
- ```bash
569
- $ poetry run transcrypto mod exp 438 234 127
570
- 32
571
- $ poetry run transcrypto mod exp 438 234 89854
572
- 60622
573
- ```
574
-
575
- #### `mod poly`
576
-
577
- Efficiently evaluate polynomial with `coeff` coefficients at point `x` modulo `m` (`c₀+c₁×x+c₂×x²+…+cₙ×xⁿ mod m`).
578
-
579
- ```bash
580
- poetry run transcrypto mod poly [-h] x m coeff [coeff ...]
581
- ```
582
-
583
- | Option/Arg | Description |
584
- |---|---|
585
- | `x` | Evaluation point `x` [type: str] |
586
- | `m` | Modulus `m`, ≥ 2 [type: str] |
587
- | `coeff` | Coefficients (constant-term first: `c₀+c₁×x+c₂×x²+…+cₙ×xⁿ`) [nargs: +] |
588
-
589
- **Example:**
590
-
591
- ```bash
592
- $ poetry run transcrypto mod poly 12 17 10 20 30
593
- 14 # (10+20×12+30×12² ≡ 14 (mod 17))
594
- $ poetry run transcrypto mod poly 10 97 3 0 0 1 1
595
- 42 # (3+1×10³+1×10⁴ ≡ 42 (mod 97))
596
- ```
597
-
598
- #### `mod lagrange`
599
-
600
- Lagrange interpolation over modulus `m`: find the `f(x)` solution for the given `x` and `zₙ:f(zₙ)` points `pt`. The modulus `m` must be a prime.
601
-
602
- ```bash
603
- poetry run transcrypto mod lagrange [-h] x m pt [pt ...]
604
- ```
605
-
606
- | Option/Arg | Description |
607
- |---|---|
608
- | `x` | Evaluation point `x` [type: str] |
609
- | `m` | Modulus `m`, ≥ 2 [type: str] |
610
- | `pt` | Points `zₙ:f(zₙ)` as `key:value` pairs (e.g., `2:4 5:3 7:1`) [nargs: +] |
611
-
612
- **Example:**
613
-
614
- ```bash
615
- $ poetry run transcrypto mod lagrange 5 13 2:4 6:3 7:1
616
- 3 # passes through (2,4), (6,3), (7,1)
617
- $ poetry run transcrypto mod lagrange 11 97 1:1 2:4 3:9 4:16 5:25
618
- 24 # passes through (1,1), (2,4), (3,9), (4,16), (5,25)
619
- ```
620
-
621
- #### `mod crt`
622
-
623
- Solves Chinese Remainder Theorem (CRT) Pair: finds the unique integer 0≤`x`<`(m1×m2)` satisfying both `x ≡ a1 (mod m1)` and `x ≡ a2 (mod m2)`, if `gcd(m1,m2)==1`.
624
-
625
- ```bash
626
- poetry run transcrypto mod crt [-h] a1 m1 a2 m2
627
- ```
628
-
629
- | Option/Arg | Description |
630
- |---|---|
631
- | `a1` | Integer residue for first congruence [type: str] |
632
- | `m1` | Modulus `m1`, ≥ 2 and `gcd(m1,m2)==1` [type: str] |
633
- | `a2` | Integer residue for second congruence [type: str] |
634
- | `m2` | Modulus `m2`, ≥ 2 and `gcd(m1,m2)==1` [type: str] |
635
-
636
- **Example:**
637
-
638
- ```bash
639
- $ poetry run transcrypto mod crt 6 7 127 13
640
- 62
641
- $ poetry run transcrypto mod crt 12 56 17 19
642
- 796
643
- $ poetry run transcrypto mod crt 6 7 462 1071
644
- <<INVALID>> moduli m1/m2 not co-prime (ModularDivideError)
645
- ```
646
-
647
- ---
648
-
649
- ### `hash`
650
-
651
- Cryptographic Hashing (SHA-256 / SHA-512 / file).
652
-
653
- ```bash
654
- poetry run transcrypto hash [-h] {sha256,sha512,file} ...
655
- ```
656
-
657
- #### `hash sha256`
658
-
659
- SHA-256 of input `data`.
660
-
661
- ```bash
662
- poetry run transcrypto hash sha256 [-h] data
663
- ```
664
-
665
- | Option/Arg | Description |
666
- |---|---|
667
- | `data` | Input data (raw text; or use --hex/--b64/--bin) [type: str] |
668
-
669
- **Example:**
670
-
671
- ```bash
672
- $ poetry run transcrypto --bin hash sha256 xyz
673
- 3608bca1e44ea6c4d268eb6db02260269892c0b42b86bbf1e77a6fa16c3c9282
674
- $ poetry run transcrypto --b64 hash sha256 eHl6 # "xyz" in base-64
675
- 3608bca1e44ea6c4d268eb6db02260269892c0b42b86bbf1e77a6fa16c3c9282
676
- ```
677
-
678
- #### `hash sha512`
679
-
680
- SHA-512 of input `data`.
681
-
682
- ```bash
683
- poetry run transcrypto hash sha512 [-h] data
684
- ```
685
-
686
- | Option/Arg | Description |
687
- |---|---|
688
- | `data` | Input data (raw text; or use --hex/--b64/--bin) [type: str] |
689
-
690
- **Example:**
691
-
692
- ```bash
693
- $ poetry run transcrypto --bin hash sha512 xyz
694
- 4a3ed8147e37876adc8f76328e5abcc1b470e6acfc18efea0135f983604953a58e183c1a6086e91ba3e821d926f5fdeb37761c7ca0328a963f5e92870675b728
695
- $ poetry run transcrypto --b64 hash sha512 eHl6 # "xyz" in base-64
696
- 4a3ed8147e37876adc8f76328e5abcc1b470e6acfc18efea0135f983604953a58e183c1a6086e91ba3e821d926f5fdeb37761c7ca0328a963f5e92870675b728
697
- ```
698
-
699
- #### `hash file`
700
-
701
- SHA-256/512 hash of file contents, defaulting to SHA-256.
702
-
703
- ```bash
704
- poetry run transcrypto hash file [-h] [--digest {sha256,sha512}] path
705
- ```
706
-
707
- | Option/Arg | Description |
708
- |---|---|
709
- | `path` | Path to existing file [type: str] |
710
- | `--digest` | Digest type, SHA-256 ("sha256") or SHA-512 ("sha512") [choices: ['sha256', 'sha512'] (default: sha256)] |
711
-
712
- **Example:**
713
-
714
- ```bash
715
- $ poetry run transcrypto hash file /etc/passwd --digest sha512
716
- 8966f5953e79f55dfe34d3dc5b160ac4a4a3f9cbd1c36695a54e28d77c7874dff8595502f8a420608911b87d336d9e83c890f0e7ec11a76cb10b03e757f78aea
717
- ```
718
-
719
- ---
720
-
721
- ### `aes`
722
-
723
- AES-256 operations (GCM/ECB) and key derivation. No measures are taken here to prevent timing attacks.
724
-
725
- ```bash
726
- poetry run transcrypto aes [-h] {key,encrypt,decrypt,ecb} ...
727
- ```
728
-
729
- #### `aes key`
730
-
731
- Derive key from a password (PBKDF2-HMAC-SHA256) with custom expensive salt and iterations. Very good/safe for simple password-to-key but not for passwords databases (because of constant salt).
732
-
733
- ```bash
734
- poetry run transcrypto aes key [-h] password
735
- ```
736
-
737
- | Option/Arg | Description |
738
- |---|---|
739
- | `password` | Password (leading/trailing spaces ignored) [type: str] |
740
-
741
- **Example:**
742
-
743
- ```bash
744
- $ poetry run transcrypto --out-b64 aes key "correct horse battery staple"
745
- DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es=
746
- $ poetry run transcrypto -p keyfile.out --protect hunter aes key "correct horse battery staple"
747
- AES key saved to 'keyfile.out'
748
- ```
749
-
750
- #### `aes encrypt`
751
-
752
- AES-256-GCM: safely encrypt `plaintext` with `-k`/`--key` or with `-p`/`--key-path` keyfile. All inputs are raw, or you can use `--bin`/`--hex`/`--b64` flags. Attention: if you provide `-a`/`--aad` (associated data, AAD), you will need to provide the same AAD when decrypting and it is NOT included in the `ciphertext`/CT returned by this method!
753
-
754
- ```bash
755
- poetry run transcrypto aes encrypt [-h] [-k KEY] [-a AAD] plaintext
756
- ```
757
-
758
- | Option/Arg | Description |
759
- |---|---|
760
- | `plaintext` | Input data to encrypt (PT) [type: str] |
761
- | `-k, --key` | Key if `-p`/`--key-path` wasn't used (32 bytes) [type: str] |
762
- | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
763
-
764
- **Example:**
765
-
766
- ```bash
767
- $ poetry run transcrypto --b64 --out-b64 aes encrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= AAAAAAB4eXo=
768
- F2_ZLrUw5Y8oDnbTP5t5xCUWX8WtVILLD0teyUi_37_4KHeV-YowVA==
769
- $ poetry run transcrypto --b64 --out-b64 aes encrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -a eHl6 AAAAAAB4eXo=
770
- xOlAHPUPpeyZHId-f3VQ_QKKMxjIW0_FBo9WOfIBrzjn0VkVV6xTRA==
771
- ```
772
-
773
- #### `aes decrypt`
774
-
775
- AES-256-GCM: safely decrypt `ciphertext` with `-k`/`--key` or with `-p`/`--key-path` keyfile. All inputs are raw, or you can use `--bin`/`--hex`/`--b64` flags. Attention: if you provided `-a`/`--aad` (associated data, AAD) during encryption, you will need to provide the same AAD now!
776
-
777
- ```bash
778
- poetry run transcrypto aes decrypt [-h] [-k KEY] [-a AAD] ciphertext
779
- ```
780
-
781
- | Option/Arg | Description |
782
- |---|---|
783
- | `ciphertext` | Input data to decrypt (CT) [type: str] |
784
- | `-k, --key` | Key if `-p`/`--key-path` wasn't used (32 bytes) [type: str] |
785
- | `-a, --aad` | Associated data (optional; has to be exactly the same as used during encryption) [type: str] |
786
-
787
- **Example:**
788
-
789
- ```bash
790
- $ poetry run transcrypto --b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= F2_ZLrUw5Y8oDnbTP5t5xCUWX8WtVILLD0teyUi_37_4KHeV-YowVA==
791
- AAAAAAB4eXo=
792
- $ poetry run transcrypto --b64 --out-b64 aes decrypt -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= -a eHl6 xOlAHPUPpeyZHId-f3VQ_QKKMxjIW0_FBo9WOfIBrzjn0VkVV6xTRA==
793
- AAAAAAB4eXo=
794
- ```
795
-
796
- #### `aes ecb`
797
-
798
- AES-256-ECB: encrypt/decrypt 128 bit (16 bytes) hexadecimal blocks. UNSAFE, except for specifically encrypting hash blocks which are very much expected to look random. ECB mode will have the same output for the same input (no IV/nonce is used).
799
-
800
- ```bash
801
- poetry run transcrypto aes ecb [-h] [-k KEY] {encrypt,decrypt} ...
802
- ```
803
-
804
- | Option/Arg | Description |
805
- |---|---|
806
- | `-k, --key` | Key if `-p`/`--key-path` wasn't used (32 bytes; raw, or you can use `--bin`/`--hex`/`--b64` flags) [type: str] |
807
-
808
- #### `aes ecb encrypt`
809
-
810
- AES-256-ECB: encrypt 16-bytes hex `plaintext` with `-k`/`--key` or with `-p`/`--key-path` keyfile. UNSAFE, except for specifically encrypting hash blocks.
811
-
812
- ```bash
813
- poetry run transcrypto aes ecb encrypt [-h] plaintext
814
- ```
815
-
816
- | Option/Arg | Description |
817
- |---|---|
818
- | `plaintext` | Plaintext block as 32 hex chars (16-bytes) [type: str] |
819
-
820
- **Example:**
821
-
822
- ```bash
823
- $ poetry run transcrypto --b64 aes ecb -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= encrypt 00112233445566778899aabbccddeeff
824
- 54ec742ca3da7b752e527b74e3a798d7
825
- ```
826
-
827
- #### `aes ecb decrypt`
828
-
829
- AES-256-ECB: decrypt 16-bytes hex `ciphertext` with `-k`/`--key` or with `-p`/`--key-path` keyfile. UNSAFE, except for specifically encrypting hash blocks.
830
-
831
- ```bash
832
- poetry run transcrypto aes ecb decrypt [-h] ciphertext
833
- ```
834
-
835
- | Option/Arg | Description |
836
- |---|---|
837
- | `ciphertext` | Ciphertext block as 32 hex chars (16-bytes) [type: str] |
838
-
839
- **Example:**
840
-
841
- ```bash
842
- $ poetry run transcrypto --b64 aes ecb -k DbWJ_ZrknLEEIoq_NpoCQwHYfjskGokpueN2O_eY0es= decrypt 54ec742ca3da7b752e527b74e3a798d7
843
- 00112233445566778899aabbccddeeff
844
- ```
845
-
846
- ---
847
-
848
- ### `rsa`
849
-
850
- 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).
851
-
852
- ```bash
853
- poetry run transcrypto rsa [-h]
854
- {new,rawencrypt,encrypt,rawdecrypt,decrypt,rawsign,sign,rawverify,verify} ...
855
- ```
856
-
857
- #### `rsa new`
858
-
859
- Generate RSA private/public key pair with `bits` modulus size (prime sizes will be `bits`/2). Requires `-p`/`--key-path` to set the basename for output files.
860
-
861
- ```bash
862
- poetry run transcrypto rsa new [-h] [--bits BITS]
863
- ```
864
-
865
- | Option/Arg | Description |
866
- |---|---|
867
- | `--bits` | Modulus size in bits; the default is a safe size [type: int (default: 3332)] |
868
-
869
- **Example:**
870
-
871
- ```bash
872
- $ poetry run transcrypto -p rsa-key rsa new --bits 64 # NEVER use such a small key: example only!
873
- RSA private/public keys saved to 'rsa-key.priv/.pub'
874
- ```
875
-
876
- #### `rsa rawencrypt`
877
-
878
- Raw encrypt *integer* `message` with public key (BEWARE: no OAEP/PSS padding or validation).
879
-
880
- ```bash
881
- poetry run transcrypto rsa rawencrypt [-h] message
882
- ```
883
-
884
- | Option/Arg | Description |
885
- |---|---|
886
- | `message` | Integer message to encrypt, 1≤`message`<*modulus* [type: str] |
887
-
888
- **Example:**
889
-
890
- ```bash
891
- $ poetry run transcrypto -p rsa-key.pub rsa rawencrypt 999
892
- 6354905961171348600
893
- ```
894
-
895
- #### `rsa encrypt`
896
-
897
- Encrypt `message` with public key.
898
-
899
- ```bash
900
- poetry run transcrypto rsa encrypt [-h] [-a AAD] plaintext
901
- ```
902
-
903
- | Option/Arg | Description |
904
- |---|---|
905
- | `plaintext` | Message to encrypt [type: str] |
906
- | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
907
-
908
- **Example:**
909
-
910
- ```bash
911
- $ poetry run transcrypto --bin --out-b64 -p rsa-key.pub rsa encrypt "abcde" -a "xyz"
912
- AO6knI6xwq6TGR…Qy22jiFhXi1eQ==
913
- ```
914
-
915
- #### `rsa rawdecrypt`
916
-
917
- Raw decrypt *integer* `ciphertext` with private key (BEWARE: no OAEP/PSS padding or validation).
918
-
919
- ```bash
920
- poetry run transcrypto rsa rawdecrypt [-h] ciphertext
921
- ```
922
-
923
- | Option/Arg | Description |
924
- |---|---|
925
- | `ciphertext` | Integer ciphertext to decrypt, 1≤`ciphertext`<*modulus* [type: str] |
926
-
927
- **Example:**
928
-
929
- ```bash
930
- $ poetry run transcrypto -p rsa-key.priv rsa rawdecrypt 6354905961171348600
931
- 999
932
- ```
933
-
934
- #### `rsa decrypt`
935
-
936
- Decrypt `ciphertext` with private key.
937
-
938
- ```bash
939
- poetry run transcrypto rsa decrypt [-h] [-a AAD] ciphertext
940
- ```
941
-
942
- | Option/Arg | Description |
943
- |---|---|
944
- | `ciphertext` | Ciphertext to decrypt [type: str] |
945
- | `-a, --aad` | Associated data (optional; has to be exactly the same as used during encryption) [type: str] |
946
-
947
- **Example:**
948
-
949
- ```bash
950
- $ poetry run transcrypto --b64 --out-bin -p rsa-key.priv rsa decrypt "AO6knI6xwq6TGR…Qy22jiFhXi1eQ==" -a "eHl6"
951
- abcde
952
- ```
953
-
954
- #### `rsa rawsign`
955
-
956
- Raw sign *integer* `message` with private key (BEWARE: no OAEP/PSS padding or validation).
957
-
958
- ```bash
959
- poetry run transcrypto rsa rawsign [-h] message
960
- ```
961
-
962
- | Option/Arg | Description |
963
- |---|---|
964
- | `message` | Integer message to sign, 1≤`message`<*modulus* [type: str] |
965
-
966
- **Example:**
967
-
968
- ```bash
969
- $ poetry run transcrypto -p rsa-key.priv rsa rawsign 999
970
- 7632909108672871784
971
- ```
972
-
973
- #### `rsa sign`
974
-
975
- Sign `message` with private key.
976
-
977
- ```bash
978
- poetry run transcrypto rsa sign [-h] [-a AAD] message
979
- ```
980
-
981
- | Option/Arg | Description |
982
- |---|---|
983
- | `message` | Message to sign [type: str] |
984
- | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
985
-
986
- **Example:**
987
-
988
- ```bash
989
- $ poetry run transcrypto --bin --out-b64 -p rsa-key.priv rsa sign "xyz"
990
- 91TS7gC6LORiL…6RD23Aejsfxlw==
991
- ```
992
-
993
- #### `rsa rawverify`
994
-
995
- Raw verify *integer* `signature` for *integer* `message` with public key (BEWARE: no OAEP/PSS padding or validation).
996
-
997
- ```bash
998
- poetry run transcrypto rsa rawverify [-h] message signature
999
- ```
1000
-
1001
- | Option/Arg | Description |
1002
- |---|---|
1003
- | `message` | Integer message that was signed earlier, 1≤`message`<*modulus* [type: str] |
1004
- | `signature` | Integer putative signature for `message`, 1≤`signature`<*modulus* [type: str] |
1005
-
1006
- **Example:**
1007
-
1008
- ```bash
1009
- $ poetry run transcrypto -p rsa-key.pub rsa rawverify 999 7632909108672871784
1010
- RSA signature: OK
1011
- $ poetry run transcrypto -p rsa-key.pub rsa rawverify 999 7632909108672871785
1012
- RSA signature: INVALID
1013
- ```
1014
-
1015
- #### `rsa verify`
1016
-
1017
- Verify `signature` for `message` with public key.
1018
-
1019
- ```bash
1020
- poetry run transcrypto rsa verify [-h] [-a AAD] message signature
1021
- ```
1022
-
1023
- | Option/Arg | Description |
1024
- |---|---|
1025
- | `message` | Message that was signed earlier [type: str] |
1026
- | `signature` | Putative signature for `message` [type: str] |
1027
- | `-a, --aad` | Associated data (optional; has to be exactly the same as used during signing) [type: str] |
1028
-
1029
- **Example:**
1030
-
1031
- ```bash
1032
- $ poetry run transcrypto --b64 -p rsa-key.pub rsa verify "eHl6" "91TS7gC6LORiL…6RD23Aejsfxlw=="
1033
- RSA signature: OK
1034
- $ poetry run transcrypto --b64 -p rsa-key.pub rsa verify "eLl6" "91TS7gC6LORiL…6RD23Aejsfxlw=="
1035
- RSA signature: INVALID
1036
- ```
1037
-
1038
- ---
1039
-
1040
- ### `elgamal`
1041
-
1042
- 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).
1043
-
1044
- ```bash
1045
- poetry run transcrypto elgamal [-h]
1046
- {shared,new,rawencrypt,encrypt,rawdecrypt,decrypt,rawsign,sign,rawverify,verify} ...
1047
- ```
1048
-
1049
- #### `elgamal shared`
1050
-
1051
- Generate a shared El-Gamal key with `bits` prime modulus size, which is the first step in key generation. 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.
1052
-
1053
- ```bash
1054
- poetry run transcrypto elgamal shared [-h] [--bits BITS]
1055
- ```
1056
-
1057
- | Option/Arg | Description |
1058
- |---|---|
1059
- | `--bits` | Prime modulus (`p`) size in bits; the default is a safe size [type: int (default: 3332)] |
1060
-
1061
- **Example:**
1062
-
1063
- ```bash
1064
- $ poetry run transcrypto -p eg-key elgamal shared --bits 64 # NEVER use such a small key: example only!
1065
- El-Gamal shared key saved to 'eg-key.shared'
1066
- ```
1067
-
1068
- #### `elgamal new`
1069
-
1070
- Generate an individual El-Gamal private/public key pair from a shared key.
1071
-
1072
- ```bash
1073
- poetry run transcrypto elgamal new [-h]
1074
- ```
1075
-
1076
- **Example:**
1077
-
1078
- ```bash
1079
- $ poetry run transcrypto -p eg-key elgamal new
1080
- El-Gamal private/public keys saved to 'eg-key.priv/.pub'
1081
- ```
1082
-
1083
- #### `elgamal rawencrypt`
1084
-
1085
- Raw encrypt *integer* `message` with public key (BEWARE: no ECIES-style KEM/DEM padding or validation).
1086
-
1087
- ```bash
1088
- poetry run transcrypto elgamal rawencrypt [-h] message
1089
- ```
1090
-
1091
- | Option/Arg | Description |
1092
- |---|---|
1093
- | `message` | Integer message to encrypt, 1≤`message`<*modulus* [type: str] |
1094
-
1095
- **Example:**
1096
-
1097
- ```bash
1098
- $ poetry run transcrypto -p eg-key.pub elgamal rawencrypt 999
1099
- 2948854810728206041:15945988196340032688
1100
- ```
1101
-
1102
- #### `elgamal encrypt`
1103
-
1104
- Encrypt `message` with public key.
1105
-
1106
- ```bash
1107
- poetry run transcrypto elgamal encrypt [-h] [-a AAD] plaintext
1108
- ```
1109
-
1110
- | Option/Arg | Description |
1111
- |---|---|
1112
- | `plaintext` | Message to encrypt [type: str] |
1113
- | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
1114
-
1115
- **Example:**
1116
-
1117
- ```bash
1118
- $ poetry run transcrypto --bin --out-b64 -p eg-key.pub elgamal encrypt "abcde" -a "xyz"
1119
- CdFvoQ_IIPFPZLua…kqjhcUTspISxURg==
1120
- ```
1121
-
1122
- #### `elgamal rawdecrypt`
1123
-
1124
- Raw decrypt *integer* `ciphertext` with private key (BEWARE: no ECIES-style KEM/DEM padding or validation).
1125
-
1126
- ```bash
1127
- poetry run transcrypto elgamal rawdecrypt [-h] ciphertext
1128
- ```
1129
-
1130
- | Option/Arg | Description |
1131
- |---|---|
1132
- | `ciphertext` | Integer ciphertext to decrypt; expects `c1:c2` format with 2 integers, 2≤`c1`,`c2`<*modulus* [type: str] |
1133
-
1134
- **Example:**
1135
-
1136
- ```bash
1137
- $ poetry run transcrypto -p eg-key.priv elgamal rawdecrypt 2948854810728206041:15945988196340032688
1138
- 999
1139
- ```
1140
-
1141
- #### `elgamal decrypt`
1142
-
1143
- Decrypt `ciphertext` with private key.
1144
-
1145
- ```bash
1146
- poetry run transcrypto elgamal decrypt [-h] [-a AAD] ciphertext
1147
- ```
1148
-
1149
- | Option/Arg | Description |
1150
- |---|---|
1151
- | `ciphertext` | Ciphertext to decrypt [type: str] |
1152
- | `-a, --aad` | Associated data (optional; has to be exactly the same as used during encryption) [type: str] |
1153
-
1154
- **Example:**
1155
-
1156
- ```bash
1157
- $ poetry run transcrypto --b64 --out-bin -p eg-key.priv elgamal decrypt "CdFvoQ_IIPFPZLua…kqjhcUTspISxURg==" -a "eHl6"
1158
- abcde
1159
- ```
1160
-
1161
- #### `elgamal rawsign`
1162
-
1163
- 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.
1164
-
1165
- ```bash
1166
- poetry run transcrypto elgamal rawsign [-h] message
1167
- ```
1168
-
1169
- | Option/Arg | Description |
1170
- |---|---|
1171
- | `message` | Integer message to sign, 1≤`message`<*modulus* [type: str] |
1172
-
1173
- **Example:**
1174
-
1175
- ```bash
1176
- $ poetry run transcrypto -p eg-key.priv elgamal rawsign 999
1177
- 4674885853217269088:14532144906178302633
1178
- ```
1179
-
1180
- #### `elgamal sign`
1181
-
1182
- Sign message with private key.
1183
-
1184
- ```bash
1185
- poetry run transcrypto elgamal sign [-h] [-a AAD] message
1186
- ```
1187
-
1188
- | Option/Arg | Description |
1189
- |---|---|
1190
- | `message` | Message to sign [type: str] |
1191
- | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
1192
-
1193
- **Example:**
1194
-
1195
- ```bash
1196
- $ poetry run transcrypto --bin --out-b64 -p eg-key.priv elgamal sign "xyz"
1197
- Xl4hlYK8SHVGw…0fCKJE1XVzA==
1198
- ```
1199
-
1200
- #### `elgamal rawverify`
1201
-
1202
- Raw verify *integer* `signature` for *integer* `message` with public key (BEWARE: no ECIES-style KEM/DEM padding or validation).
1203
-
1204
- ```bash
1205
- poetry run transcrypto elgamal rawverify [-h] message signature
1206
- ```
1207
-
1208
- | Option/Arg | Description |
1209
- |---|---|
1210
- | `message` | Integer message that was signed earlier, 1≤`message`<*modulus* [type: str] |
1211
- | `signature` | Integer putative signature for `message`; expects `s1:s2` format with 2 integers, 2≤`s1`,`s2`<*modulus* [type: str] |
1212
-
1213
- **Example:**
1214
-
1215
- ```bash
1216
- $ poetry run transcrypto -p eg-key.pub elgamal rawverify 999 4674885853217269088:14532144906178302633
1217
- El-Gamal signature: OK
1218
- $ poetry run transcrypto -p eg-key.pub elgamal rawverify 999 4674885853217269088:14532144906178302632
1219
- El-Gamal signature: INVALID
1220
- ```
1221
-
1222
- #### `elgamal verify`
1223
-
1224
- Verify `signature` for `message` with public key.
1225
-
1226
- ```bash
1227
- poetry run transcrypto elgamal verify [-h] [-a AAD] message signature
1228
- ```
1229
-
1230
- | Option/Arg | Description |
1231
- |---|---|
1232
- | `message` | Message that was signed earlier [type: str] |
1233
- | `signature` | Putative signature for `message` [type: str] |
1234
- | `-a, --aad` | Associated data (optional; has to be exactly the same as used during signing) [type: str] |
1235
-
1236
- **Example:**
1237
-
1238
- ```bash
1239
- $ poetry run transcrypto --b64 -p eg-key.pub elgamal verify "eHl6" "Xl4hlYK8SHVGw…0fCKJE1XVzA=="
1240
- El-Gamal signature: OK
1241
- $ poetry run transcrypto --b64 -p eg-key.pub elgamal verify "eLl6" "Xl4hlYK8SHVGw…0fCKJE1XVzA=="
1242
- El-Gamal signature: INVALID
1243
- ```
1244
-
1245
- ---
1246
-
1247
- ### `dsa`
1248
-
1249
- 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).
1250
-
1251
- ```bash
1252
- poetry run transcrypto dsa [-h]
1253
- {shared,new,rawsign,sign,rawverify,verify} ...
1254
- ```
1255
-
1256
- #### `dsa shared`
1257
-
1258
- 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.
1259
-
1260
- ```bash
1261
- poetry run transcrypto dsa shared [-h] [--p-bits P_BITS]
1262
- [--q-bits Q_BITS]
1263
- ```
1264
-
1265
- | Option/Arg | Description |
1266
- |---|---|
1267
- | `--p-bits` | Prime modulus (`p`) size in bits; the default is a safe size [type: int (default: 4096)] |
1268
- | `--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)] |
1269
-
1270
- **Example:**
1271
-
1272
- ```bash
1273
- $ poetry run transcrypto -p dsa-key dsa shared --p-bits 128 --q-bits 32 # NEVER use such a small key: example only!
1274
- DSA shared key saved to 'dsa-key.shared'
1275
- ```
1276
-
1277
- #### `dsa new`
1278
-
1279
- Generate an individual DSA private/public key pair from a shared key.
1280
-
1281
- ```bash
1282
- poetry run transcrypto dsa new [-h]
1283
- ```
1284
-
1285
- **Example:**
1286
-
1287
- ```bash
1288
- $ poetry run transcrypto -p dsa-key dsa new
1289
- DSA private/public keys saved to 'dsa-key.priv/.pub'
1290
- ```
1291
-
1292
- #### `dsa rawsign`
1293
-
1294
- Raw sign *integer* message with private key (BEWARE: no ECDSA/EdDSA padding or validation). Output will 2 *integers* in a `s1:s2` format.
1295
-
1296
- ```bash
1297
- poetry run transcrypto dsa rawsign [-h] message
1298
- ```
1299
-
1300
- | Option/Arg | Description |
1301
- |---|---|
1302
- | `message` | Integer message to sign, 1≤`message`<`q` [type: str] |
1303
-
1304
- **Example:**
1305
-
1306
- ```bash
1307
- $ poetry run transcrypto -p dsa-key.priv dsa rawsign 999
1308
- 2395961484:3435572290
1309
- ```
1310
-
1311
- #### `dsa sign`
1312
-
1313
- Sign message with private key.
1314
-
1315
- ```bash
1316
- poetry run transcrypto dsa sign [-h] [-a AAD] message
1317
- ```
1318
-
1319
- | Option/Arg | Description |
1320
- |---|---|
1321
- | `message` | Message to sign [type: str] |
1322
- | `-a, --aad` | Associated data (optional; has to be separately sent to receiver/stored) [type: str] |
1323
-
1324
- **Example:**
1325
-
1326
- ```bash
1327
- $ poetry run transcrypto --bin --out-b64 -p dsa-key.priv dsa sign "xyz"
1328
- yq8InJVpViXh9…BD4par2XuA=
1329
- ```
1330
-
1331
- #### `dsa rawverify`
1332
-
1333
- Raw verify *integer* `signature` for *integer* `message` with public key (BEWARE: no ECDSA/EdDSA padding or validation).
1334
-
1335
- ```bash
1336
- poetry run transcrypto dsa rawverify [-h] message signature
1337
- ```
1338
-
1339
- | Option/Arg | Description |
1340
- |---|---|
1341
- | `message` | Integer message that was signed earlier, 1≤`message`<`q` [type: str] |
1342
- | `signature` | Integer putative signature for `message`; expects `s1:s2` format with 2 integers, 2≤`s1`,`s2`<`q` [type: str] |
1343
-
1344
- **Example:**
1345
-
1346
- ```bash
1347
- $ poetry run transcrypto -p dsa-key.pub dsa rawverify 999 2395961484:3435572290
1348
- DSA signature: OK
1349
- $ poetry run transcrypto -p dsa-key.pub dsa rawverify 999 2395961484:3435572291
1350
- DSA signature: INVALID
1351
- ```
1352
-
1353
- #### `dsa verify`
1354
-
1355
- Verify `signature` for `message` with public key.
1356
-
1357
- ```bash
1358
- poetry run transcrypto dsa verify [-h] [-a AAD] message signature
1359
- ```
1360
-
1361
- | Option/Arg | Description |
1362
- |---|---|
1363
- | `message` | Message that was signed earlier [type: str] |
1364
- | `signature` | Putative signature for `message` [type: str] |
1365
- | `-a, --aad` | Associated data (optional; has to be exactly the same as used during signing) [type: str] |
1366
-
1367
- **Example:**
1368
-
1369
- ```bash
1370
- $ poetry run transcrypto --b64 -p dsa-key.pub dsa verify "eHl6" "yq8InJVpViXh9…BD4par2XuA="
1371
- DSA signature: OK
1372
- $ poetry run transcrypto --b64 -p dsa-key.pub dsa verify "eLl6" "yq8InJVpViXh9…BD4par2XuA="
1373
- DSA signature: INVALID
1374
- ```
1375
-
1376
- ---
1377
-
1378
- ### `bid`
1379
-
1380
- Bidding on a `secret` so that you can cryptographically convince a neutral party that the `secret` that was committed to previously was not changed. All methods require file key(s) as `-p`/`--key-path` (see provided examples).
1381
-
1382
- ```bash
1383
- poetry run transcrypto bid [-h] {new,verify} ...
1384
- ```
1385
-
1386
- #### `bid new`
1387
-
1388
- Generate the bid files for `secret`. Requires `-p`/`--key-path` to set the basename for output files.
1389
-
1390
- ```bash
1391
- poetry run transcrypto bid new [-h] secret
1392
- ```
1393
-
1394
- | Option/Arg | Description |
1395
- |---|---|
1396
- | `secret` | Input data to bid to, the protected "secret" [type: str] |
1397
-
1398
- **Example:**
1399
-
1400
- ```bash
1401
- $ poetry run transcrypto --bin -p my-bid bid new "tomorrow it will rain"
1402
- Bid private/public commitments saved to 'my-bid.priv/.pub'
1403
- ```
1404
-
1405
- #### `bid verify`
1406
-
1407
- Verify the bid files for correctness and reveal the `secret`. Requires `-p`/`--key-path` to set the basename for output files.
1408
-
1409
- ```bash
1410
- poetry run transcrypto bid verify [-h]
1411
- ```
1412
-
1413
- **Example:**
1414
-
1415
- ```bash
1416
- $ poetry run transcrypto --out-bin -p my-bid bid verify
1417
- Bid commitment: OK
1418
- Bid secret:
1419
- tomorrow it will rain
1420
- ```
1421
-
1422
- ---
1423
-
1424
- ### `sss`
1425
-
1426
- 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).
1427
-
1428
- ```bash
1429
- poetry run transcrypto sss [-h]
1430
- {new,rawshares,shares,rawrecover,recover,rawverify} ...
1431
- ```
1432
-
1433
- #### `sss new`
1434
-
1435
- Generate the private keys with `bits` prime modulus size and so that at least a `minimum` number of shares are needed to recover the secret. This key will be used to generate the shares later (with the `shares` command). Requires `-p`/`--key-path` to set the basename for output files.
1436
-
1437
- ```bash
1438
- poetry run transcrypto sss new [-h] [--bits BITS] minimum
1439
- ```
1440
-
1441
- | Option/Arg | Description |
1442
- |---|---|
1443
- | `minimum` | Minimum number of shares required to recover secret, ≥ 2 [type: int] |
1444
- | `--bits` | Prime modulus (`p`) size in bits; the default is a safe size ***IFF*** you are protecting symmetric keys; the number of bits should be comfortably larger than the size of the secret you want to protect with this scheme [type: int (default: 1024)] |
1445
-
1446
- **Example:**
1447
-
1448
- ```bash
1449
- $ poetry run transcrypto -p sss-key sss new 3 --bits 64 # NEVER use such a small key: example only!
1450
- SSS private/public keys saved to 'sss-key.priv/.pub'
1451
- ```
1452
-
1453
- #### `sss rawshares`
1454
-
1455
- Raw shares: Issue `count` private shares for an *integer* `secret` (BEWARE: no modern message wrapping, padding or validation).
1456
-
1457
- ```bash
1458
- poetry run transcrypto sss rawshares [-h] secret count
1459
- ```
1460
-
1461
- | Option/Arg | Description |
1462
- |---|---|
1463
- | `secret` | Integer secret to be protected, 1≤`secret`<*modulus* [type: str] |
1464
- | `count` | How many shares to produce; must be ≥ `minimum` used in `new` command or else the `secret` would become unrecoverable [type: int] |
1465
-
1466
- **Example:**
1467
-
1468
- ```bash
1469
- $ poetry run transcrypto -p sss-key sss rawshares 999 5
1470
- SSS 5 individual (private) shares saved to 'sss-key.share.1…5'
1471
- $ rm sss-key.share.2 sss-key.share.4 # this is to simulate only having shares 1,3,5
1472
- ```
1473
-
1474
- #### `sss shares`
1475
-
1476
- Shares: Issue `count` private shares for a `secret`.
1477
-
1478
- ```bash
1479
- poetry run transcrypto sss shares [-h] secret count
1480
- ```
1481
-
1482
- | Option/Arg | Description |
1483
- |---|---|
1484
- | `secret` | Secret to be protected [type: str] |
1485
- | `count` | How many shares to produce; must be ≥ `minimum` used in `new` command or else the `secret` would become unrecoverable [type: int] |
1486
-
1487
- **Example:**
1488
-
1489
- ```bash
1490
- $ poetry run transcrypto --bin -p sss-key sss shares "abcde" 5
1491
- SSS 5 individual (private) shares saved to 'sss-key.share.1…5'
1492
- $ rm sss-key.share.2 sss-key.share.4 # this is to simulate only having shares 1,3,5
1493
- ```
1494
-
1495
- #### `sss rawrecover`
1496
-
1497
- Raw recover *integer* secret from shares; will use any available shares that were found (BEWARE: no modern message wrapping, padding or validation).
1498
-
1499
- ```bash
1500
- poetry run transcrypto sss rawrecover [-h]
1501
- ```
1502
-
1503
- **Example:**
1504
-
1505
- ```bash
1506
- $ poetry run transcrypto -p sss-key sss rawrecover
1507
- Loaded SSS share: 'sss-key.share.3'
1508
- Loaded SSS share: 'sss-key.share.5'
1509
- Loaded SSS share: 'sss-key.share.1' # using only 3 shares: number 2/4 are missing
1510
- Secret:
1511
- 999
1512
- ```
1513
-
1514
- #### `sss recover`
1515
-
1516
- Recover secret from shares; will use any available shares that were found.
1517
-
1518
- ```bash
1519
- poetry run transcrypto sss recover [-h]
1520
- ```
1521
-
1522
- **Example:**
1523
-
1524
- ```bash
1525
- $ poetry run transcrypto --out-bin -p sss-key sss recover
1526
- Loaded SSS share: 'sss-key.share.3'
1527
- Loaded SSS share: 'sss-key.share.5'
1528
- Loaded SSS share: 'sss-key.share.1' # using only 3 shares: number 2/4 are missing
1529
- Secret:
1530
- abcde
1531
- ```
1532
-
1533
- #### `sss rawverify`
1534
-
1535
- Raw verify shares against a secret (private params; BEWARE: no modern message wrapping, padding or validation).
1536
-
1537
- ```bash
1538
- poetry run transcrypto sss rawverify [-h] secret
1539
- ```
1540
-
1541
- | Option/Arg | Description |
1542
- |---|---|
1543
- | `secret` | Integer secret used to generate the shares [type: str] |
1544
-
1545
- **Example:**
1546
-
1547
- ```bash
1548
- $ poetry run transcrypto -p sss-key sss rawverify 999
1549
- SSS share 'sss-key.share.3' verification: OK
1550
- SSS share 'sss-key.share.5' verification: OK
1551
- SSS share 'sss-key.share.1' verification: OK
1552
- $ poetry run transcrypto -p sss-key sss rawverify 998
1553
- SSS share 'sss-key.share.3' verification: INVALID
1554
- SSS share 'sss-key.share.5' verification: INVALID
1555
- SSS share 'sss-key.share.1' verification: INVALID
1556
- ```
1557
-
1558
- ---
1559
-
1560
- ### `doc`
1561
-
1562
- Documentation utilities. (Not for regular use: these are developer utils.)
1563
-
1564
- ```bash
1565
- poetry run transcrypto doc [-h] {md} ...
1566
- ```
1567
-
1568
- #### `doc md`
1569
-
1570
- Emit Markdown docs for the CLI (see README.md section "Creating a New Version").
1571
-
1572
- ```bash
1573
- poetry run transcrypto doc md [-h]
1574
- ```
1575
-
1576
- **Example:**
1577
-
1578
- ```bash
1579
- $ poetry run transcrypto doc md > CLI.md
1580
- $ ./tools/inject_md_includes.py
1581
- inject: README.md updated with included content
1582
- ```
1583
- <!-- INCLUDE:CLI.md END -->
1584
- <!-- (auto-generated; do not edit between START/END) -->
1585
-
1586
- <!-- cspell:enable -->
1587
-
1588
- ### Base Library
1589
-
1590
- #### Humanized Sizes (IEC binary)
1591
-
1592
- ```py
1593
- from transcrypto import utils
1594
-
1595
- utils.HumanizedBytes(512) # '512 B'
1596
- utils.HumanizedBytes(2048) # '2.00 KiB'
1597
- utils.HumanizedBytes(5 * 1024**3) # '5.00 GiB'
1598
- ```
1599
-
1600
- Converts raw byte counts to binary-prefixed strings (`B`, `KiB`, `MiB`, `GiB`, `TiB`, `PiB`, `EiB`). Values under 1024 bytes are returned as integers with `B`; larger values use two decimals.
1601
-
1602
- - standard: 1 KiB = 1024 B, 1 MiB = 1024 KiB, …
1603
- - errors: negative inputs raise `InputError`
1604
-
1605
- #### Humanized Decimal Quantities (SI)
1606
-
1607
- ```py
1608
- # Base (unitless)
1609
- utils.HumanizedDecimal(950) # '950'
1610
- utils.HumanizedDecimal(1500) # '1.50 k'
1611
-
1612
- # With a unit (trimmed and attached)
1613
- utils.HumanizedDecimal(1500, ' Hz ') # '1.50 kHz'
1614
- utils.HumanizedDecimal(0.123456, 'V') # '0.1235 V'
1615
-
1616
- # Large magnitudes
1617
- utils.HumanizedDecimal(3_200_000) # '3.20 M'
1618
- utils.HumanizedDecimal(7.2e12, 'B/s') # '7.20 TB/s'
1619
- ```
1620
-
1621
- Scales by powers of 1000 using SI prefixes (`k`, `M`, `G`, `T`, `P`, `E`). For values `<1000`, integers are shown as-is; small floats show four decimals. For scaled values, two decimals are used and the unit (if provided) is attached without a space (e.g., `kHz`).
1622
-
1623
- - unit handling: `unit` is stripped; `<1000` values include a space before the unit (`'950 Hz'`)
1624
- - errors: negative or non-finite inputs raise `InputError`
1625
-
1626
- #### Humanized Durations
1627
-
1628
- ```py
1629
- utils.HumanizedSeconds(0) # '0.00 s'
1630
- utils.HumanizedSeconds(0.000004) # '4.000 µs'
1631
- utils.HumanizedSeconds(0.25) # '250.000 ms'
1632
- utils.HumanizedSeconds(42) # '42.00 s'
1633
- utils.HumanizedSeconds(3661) # '1.02 h'
1634
- utils.HumanizedSeconds(172800) # '2.00 d'
1635
- ```
1636
-
1637
- Chooses an appropriate time unit based on magnitude and formats with fixed precision:
1638
-
1639
- - `< 1 ms`: microseconds with three decimals (`µs`)
1640
- - `< 1 s`: milliseconds with three decimals (`ms`)
1641
- - `< 60 s`: seconds with two decimals (`s`)
1642
- - `< 60 min`: minutes with two decimals (`min`)
1643
- - `< 24 h`: hours with two decimals (`h`)
1644
- - `≥ 24 h`: days with two decimals (`d`)
1645
- - special case: `0 → '0.00 s'`
1646
- - errors: negative or non-finite inputs raise `InputError`
1647
-
1648
- #### Execution Timing
1649
-
1650
- A flexible timing utility that works as a **context manager**, **decorator**, or **manual timer object**.
1651
-
1652
- ```py
1653
- from transcrypto import base
1654
- import time
1655
- ```
1656
-
1657
- ##### Context manager
1658
-
1659
- ```py
1660
- with base.Timer('Block timing'):
1661
- time.sleep(1.2)
1662
- # → logs: "Block timing: 1.20 s" (default via logging.info)
1663
- ```
1664
-
1665
- Starts timing on entry, stops on exit, and reports elapsed time automatically.
1666
-
1667
- ##### Decorator
1668
-
1669
- ```py
1670
- @base.Timer('Function timing')
1671
- def slow_function():
1672
- time.sleep(0.8)
1673
-
1674
- slow_function()
1675
- # → logs: "Function timing: 0.80 s"
1676
- ```
1677
-
1678
- Wraps a function so that each call is automatically timed.
1679
-
1680
- ##### Manual use
1681
-
1682
- ```py
1683
- tm = base.Timer('Inline timing', emit_print=True)
1684
- tm.Start()
1685
- time.sleep(0.1)
1686
- tm.Stop() # prints: "Inline timing: 0.10 s"
1687
- ```
1688
-
1689
- Manual control over `Start()` and `Stop()` for precise measurement of custom intervals.
1690
-
1691
- ##### Key points
1692
-
1693
- - **Label**: required, shown in output; empty labels raise `InputError`
1694
- - **Output**:
1695
- - `emit_log=True` → `logging.info()` (default)
1696
- - `emit_print=True` → direct `print()`
1697
- - Both can be enabled
1698
- - **Format**: elapsed time is shown using `HumanizedSeconds()`
1699
- - **Safety**:
1700
- - Cannot start an already started timer
1701
- - Cannot stop an unstarted or already stopped timer
1702
- (raises `Error`)
1703
-
1704
- #### Serialization Pipeline
1705
-
1706
- These helpers turn arbitrary Python objects into compressed and/or encrypted binary blobs, and back again — with detailed timing and size logging.
1707
-
1708
- ```py
1709
- from transcrypto import base
1710
- ```
1711
-
1712
- ##### Serialize
1713
-
1714
- ```py
1715
- data = {'x': 42, 'y': 'hello'}
1716
-
1717
- # Basic serialization
1718
- blob = base.Serialize(data)
1719
-
1720
- # With compression and encryption
1721
- blob = base.Serialize(
1722
- data,
1723
- compress=9, # compression level (-22..22, default=3)
1724
- key=my_symmetric_key # must implement SymmetricCrypto
1725
- )
1726
-
1727
- # Save directly to file
1728
- base.Serialize(data, file_path='/tmp/data.blob')
1729
- ```
1730
-
1731
- Serialization path:
1732
-
1733
- ```text
1734
- obj → pickle → (compress) → (encrypt) → (save)
1735
- ```
1736
-
1737
- At each stage:
1738
-
1739
- - Data size is measured using `HumanizedBytes`
1740
- - Duration is timed with `Timer`
1741
- - Results are logged once at the end
1742
-
1743
- Compression levels:
1744
-
1745
- `compress` uses `zstandard`; see table below for speed/ratio trade-offs:
1746
-
1747
- | Level | Speed | Compression ratio | Typical use case |
1748
- | -------- | ------------| --------------------------------- | --------------------------------------- |
1749
- | -5 to -1 | Fastest | Poor (better than no compression) | Real-time or very latency-sensitive |
1750
- | 0…3 | Very fast | Good ratio | Default CLI choice, safe baseline |
1751
- | 4…6 | Moderate | Better ratio | Good compromise for general persistence |
1752
- | 7…10 | Slower | Marginally better ratio | Only if storage space is precious |
1753
- | 11…15 | Much slower | Slight gains | Large archives, not for runtime use |
1754
- | 16…22 | Very slow | Tiny gains | Archival-only, multi-GB datasets |
1755
-
1756
- Errors: invalid compression level is clamped to range; other input errors raise `InputError`.
1757
-
1758
- ##### DeSerialize
1759
-
1760
- ```py
1761
- # From in-memory blob
1762
- obj = base.DeSerialize(data=blob)
1763
-
1764
- # From file
1765
- obj = base.DeSerialize(file_path='/tmp/data.blob')
1766
-
1767
- # With decryption
1768
- obj = base.DeSerialize(data=blob, key=my_symmetric_key)
1769
- ```
1770
-
1771
- Deserialization path:
1772
-
1773
- ```text
1774
- data/file → (decrypt) → (decompress if Zstd) → unpickle
1775
- ```
1776
-
1777
- - Compression is auto-detected via Zstandard magic numbers.
1778
- - All steps are timed/logged like in `Serialize`.
1779
-
1780
- **Constraints & errors**:
1781
-
1782
- - Exactly one of `data` or `file_path` must be provided.
1783
- - `file_path` must exist; `data` must be at least 4 bytes.
1784
- - Wrong key or corrupted data can raise `CryptoError`.
1785
-
1786
- #### Cryptographically Secure Randomness
1787
-
1788
- These helpers live in `base` and wrap Python’s `secrets` with additional checks and guarantees for crypto use-cases.
1789
-
1790
- ```py
1791
- from transcrypto import base
1792
- ```
1793
-
1794
- ##### Fixed-size random integers
1795
-
1796
- ```py
1797
- # Generate a 256-bit integer (first bit always set)
1798
- r = base.RandBits(256)
1799
- assert r.bit_length() == 256
1800
- ```
1801
-
1802
- 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.
1803
-
1804
- - errors: `n_bits < 8` → `InputError`
1805
-
1806
- ##### Uniform random integers in a range
1807
-
1808
- ```py
1809
- # Uniform between [10, 20] inclusive
1810
- n = base.RandInt(10, 20)
1811
- assert 10 <= n <= 20
1812
- ```
1813
-
1814
- Returns a crypto-secure integer uniformly distributed over the closed interval `[min_int, max_int]`.
1815
-
1816
- - constraints: `min_int ≥ 0` and `< max_int`
1817
- - errors: invalid bounds → `InputError`
1818
-
1819
- ##### In-place secure shuffle
1820
-
1821
- ```py
1822
- deck = list(range(10))
1823
- base.RandShuffle(deck)
1824
- print(deck) # securely shuffled order
1825
- ```
1826
-
1827
- Performs an in-place Fisher–Yates shuffle using `secrets.randbelow`. Suitable for sensitive data ordering.
1828
-
1829
- - constraints: sequence length ≥ 2
1830
- - errors: shorter sequences → `InputError`
1831
-
1832
- ##### Random byte strings
1833
-
1834
- ```py
1835
- # 32 random bytes
1836
- b = base.RandBytes(32)
1837
- assert len(b) == 32
1838
- ```
1839
-
1840
- Generates `n_bytes` of high-quality crypto-secure random data.
1841
-
1842
- - constraints: `n_bytes ≥ 1`
1843
- - errors: smaller values → `InputError`
1844
-
1845
- #### Computing the Greatest Common Divisor
1846
-
1847
- ```py
1848
- >>> from transcrypto import base
1849
- >>> base.GCD(462, 1071)
1850
- 21
1851
- >>> base.GCD(0, 17)
1852
- 17
1853
- ```
1854
-
1855
- 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:
1856
-
1857
- ```py
1858
- >>> base.ExtendedGCD(462, 1071)
1859
- (21, -2, 1)
1860
- >>> 462 * -2 + 1071 * 1
1861
- 21
1862
- ```
1863
-
1864
- Use-cases:
1865
-
1866
- - modular inverses: `inv = x % m` when `gcd(a, m) == 1`
1867
- - solving linear Diophantine equations
1868
- - RSA / ECC key generation internals
1869
-
1870
- #### Fast Modular Arithmetic
1871
-
1872
- ```py
1873
- from transcrypto import modmath
1874
-
1875
- m = 2**256 - 189 # a large prime modulus
1876
-
1877
- # Inverse ──────────────────────────────
1878
- x = 123456789
1879
- x_inv = modmath.ModInv(x, m)
1880
- assert (x * x_inv) % m == 1
1881
-
1882
- # Division (x / y) mod m ──────────────
1883
- y = 987654321
1884
- z = modmath.ModDiv(x, y, m) # solves z·y ≡ x (mod m)
1885
- assert (z * y) % m == x % m
1886
-
1887
- # Exponentiation ──────────────────────
1888
- exp = modmath.ModExp(3, 10**20, m) # ≈ log₂(y) time, handles huge exponents
1889
- ```
1890
-
1891
- ##### Chinese Remainder Theorem (CRT) – Pair
1892
-
1893
- ```py
1894
- from transcrypto import modmath
1895
-
1896
- # Solve:
1897
- # x ≡ 2 (mod 3)
1898
- # x ≡ 3 (mod 5)
1899
- x = modmath.CRTPair(2, 3, 3, 5)
1900
- print(x) # 8
1901
- assert x % 3 == 2
1902
- assert x % 5 == 3
1903
- ```
1904
-
1905
- Solves a system of two simultaneous congruences with **pairwise co-prime** moduli, returning the **least non-negative solution** `x` such that:
1906
-
1907
- ```text
1908
- x ≡ a1 (mod m1)
1909
- x ≡ a2 (mod m2)
1910
- 0 ≤ x < m1 * m2
1911
- ```
1912
-
1913
- - **Requirements**:
1914
- - `m1 ≥ 2`, `m2 ≥ 2`, `m1 != m2`
1915
- - `gcd(m1, m2) == 1` (co-prime)
1916
- - **Errors**:
1917
- - invalid modulus values → `InputError`
1918
- - non co-prime moduli → `ModularDivideError`
1919
-
1920
- This function is a 2-modulus variant; for multiple moduli, apply it iteratively or use a general CRT solver.
1921
-
1922
- ##### Modular Polynomials & Lagrange Interpolation
1923
-
1924
- ```py
1925
- # f(t) = 7t³ − 3t² + 2t + 5 (coefficients constant-term first)
1926
- coefficients = [5, 2, -3, 7]
1927
- print(modmath.ModPolynomial(11, coefficients, 97)) # → 19
1928
-
1929
- # Given three points build the degree-≤2 polynomial and evaluate it.
1930
- pts = {2: 4, 5: 3, 7: 1}
1931
- print(modmath.ModLagrangeInterpolate(9, pts, 11)) # → 2
1932
- ```
1933
-
1934
- #### Primality testing & Prime generators, Mersenne primes
1935
-
1936
- ```py
1937
- modmath.IsPrime(2**127 - 1) # True (Mersenne prime)
1938
- modmath.IsPrime(3825123056546413051) # False (strong pseudo-prime)
1939
-
1940
- # Direct Miller–Rabin with custom witnesses
1941
- modmath.MillerRabinIsPrime(961748941, witnesses={2,7,61})
1942
-
1943
- # Infinite iterator of primes ≥ 10⁶
1944
- for p in modmath.PrimeGenerator(1_000_000):
1945
- print(p)
1946
- if p > 1_000_100:
1947
- break
1948
-
1949
- # Secure random 384-bit prime (for RSA/ECC experiments)
1950
- p384 = modmath.NBitRandomPrime(384)
1951
-
1952
- for k, m_p, perfect in modmath.MersennePrimesGenerator(0):
1953
- print(f'p = {k:>8} M = {m_p} perfect = {perfect}')
1954
- if k > 10000: # stop after a few
1955
- break
1956
- ```
1957
-
1958
- #### Cryptographic Hashing
1959
-
1960
- Simple, fixed-output-size wrappers over Python’s `hashlib` for common digest operations, plus file hashing.
1961
-
1962
- ```py
1963
- from transcrypto import base
1964
- ```
1965
-
1966
- ##### SHA-256 hashing
1967
-
1968
- ```py
1969
- h = base.Hash256(b'hello world')
1970
- assert len(h) == 32 # bytes
1971
- print(h.hex()) # 64 hex chars
1972
- ```
1973
-
1974
- Computes the SHA-256 digest of a byte string, returning exactly 32 bytes (256 bits). Suitable for fingerprints, commitments, or internal crypto primitives.
1975
-
1976
- ##### SHA-512 hashing
1977
-
1978
- ```py
1979
- h = base.Hash512(b'hello world')
1980
- assert len(h) == 64 # bytes
1981
- print(h.hex()) # 128 hex chars
1982
- ```
1983
-
1984
- 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.
1985
-
1986
- ##### File hashing
1987
-
1988
- ```py
1989
- # Default SHA-256
1990
- fh = base.FileHash('/path/to/file')
1991
- print(fh.hex())
1992
-
1993
- # SHA-512
1994
- fh2 = base.FileHash('/path/to/file', digest='sha512')
1995
- ```
1996
-
1997
- Hashes a file from disk in streaming mode. By default uses SHA-256; `digest='sha512'` switches to SHA-512.
1998
-
1999
- - constraints:
2000
- - `digest` must be `'sha256'` or `'sha512'`
2001
- - `full_path` must exist
2002
- - errors: invalid digest or missing file → `InputError`
2003
-
2004
- #### Symmetric Encryption Interface
2005
-
2006
- `SymmetricCrypto` is an abstract base class that defines the **byte-in / byte-out** contract for symmetric ciphers.
2007
-
2008
- - **Metadata handling** — if the algorithm uses a `nonce` or `tag`, the implementation must handle it internally (e.g., append it to ciphertext).
2009
- - **AEAD modes** — if supported, `associated_data` must be authenticated; otherwise, a non-`None` value should raise `InputError`.
2010
-
2011
- ```py
2012
- class MyAES(base.SymmetricCrypto):
2013
- def Encrypt(self, plaintext: bytes, *, associated_data=None) -> bytes:
2014
- ...
2015
- def Decrypt(self, ciphertext: bytes, *, associated_data=None) -> bytes:
2016
- ...
2017
- ```
2018
-
2019
- #### Crypto Objects General Properties (`CryptoKey`)
2020
-
2021
- Cryptographic objects all derive from the `CryptoKey` class and will all have some important characteristics:
2022
-
2023
- - 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…`).
2024
- - It will have a `_DebugDump()` method that **does print secrets** and can be used for **debugging only**.
2025
- - Can be easily serialized to `bytes` by the `blob` property and to base-64 encoded `str` by the `encoded` property.
2026
- - 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.
2027
- - 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.
2028
-
2029
- Example:
2030
-
2031
- <!-- cspell:disable -->
2032
- ```py
2033
- from transcrypto import base, rsa, aes
2034
-
2035
- priv = rsa.RSAPrivateKey.New(512) # small key, but good for this example
2036
- print(str(priv)) # safe, no secrets
2037
- # ▶ RSAPrivateKey(RSAPublicKey(public_modulus=pQaoxy-QeXSds1k9WsGjJw==, encrypt_exp=AQAB), modulus_p=f18141aa…, modulus_q=67494eb9…, decrypt_exp=c96db24a…)
2038
-
2039
- print(priv._DebugDump()) # UNSAFE: prints secrets
2040
- # ▶ 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)
2041
-
2042
- print(priv.blob)
2043
- # ▶ 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."
2044
-
2045
- print(priv.encoded)
2046
- # ▶ KLUv_WBwAIELAIAElWUBAAAAAAAAjA90cmFuc2NyeXB0by5yc2GUjA1SU0FQcml2YXRlS2V5lJOUKYGUXZQoikHf1EvsmZedAZve7TrLmobLAwuRIr_77TLG6G_0fsLGThERVJu075be8PLjUQYnLXcacZFQ5Fb1Iy1WtiE985euAEoBAAEAiiFR9ngiXMzkf41o5CRBY3h0D4DJVisDDhLmAWsiaHggzQCKIS_cmQ6MKXCtROtC7c_Mrsi9A-9NM8DksaHaRwvy6uTZAIpB4TVbsLxc41TEc19wIzpxbi9y5dW5gdfTkRQSSiz0ijmb8Xk3pyBfKAv8JbHp8Yv48gNZUfX67qq0J7yhJqeUoACKIbFb2kTNRzSqm3JRtjc2BPS-FnLFdadlFcV4-6IW7eqLAIogFZfzDN39gZLR9uTz4KHSTaqxWrJgP8-YYssjss6FlFKKIIItgCDv7ompNpY8gBs5bibN8XTsr-JOYSntDVT5Fe5vZWIu
2047
-
2048
- key = aes.AESKey(key256=b'x' * 32)
2049
- print(key)
2050
- # ▶ AESKey(key256=86a86df7…)
2051
-
2052
- encrypted = priv.Blob(key=key)
2053
- print(priv == rsa.RSAPrivateKey.Load(encrypted, key=key))
2054
- # ▶ True
2055
- ```
2056
- <!-- cspell:enable -->
2057
-
2058
- #### AES-256 Symmetric Encryption
2059
-
2060
- Implements AES-256 in **GCM mode** for authenticated encryption and decryption, plus an **ECB mode** helper for fixed-size block encoding.
2061
- Also includes a high-iteration PBKDF2-based key derivation from static passwords.
2062
-
2063
- ##### Key creation
2064
-
2065
- ```py
2066
- from transcrypto import aes
2067
-
2068
- # From raw bytes (must be exactly 32 bytes)
2069
- key = aes.AESKey(key256=b'\x00' * 32)
2070
-
2071
- # From a static password (slow, high-iteration PBKDF2-SHA256)
2072
- key = aes.AESKey.FromStaticPassword('correct horse battery staple')
2073
- print(key.encoded) # URL-safe Base64
2074
- ```
2075
-
2076
- - **Length**: `key256` must be exactly 32 bytes
2077
- - `FromStaticPassword()`:
2078
- - Uses PBKDF2-HMAC-SHA256 with **fixed** salt and \~2 million iterations
2079
- - Designed for **interactive** password entry, **not** for password databases
2080
-
2081
- ##### AES-256 + GCM (default)
2082
-
2083
- ```py
2084
- data = b'secret message'
2085
- aad = b'metadata'
2086
-
2087
- # Encrypt (returns IV + ciphertext + tag)
2088
- ct = key.Encrypt(data, associated_data=aad)
2089
-
2090
- # Decrypt
2091
- pt = key.Decrypt(ct, associated_data=aad)
2092
- assert pt == data
2093
- ```
2094
-
2095
- - **Security**:
2096
- - Random 128-bit IV (`iv`) per encryption
2097
- - Authenticated tag (128-bit) ensures integrity
2098
- - Optional `associated_data` is authenticated but not encrypted
2099
- - **Errors**:
2100
- - Tag mismatch or wrong key → `CryptoError`
2101
-
2102
- ##### AES-256 + ECB (unsafe, fixed block only)
2103
-
2104
- ```py
2105
- # ECB mode is for 16-byte block encoding ONLY
2106
- ecb = key.ECBEncoder()
2107
-
2108
- block = b'16-byte string!!'
2109
- ct_block = ecb.Encrypt(block)
2110
- pt_block = ecb.Decrypt(ct_block)
2111
- assert pt_block == block
2112
-
2113
- # Hex helpers
2114
- hex_ct = ecb.EncryptHex('00112233445566778899aabbccddeeff')
2115
- ```
2116
-
2117
- - **ECB mode**:
2118
- - 16-byte plaintext ↔ 16-byte ciphertext
2119
- - No padding, no IV, no integrity — **do not use for general encryption**
2120
- - `associated_data` not supported
2121
-
2122
- Key points:
2123
-
2124
- - **GCM mode** is secure for general use; ECB mode is for special low-level operations
2125
- - **Static password derivation** is intentionally slow to resist brute force
2126
- - All sizes and parameters are validated with `InputError` on misuse
2127
-
2128
- #### RSA (Rivest-Shamir-Adleman) Public Cryptography
2129
-
2130
- <https://en.wikipedia.org/wiki/RSA_cryptosystem>
2131
-
2132
- This implementation is raw RSA, no OAEP or PSS! It works on the actual integers. For real uses you should look for higher-level implementations.
2133
-
2134
- By default and deliberate choice the *encryption exponent* will be either 7 or 65537, depending on the size of `phi=(p-1)*(q-1)`. If `phi` allows it the larger one will be chosen to avoid Coppersmith attacks.
2135
-
2136
- ```py
2137
- from transcrypto import rsa
2138
-
2139
- # Generate a key pair
2140
- priv = rsa.RSAPrivateKey.New(2048) # 2048-bit modulus
2141
- pub = rsa.RSAPublicKey.Copy(priv) # public half
2142
- print(priv.public_modulus.bit_length()) # 2048
2143
-
2144
- # Safe Encrypt & decrypt
2145
- msg = b'xyz'
2146
- cipher = pub.Encrypt(msg, associated_data=b'aad')
2147
- plain = priv.Decrypt(cipher, associated_data=b'aad')
2148
- assert plain == msg
2149
-
2150
- # Safe Sign & verify
2151
- signature = priv.Sign(msg) # can also have associated_data, optionally
2152
- assert pub.Verify(msg, signature)
2153
-
2154
- # Raw Encrypt & decrypt
2155
- msg = 123456789 # (Zero is forbidden by design; smallest valid message is 1.)
2156
- cipher = pub.RawEncrypt(msg)
2157
- plain = priv.RawDecrypt(cipher)
2158
- assert plain == msg
2159
-
2160
- # Raw Sign & verify
2161
- signature = priv.RawSign(msg)
2162
- assert pub.RawVerify(msg, signature)
2163
-
2164
- # Blind signatures (obfuscation pair) - only works on raw RSA
2165
- pair = rsa.RSAObfuscationPair.New(pub)
2166
-
2167
- blind_msg = pair.ObfuscateMessage(msg) # what you send to signer
2168
- blind_sig = priv.RawSign(blind_msg) # signer’s output
2169
-
2170
- sig = pair.RevealOriginalSignature(msg, blind_sig)
2171
- assert pub.RawVerify(msg, sig)
2172
- ```
2173
-
2174
- #### El-Gamal Public-Key Cryptography
2175
-
2176
- [https://en.wikipedia.org/wiki/ElGamal\_encryption](https://en.wikipedia.org/wiki/ElGamal_encryption)
2177
-
2178
- This is **raw El-Gamal** over a prime field — no padding, no hashing — and is **not** DSA.
2179
- For real-world deployments, use a high-level library with authenticated encryption and proper encoding.
2180
-
2181
- ```py
2182
- from transcrypto import elgamal
2183
-
2184
- # Shared parameters (prime modulus, group base) for a group
2185
- shared = elgamal.ElGamalSharedPublicKey.New(256)
2186
- print(shared.prime_modulus)
2187
- print(shared.group_base)
2188
-
2189
- # Public key from private
2190
- priv = elgamal.ElGamalPrivateKey.New(shared)
2191
- pub = elgamal.ElGamalPublicKey.Copy(priv)
2192
-
2193
- # Safe Encrypt & decrypt
2194
- msg = b'xyz'
2195
- cipher = pub.Encrypt(msg, associated_data=b'aad')
2196
- plain = priv.Decrypt(cipher, associated_data=b'aad')
2197
- assert plain == msg
2198
-
2199
- # Safe Sign & verify
2200
- signature = priv.Sign(msg) # can also have associated_data, optionally
2201
- assert pub.Verify(msg, signature)
2202
-
2203
- # Raw Encryption
2204
- msg = 42
2205
- cipher = pub.RawEncrypt(msg)
2206
- plain = priv.RawDecrypt(cipher)
2207
- assert plain == msg
2208
-
2209
- # Raw Signature verify
2210
- sig = priv.RawSign(msg)
2211
- assert pub.RawVerify(msg, sig)
2212
- ```
2213
-
2214
- Key points:
2215
-
2216
- - **Security parameters**:
2217
- - Recommended `prime_modulus` bit length ≥ 2048 for real security
2218
- - Random values from `base.RandBits`
2219
- - **Ephemeral keys**:
2220
- - Fresh per encryption/signature
2221
- - Must satisfy `gcd(k, p-1) == 1`
2222
- - **Errors**:
2223
- - Bad ranges → `InputError`
2224
- - Invalid math relationships → `CryptoError`
2225
- - **Group sharing**:
2226
- - Multiple parties can share `(p, g)` but have different `(individual_base, decrypt_exp)`
2227
-
2228
- #### DSA (Digital Signature Algorithm)
2229
-
2230
- [https://en.wikipedia.org/wiki/Digital\_Signature\_Algorithm](https://en.wikipedia.org/wiki/Digital_Signature_Algorithm)
2231
-
2232
- This is **raw DSA** over a prime field — **no hashing or padding**. You sign/verify **integers** modulo `q` (`prime_seed`). For real use, hash the message first (e.g., SHA-256) and then map to an integer `< q`.
2233
-
2234
- ```py
2235
- from transcrypto import dsa
2236
-
2237
- # Shared parameters (p, q, g)
2238
- shared = dsa.DSASharedPublicKey.New(p_bits=1024, q_bits=160)
2239
- print(shared.prime_modulus) # p
2240
- print(shared.prime_seed) # q (q | p-1)
2241
- print(shared.group_base) # g
2242
-
2243
- # Individual key pair
2244
- priv = dsa.DSAPrivateKey.New(shared)
2245
- pub = dsa.DSAPublicKey.Copy(priv)
2246
-
2247
- # Safe Sign & verify
2248
- msg = b'xyz'
2249
- signature = priv.Sign(msg) # can also have associated_data, optionally
2250
- assert pub.Verify(msg, signature)
2251
-
2252
- # Raw Sign & verify (message must be 1 ≤ m < q)
2253
- msg = 123456789 % shared.prime_seed
2254
- sig = priv.RawSign(msg)
2255
- assert pub.RawVerify(msg, sig)
2256
- ```
2257
-
2258
- - ranges:
2259
- - `1 ≤ message < q`
2260
- - signatures: `(s1, s2)` with `2 ≤ s1, s2 < q`
2261
- - errors:
2262
- - invalid ranges → `InputError`
2263
- - inconsistent parameters → `CryptoError`
2264
-
2265
- ##### Security notes
2266
-
2267
- - Choose **large** parameters (e.g., `p ≥ 2048 bits`, `q ≥ 224 bits`) for non-toy settings.
2268
- - In practice, compute `m = int.from_bytes(Hash(message), 'big') % q` before calling `Sign(m)`.
2269
-
2270
- ##### Advanced: custom primes generator
2271
-
2272
- ```py
2273
- # Generate primes (p, q) with q | (p-1); also returns m = (p-1)//q
2274
- p, q, m = dsa.NBitRandomDSAPrimes(p_bits=1024, q_bits=160)
2275
- assert (p - 1) % q == 0
2276
- ```
2277
-
2278
- Used internally by `DSASharedPublicKey.New()`.
2279
- Search breadth and retry caps are bounded; repeated failures raise `CryptoError`.
2280
-
2281
- #### Public Bidding
2282
-
2283
- This is a way of bidding on some commitment (the `secret`) that can be cryptographically proved later to not have been changed. To do that the secret is combined with 2 nonces (random values, `n1` & `n2`) and a hash of it is taken (`H=SHA-512(n1||n2||secret)`). The hash `H` and one nonce `n1` are public and divulged. The other nonce `n2` and the `secret` are kept private and will be used to show `secret` was not changed since the beginning of the process. The nonces guarantee the `secret` cannot be brute-forced or changed after-the-fact. The whole process is as strong as SHA-512 collisions.
2284
-
2285
- ```py
2286
- from transcrypto import base
2287
-
2288
- # Generate the private and public bids
2289
- bid_priv = base.PrivateBid512.New(secret) # this one you keep private
2290
- bid_pub = base.PublicBid512.Copy(bid_priv) # this one you publish
2291
-
2292
- # Checking that a bid is genuine requires the public bid and knowing the nonce and the secret:
2293
- print(bid_pub.VerifyBid(private_key, secret_bid)) # these come from a divulged private bid
2294
- # of course, you want to also make sure the provided private data matches your version of it, e.g.:
2295
- bid_pub_expected = base.PublicBid512.Copy(bid_priv)
2296
- print(bid_pub == bid_pub_expected)
2297
- ```
2298
-
2299
- #### SSS (Shamir Shared Secret)
2300
-
2301
- <https://en.wikipedia.org/wiki/Shamir's_secret_sharing>
2302
-
2303
- This is the information-theoretic SSS but with no authentication or binding between share and secret. Malicious share injection is possible! Add MAC or digital signature in hostile settings. Use at least 128-bit modulus for non-toy deployments.
2304
-
2305
- ```py
2306
- from transcrypto import sss
2307
-
2308
- # Generate parameters: at least 3 of 5 shares needed,
2309
- # coefficients & modulus are 128-bit primes
2310
- priv = sss.ShamirSharedSecretPrivate.New(minimum_shares=3, bit_length=128)
2311
- pub = sss.ShamirSharedSecretPublic.Copy(priv) # what you publish
2312
-
2313
- print(f'threshold : {pub.minimum}')
2314
- print(f'prime mod : {pub.modulus}')
2315
- print(f'poly coefficients: {priv.polynomial}') # keep these private!
2316
-
2317
- # Safe Issuing shares
2318
-
2319
- secret = b'xyz'
2320
- # Generate 5 shares, each has a copy of the encrypted secret
2321
- five_shares = priv.MakeDataShares(secret, 5)
2322
- for sh in five_shares:
2323
- print(sh)
2324
-
2325
- # Raw Issuing shares
2326
-
2327
- secret = 0xC0FFEE
2328
- # Generate an unlimited stream; here we take 5
2329
- five_shares = list(priv.RawShares(secret, max_shares=5))
2330
- for sh in five_shares:
2331
- print(f'share {sh.share_key} → {sh.share_value}')
2332
- ```
2333
-
2334
- A single share object looks like `sss.ShamirSharePrivate(minimum=3, modulus=..., share_key=42, share_value=123456789)`.
2335
-
2336
- ```py
2337
- # Safe Re-constructing the secret
2338
- secret = b'xyz'
2339
- five_shares = priv.MakeDataShares(secret, 5)
2340
- subset = five_shares[:3] # any 3 distinct shares
2341
- recovered = subset[0].RecoverData(subset) # each share has the encrypted data, so you ask it to join with the others
2342
- assert recovered == secret
2343
-
2344
- # Raw Re-constructing the secret
2345
- secret = 0xC0FFEE
2346
- five_shares = list(priv.RawShares(secret, max_shares=5))
2347
- subset = five_shares[:3] # any 3 distinct shares
2348
- recovered = pub.RawRecoverSecret(subset)
2349
- assert recovered == secret
2350
- ```
2351
-
2352
- If you supply fewer than minimum shares you get a `CryptoError`, unless you explicitly override:
2353
-
2354
- ```py
2355
- try:
2356
- pub.RawRecoverSecret(five_shares[:2]) # raises
2357
- except Exception as e:
2358
- print(e) # "unrecoverable secret …"
2359
-
2360
- # Force the interpolation even with 2 points (gives a wrong secret, of course)
2361
- print(pub.RawRecoverSecret(five_shares[:2], force_recover=True))
2362
-
2363
- # Checking that a share is genuine
2364
-
2365
- share = five_shares[0]
2366
- ok = priv.RawVerifyShare(secret, share) # ▶ True
2367
- tampered = sss.ShamirSharePrivate(
2368
- minimum=share.minimum,
2369
- modulus=share.modulus,
2370
- share_key=share.share_key,
2371
- share_value=(share.share_value + 1) % share.modulus)
2372
- print(priv.RawVerifyShare(secret, tampered)) # ▶ False
2373
- ```
2374
-
2375
- ## Appendix: Development Instructions
2376
-
2377
- ### Setup
2378
-
2379
- If you want to develop for this project, first install python 3.13 and [Poetry](https://python-poetry.org/docs/cli/), but to get the versions you will need, we suggest you do it like this (*Linux*):
2380
-
2381
- ```sh
2382
- sudo apt-get update
2383
- sudo apt-get upgrade
2384
- sudo apt-get install git python3 python3-pip pipx python3-dev python3-venv build-essential software-properties-common
2385
-
2386
- sudo add-apt-repository ppa:deadsnakes/ppa # install arbitrary python version
2387
- sudo apt-get update
2388
- sudo apt-get install python3.13
2389
-
2390
- sudo apt-get remove python3-poetry
2391
- python3.13 -m pipx ensurepath
2392
- # re-open terminal
2393
- pipx install poetry
2394
- poetry --version # should be >=2.1
2395
-
2396
- poetry config virtualenvs.in-project true # creates .venv inside project directory
2397
- poetry config pypi-token.pypi <TOKEN> # add your personal PyPI project token, if any
2398
- ```
2399
-
2400
- or this (*Mac*):
2401
-
2402
- ```sh
2403
- brew update
2404
- brew upgrade
2405
- brew cleanup -s
2406
-
2407
- brew install git python@3.13 # install arbitrary python version
2408
-
2409
- brew uninstall poetry
2410
- python3.13 -m pip install --user pipx
2411
- python3.13 -m pipx ensurepath
2412
- # re-open terminal
2413
- pipx install poetry
2414
- poetry --version # should be >=2.1
2415
-
2416
- poetry config virtualenvs.in-project true # creates .venv inside project directory
2417
- poetry config pypi-token.pypi <TOKEN> # add your personal PyPI project token, if any
2418
- ```
2419
-
2420
- Now install the project:
2421
-
2422
- ```sh
2423
- git clone https://github.com/balparda/transcrypto.git transcrypto
2424
- cd transcrypto
2425
-
2426
- poetry env use python3.13 # creates the venv
2427
- poetry install --sync # HONOR the project's poetry.lock file, uninstalls stray packages
2428
- poetry env info # no-op: just to check
2429
-
2430
- poetry run pytest -vvv
2431
- # or any command as:
2432
- poetry run <any-command>
2433
- ```
2434
-
2435
- To activate like a regular environment do:
2436
-
2437
- ```sh
2438
- poetry env activate
2439
- # will print activation command which you next execute, or you can do:
2440
- source .env/bin/activate # if .env is local to the project
2441
- source "$(poetry env info --path)/bin/activate" # for other paths
2442
-
2443
- pytest # or other commands
2444
-
2445
- deactivate
2446
- ```
2447
-
2448
- ### Updating Dependencies
2449
-
2450
- 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.
2451
-
2452
- To add a new dependency you should do:
2453
-
2454
- ```sh
2455
- poetry add "pkg>=1.2.3" # regenerates lock, updates env (adds dep to prod code)
2456
- poetry add -G dev "pkg>=1.2.3" # adds dep to dev code ("group" dev)
2457
- # also remember: "pkg@^1.2.3" = latest 1.* ; "pkg@~1.2.3" = latest 1.2.* ; "pkg@1.2.3" exact
2458
- ```
2459
-
2460
- If you manually added a dependency to `pyproject.toml` you should ***very carefully*** recreate the environment and files:
2461
-
2462
- ```sh
2463
- rm -rf .venv .poetry poetry.lock
2464
- poetry env use python3.13
2465
- poetry install
2466
- ```
2467
-
2468
- Remember to check your diffs before submitting (especially `poetry.lock`) to avoid surprises!
2469
-
2470
- When dependencies change, always regenerate `requirements.txt` by running:
2471
-
2472
- ```sh
2473
- poetry export --format requirements.txt --without-hashes --output requirements.txt
2474
- ```
2475
-
2476
- ### Creating a New Version
2477
-
2478
- ```sh
2479
- # bump the version!
2480
- poetry version minor # updates 1.6 to 1.7, for example
2481
- # or:
2482
- poetry version patch # updates 1.6 to 1.6.1
2483
- # or:
2484
- poetry version <version-number>
2485
- # (also updates `pyproject.toml` and `poetry.lock`)
2486
-
2487
- # publish to GIT, including a TAG
2488
- git commit -a -m "release version 1.0.2"
2489
- git tag 1.0.2
2490
- git push
2491
- git push --tags
2492
-
2493
- # prepare package for PyPI
2494
- poetry build
2495
- poetry publish
2496
- ```
2497
-
2498
- If you changed the CLI interface at all run:
2499
-
2500
- ```sh
2501
- poetry run transcrypto doc md > CLI.md
2502
- ./tools/inject_md_includes.py
2503
- ```
2504
-
2505
- You can find the 10 top slowest tests by running:
2506
-
2507
- ```sh
2508
- poetry run pytest -vvv -q --durations=10
2509
- ```
2510
-
2511
- You can search for flaky tests by running all tests 100 times:
2512
-
2513
- ```sh
2514
- poetry run pytest --flake-finder --flake-runs=100
2515
- ```