ikiprotect 1.0.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.
- ikiprotect-1.0.0/.github/workflows/python.yml +30 -0
- ikiprotect-1.0.0/.gitignore +13 -0
- ikiprotect-1.0.0/LICENSE +21 -0
- ikiprotect-1.0.0/PKG-INFO +312 -0
- ikiprotect-1.0.0/README.MD +282 -0
- ikiprotect-1.0.0/assets/image.png +0 -0
- ikiprotect-1.0.0/examples/example_usage.py +350 -0
- ikiprotect-1.0.0/pyproject.toml +41 -0
- ikiprotect-1.0.0/src/iki_protect/__init__.py +5 -0
- ikiprotect-1.0.0/src/iki_protect/__main__.py +4 -0
- ikiprotect-1.0.0/src/iki_protect/cli/__init__.py +1 -0
- ikiprotect-1.0.0/src/iki_protect/cli/app.py +47 -0
- ikiprotect-1.0.0/src/iki_protect/cli/commands/__init__.py +3 -0
- ikiprotect-1.0.0/src/iki_protect/cli/commands/decrypt.py +152 -0
- ikiprotect-1.0.0/src/iki_protect/cli/commands/detect.py +123 -0
- ikiprotect-1.0.0/src/iki_protect/cli/commands/encrypt.py +172 -0
- ikiprotect-1.0.0/src/iki_protect/cli/commands/hash_cmd.py +337 -0
- ikiprotect-1.0.0/src/iki_protect/cli/commands/jwt_cmd.py +135 -0
- ikiprotect-1.0.0/src/iki_protect/cli/commands/keys.py +127 -0
- ikiprotect-1.0.0/src/iki_protect/cli/commands/mask.py +54 -0
- ikiprotect-1.0.0/src/iki_protect/cli/commands/sign.py +56 -0
- ikiprotect-1.0.0/src/iki_protect/cli/facade.py +5 -0
- ikiprotect-1.0.0/src/iki_protect/content/__init__.py +1 -0
- ikiprotect-1.0.0/src/iki_protect/content/base.py +34 -0
- ikiprotect-1.0.0/src/iki_protect/content/config_file.py +46 -0
- ikiprotect-1.0.0/src/iki_protect/content/plain_text.py +10 -0
- ikiprotect-1.0.0/src/iki_protect/core/__init__.py +11 -0
- ikiprotect-1.0.0/src/iki_protect/core/config.py +62 -0
- ikiprotect-1.0.0/src/iki_protect/core/detectors/__init__.py +30 -0
- ikiprotect-1.0.0/src/iki_protect/core/detectors/base.py +41 -0
- ikiprotect-1.0.0/src/iki_protect/core/detectors/regex_detectors.py +233 -0
- ikiprotect-1.0.0/src/iki_protect/core/detectors/registry.py +108 -0
- ikiprotect-1.0.0/src/iki_protect/core/errors.py +26 -0
- ikiprotect-1.0.0/src/iki_protect/core/keys/__init__.py +5 -0
- ikiprotect-1.0.0/src/iki_protect/core/keys/kms.py +119 -0
- ikiprotect-1.0.0/src/iki_protect/core/keys/manager.py +198 -0
- ikiprotect-1.0.0/src/iki_protect/core/keys/sss.py +54 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/__init__.py +1 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/encryption/__init__.py +1 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/encryption/hpke.py +102 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/encryption/hybrid_kem.py +51 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/encryption/symmetric.py +419 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/hashing/__init__.py +1 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/hashing/envelope.py +154 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/hashing/fast_hash.py +101 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/hashing/kdf.py +25 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/hashing/slow_hash.py +119 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/jwt/__init__.py +1 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/jwt/jwt_strategy.py +242 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/masking/__init__.py +1 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/masking/redact.py +19 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/masking/tokenize.py +26 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/signing/__init__.py +1 -0
- ikiprotect-1.0.0/src/iki_protect/core/strategies/signing/asymmetric_sign.py +123 -0
- ikiprotect-1.0.0/src/iki_protect/facade.py +524 -0
- ikiprotect-1.0.0/src/iki_protect/version.py +1 -0
- ikiprotect-1.0.0/tests/__init__.py +1 -0
- ikiprotect-1.0.0/tests/conftest.py +9 -0
- ikiprotect-1.0.0/tests/security/test_cli_encryption.py +237 -0
- ikiprotect-1.0.0/tests/security/test_cli_hashing.py +200 -0
- ikiprotect-1.0.0/tests/security/test_cli_key_generation.py +65 -0
- ikiprotect-1.0.0/tests/security/test_hashing.py +34 -0
- ikiprotect-1.0.0/tests/security/test_jwt_and_signing.py +162 -0
- ikiprotect-1.0.0/tests/security/test_key_generation.py +44 -0
- ikiprotect-1.0.0/tests/security/test_symmetric_roundtrip.py +84 -0
- ikiprotect-1.0.0/tests/unit/test_detectors.py +124 -0
- ikiprotect-1.0.0/tests/unit/test_hpke_and_chunked.py +34 -0
- ikiprotect-1.0.0/tests/unit/test_kms_local.py +31 -0
- ikiprotect-1.0.0/tests/unit/test_sss_fallback.py +17 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Python package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: [3.11, 3.12, 3.14]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: |
|
|
23
|
+
python -m pip install --upgrade pip
|
|
24
|
+
pip install -e .[dev]
|
|
25
|
+
- name: Run ruff
|
|
26
|
+
run: python -m ruff check src tests
|
|
27
|
+
- name: Run mypy
|
|
28
|
+
run: python -m mypy src tests
|
|
29
|
+
- name: Run pytest
|
|
30
|
+
run: python -m pytest -q
|
ikiprotect-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Franz Monzales
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ikiprotect
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A portable Swiss Army knife for protecting a single piece of text or file: detect, mask, hash, encrypt, tokenize.
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: cli,encryption,pii,privacy,secrets
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Requires-Dist: argon2-cffi>=23.0
|
|
10
|
+
Requires-Dist: blake3>=0.3
|
|
11
|
+
Requires-Dist: cryptography>=41.0
|
|
12
|
+
Requires-Dist: hpke>=0.6
|
|
13
|
+
Requires-Dist: pyyaml>=6.0
|
|
14
|
+
Requires-Dist: rich>=13.0
|
|
15
|
+
Requires-Dist: typer>=0.12
|
|
16
|
+
Provides-Extra: age
|
|
17
|
+
Requires-Dist: pyrage>=1.1; extra == 'age'
|
|
18
|
+
Provides-Extra: faker
|
|
19
|
+
Requires-Dist: faker>=24.0; extra == 'faker'
|
|
20
|
+
Provides-Extra: keyring
|
|
21
|
+
Requires-Dist: keyring>=25.0; extra == 'keyring'
|
|
22
|
+
Provides-Extra: kms-aws
|
|
23
|
+
Requires-Dist: boto3>=1.34; extra == 'kms-aws'
|
|
24
|
+
Provides-Extra: office
|
|
25
|
+
Requires-Dist: pypdf>=4.0; extra == 'office'
|
|
26
|
+
Requires-Dist: python-docx>=1.1; extra == 'office'
|
|
27
|
+
Provides-Extra: pqc
|
|
28
|
+
Requires-Dist: pqcrypto>=0.3; extra == 'pqc'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# 🛡️ Iki-Protect
|
|
32
|
+
|
|
33
|
+
[](https://pypi.org/project/iki-protect/)
|
|
34
|
+
[](./LICENSE)
|
|
35
|
+
|
|
36
|
+
**One tool. Every data-protection primitive you'll ever need.**
|
|
37
|
+
Find PII and secrets, hide them, hash things, encrypt things, sign things, and issue JWTs — from a single CLI command or a single Python object. No servers, no accounts, no external services required.
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install ikiprotect
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from iki_protect import IkiProtect
|
|
47
|
+
protect = IkiProtect()
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
That's it — everything below is one method call or one CLI command away.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🚀 Why people reach for this
|
|
55
|
+
|
|
56
|
+
- **🔍 Finds what shouldn't be there** — emails, credit cards, IBANs, SSNs, IP addresses, and 12 different flavors of leaked API key/secret, in any text or file.
|
|
57
|
+
- **🙈 Hides it your way** — full redaction, partial masking (`j***e@example.com`), or deterministic tokenization that stays consistent every time.
|
|
58
|
+
- **🔐 Locks it down** — 6 modern AEAD ciphers, layered/chained encryption, envelope (DEK/KEK) encryption with key rotation, chunked encryption for huge files, and public-key encryption (Hybrid KEM / HPKE).
|
|
59
|
+
- **#️⃣ Hashes anything** — fast digests for checksums, keyed HMACs for integrity, and slow Argon2/PBKDF2 KDFs for passwords — done right by default.
|
|
60
|
+
- **✍️ Proves authenticity** — Ed25519, RSA-PSS, and ECDSA signatures; full JWT encode/decode/verify across 11 algorithms.
|
|
61
|
+
- **🔑 Manages your keys** — generate keypairs, derive keys from passphrases, resolve keys from env vars/files, split a secret into shares and recombine it later.
|
|
62
|
+
- **🖥️ CLI or 🐍 Python — your choice** — every capability works as a terminal command _and_ as a plain Python method call through the `IkiProtect` facade.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 🧩 The complete feature set
|
|
67
|
+
|
|
68
|
+
### 🔍 Find sensitive data — `detect`
|
|
69
|
+
|
|
70
|
+
Scans a string, file, or an entire folder and tells you exactly what it found and where.
|
|
71
|
+
|
|
72
|
+
| Category | What it catches |
|
|
73
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
74
|
+
| **PII** | Emails, phone numbers, US Social Security numbers, IPv4 addresses, credit card numbers, IBANs |
|
|
75
|
+
| **Secrets** | AWS keys, GCP keys, GitHub tokens (classic + fine-grained), GitLab tokens, Slack tokens, Stripe keys, OpenAI keys, Twilio keys, NPM tokens, PEM private-key blocks, JWTs |
|
|
76
|
+
|
|
77
|
+
- Group findings with easy shorthands: `--types pii`, `--types secrets`, or both.
|
|
78
|
+
- Overlapping matches are automatically de-duplicated so you don't get double hits on the same text.
|
|
79
|
+
- Scan a whole repo with `--recursive`, respect a `.ikiprotectignore` file, and fail your CI pipeline with `--fail-on` if anything's found.
|
|
80
|
+
- Extendable with your own detectors via a plugin system.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
ikiprotect detect notes.txt --format json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
findings = protect.detect("email me at a@b.com", types="pii,secrets")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 🙈 Hide sensitive data — `mask`
|
|
91
|
+
|
|
92
|
+
Once something's found, replace it in place or write a cleaned copy.
|
|
93
|
+
|
|
94
|
+
| Strategy | Example | Best for |
|
|
95
|
+
| ------------ | ----------------------------------------- | ------------------------------------------------------------------- |
|
|
96
|
+
| **redact** | `john@example.com` → `[REDACTED]` | Logs, tickets, anything shared externally |
|
|
97
|
+
| **partial** | `john@example.com` → `j****************m` | Support screenshots, debugging |
|
|
98
|
+
| **tokenize** | `john@example.com` → `V-ntuFR9wvlZhRp-` | Analytics/pseudonymization — same input always gives the same token |
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
ikiprotect mask notes.txt --types pii,secrets --strategy partial
|
|
102
|
+
ikiprotect mask foo.txt --strategy tokenize --key-ref file:./token_key.bin
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### #️⃣ Hash anything — `hash`
|
|
106
|
+
|
|
107
|
+
One command covers everything from "checksum a file" to "store a password correctly."
|
|
108
|
+
|
|
109
|
+
- **General-purpose digests:** SHA-256, SHA-512, SHA3-256, SHA3-512, BLAKE2b, BLAKE2s, BLAKE3 (plus keyed and extendable-output BLAKE3 modes), CRC32
|
|
110
|
+
- **Keyed MACs (integrity/authenticity):** HMAC-SHA256, HMAC-SHA512
|
|
111
|
+
- **Password-grade KDFs (slow & salted on purpose):** Argon2id, Argon2i, Argon2d, PBKDF2-SHA256, PBKDF2-SHA512 — with Argon2's cost parameters tunable via environment variables for production hardening
|
|
112
|
+
- Verifying a password hash auto-detects which algorithm produced it, so you don't have to remember or store that separately
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
echo -n "correct horse battery staple" | ikiprotect hash --algo argon2id
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
pw_hash = protect.hash_password("correct horse battery staple")
|
|
120
|
+
protect.verify_password(pw_hash, "correct horse battery staple")
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 🔐 Encrypt anything — `encrypt` / `decrypt`
|
|
124
|
+
|
|
125
|
+
From a quick one-off secret to a full key-management pipeline.
|
|
126
|
+
|
|
127
|
+
- **6 authenticated ciphers:** AES-256-GCM, AES-192-GCM, AES-128-GCM, AES-256-GCM-SIV, ChaCha20-Poly1305, XChaCha20-Poly1305
|
|
128
|
+
- **Self-describing ciphertext** — the algorithm and nonce length travel with the ciphertext, so `decrypt` just works without extra bookkeeping
|
|
129
|
+
- **Layered encryption** — chain multiple algorithms together for defense-in-depth
|
|
130
|
+
- **Envelope encryption (DEK/KEK)** — generate a fresh data key per message, wrap it under a master key, and **rotate the master key later without re-encrypting the payload**
|
|
131
|
+
- **Chunked/streaming encryption** — handles multi-gigabyte files in fixed-size, independently-authenticated chunks
|
|
132
|
+
- **Public-key encryption** — Hybrid KEM (X25519) and a minimal HPKE-compatible mode, so you can encrypt _to someone's public key_ with no shared secret needed
|
|
133
|
+
- **Built-in KMS simulator** — generate and unwrap data keys the same way you would with AWS KMS, entirely offline (with a placeholder ready for a real AWS KMS integration)
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
ikiprotect encrypt secret.txt --key-ref env:MY_KEY -o secret.enc
|
|
137
|
+
ikiprotect encrypt secret.txt --envelope --key-ref env:MY_KEK -o secret.enc
|
|
138
|
+
ikiprotect encrypt rewrap secret.enc --old-key-ref env:OLD_KEK --new-key-ref env:NEW_KEK -o secret.rewrapped
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
ciphertext = protect.encrypt(b"secret data", key)
|
|
143
|
+
envelope = protect.envelope_encrypt(kek, b"secret data", ["aes-256-gcm"])
|
|
144
|
+
encap, shared_key = protect.hybrid_encapsulate(recipient_public_key)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### ✍️ Prove authenticity — `sign` / `verify-signature`, `jwt`
|
|
148
|
+
|
|
149
|
+
- **Digital signatures:** Ed25519, RSA-PSS, ECDSA (P-256, P-384, P-521) — sign a release artifact, verify it came from you
|
|
150
|
+
- **JWTs:** encode, decode, and verify across HS256/384/512, RS256/384/512, PS256/384/512, ES256/384/512, and EdDSA, with issuer/audience/leeway checks built in
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
ikiprotect generate-keypair --algo ed25519 -o ./keys
|
|
154
|
+
ikiprotect sign release.tar.gz --algo ed25519 --private-key ./keys/ed25519_private.key -o release.sig
|
|
155
|
+
ikiprotect jwt encode claims.json --algo HS256 --key-ref env:JWT_SECRET
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
priv, pub = protect.generate_keypair("ed25519")
|
|
160
|
+
signature = protect.sign(b"message", priv)
|
|
161
|
+
token = protect.jwt_encode({"sub": "1234"}, b"hs256-secret", "HS256")
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 🔑 Manage your keys
|
|
165
|
+
|
|
166
|
+
- Generate keypairs (Ed25519, RSA, ECDSA P-256/384/521) with one command
|
|
167
|
+
- Derive an encryption key from a human passphrase (SHA-256, PBKDF2, or Argon2id)
|
|
168
|
+
- Resolve keys from `env:VAR_NAME`, `file:path`, or a raw path — with file-permission checks so you don't accidentally use a world-readable key
|
|
169
|
+
- **Split a secret into N shares with a K-of-N recovery threshold**, then recombine them later (true Shamir secret sharing, or an XOR fallback)
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
ikiprotect keys split secret.bin --n 5 --k 3 -o shares.json
|
|
173
|
+
ikiprotect keys combine shares.json -o recovered.bin
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
shares = protect.split_secret(secret_bytes, n=5, k=3)
|
|
178
|
+
recovered = protect.combine_shares(shares)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### 📄 Works with structured files, too
|
|
182
|
+
|
|
183
|
+
Beyond plain text/log files, Iki-Protect can target a single field inside one JSON or YAML config file by dot-path (e.g. `database.password`) instead of scanning/replacing the whole document.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 🖥️ CLI or 🐍 Python — everything, either way
|
|
188
|
+
|
|
189
|
+
Every feature above works two ways:
|
|
190
|
+
|
|
191
|
+
1. **From the terminal**, via the `ikiprotect` command (see the command table and examples above).
|
|
192
|
+
2. **From Python**, via one object: `IkiProtect` from `iki_protect.facade`. No need to know which internal class implements `"aes-256-gcm"` or `"argon2id"` — just call the method.
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from iki_protect.facade import IkiProtect
|
|
196
|
+
|
|
197
|
+
protect = IkiProtect()
|
|
198
|
+
|
|
199
|
+
# Detect & mask
|
|
200
|
+
findings = protect.detect("email me at a@b.com", types="pii,secrets")
|
|
201
|
+
masked = protect.mask("email me at a@b.com")
|
|
202
|
+
|
|
203
|
+
# Hashing
|
|
204
|
+
digest = protect.hash(b"data", algorithm="sha256")
|
|
205
|
+
pw_hash = protect.hash_password("correct horse battery staple")
|
|
206
|
+
protect.verify_password(pw_hash, "correct horse battery staple")
|
|
207
|
+
|
|
208
|
+
# Encryption
|
|
209
|
+
key = protect.derive_passphrase_key("my passphrase")
|
|
210
|
+
ciphertext = protect.encrypt(b"secret data", key)
|
|
211
|
+
plaintext = protect.decrypt(ciphertext, key)
|
|
212
|
+
|
|
213
|
+
# Keys, signing, JWT
|
|
214
|
+
priv, pub = protect.generate_keypair("ed25519")
|
|
215
|
+
signature = protect.sign(b"message", priv)
|
|
216
|
+
protect.verify_signature(signature, b"message", pub)
|
|
217
|
+
|
|
218
|
+
token = protect.jwt_encode({"sub": "1234"}, b"hs256-secret", "HS256")
|
|
219
|
+
claims = protect.jwt_verify(token, b"hs256-secret", "HS256")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Want the underlying strategy classes instead of the facade? `iki_protect.api` re-exports every building block flat, for `from iki_protect.api import Aes256GcmStrategy` style imports. See `examples/example_usage.py` for a full end-to-end walkthrough of every single feature in one runnable script.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 📦 Project layout
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
src/iki_protect/
|
|
230
|
+
├── cli/ # Typer-based CLI commands (detect, mask, hash, encrypt, decrypt, sign, jwt, keys)
|
|
231
|
+
├── content/ # Plain text, JSON, YAML readers (one file at a time)
|
|
232
|
+
├── core/
|
|
233
|
+
│ ├── detectors/ # Regex + checksum-based PII/secret detectors, plugin registry
|
|
234
|
+
│ ├── keys/ # Key resolution, generation (Ed25519/RSA/ECDSA), passphrase derivation, KMS, secret sharing
|
|
235
|
+
│ └── strategies/
|
|
236
|
+
│ ├── masking/ # Redact / partial-mask / tokenize transforms
|
|
237
|
+
│ ├── hashing/ # Fast hashes, HKDF, Argon2/PBKDF2 slow hashes
|
|
238
|
+
│ ├── encryption/ # AEAD ciphers, layered/envelope/chunked encryption, Hybrid KEM, HPKE
|
|
239
|
+
│ ├── signing/ # Ed25519 / RSA-PSS / ECDSA
|
|
240
|
+
│ └── jwt/ # JWT encode/decode/verify
|
|
241
|
+
├── api.py # Flat re-export of every public symbol
|
|
242
|
+
└── facade.py # `IkiProtect` — one object, name-driven method for every feature
|
|
243
|
+
examples/example_usage.py # Runnable end-to-end demo of the whole feature set
|
|
244
|
+
tests/ # Unit + security test suites
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## 🛠️ Installation
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
pip install ikiprotect
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Requires Python ≥ 3.9. Core dependencies (installed automatically): `typer`, `rich`, `cryptography`, `blake3`, `argon2-cffi`, `PyYAML`.
|
|
254
|
+
|
|
255
|
+
Working on the source directly instead of installing from PyPI:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
git clone <this-repo>
|
|
259
|
+
cd iki-protect
|
|
260
|
+
pip install -e ".[dev]"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## ⚡ Quick examples
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# Detect and mask PII/secrets in a file
|
|
267
|
+
ikiprotect detect notes.txt --format json
|
|
268
|
+
ikiprotect mask notes.txt --types pii,secrets --strategy partial
|
|
269
|
+
|
|
270
|
+
# Hash a value with Argon2id (password-grade)
|
|
271
|
+
echo -n "correct horse battery staple" | ikiprotect hash --algo argon2id
|
|
272
|
+
|
|
273
|
+
# Encrypt/decrypt a file (key-ref based)
|
|
274
|
+
ikiprotect encrypt secret.txt --key-ref env:MY_KEY -o secret.enc
|
|
275
|
+
ikiprotect decrypt secret.enc --key-ref env:MY_KEY -o secret.txt
|
|
276
|
+
|
|
277
|
+
# Envelope mode (DEK/KEK): generate a random DEK, wrap under KEK
|
|
278
|
+
ikiprotect encrypt secret.txt --envelope --key-ref env:MY_KEK -o secret.enc
|
|
279
|
+
# Rotate the KEK that wraps the DEK without re-encrypting payload
|
|
280
|
+
ikiprotect encrypt rewrap secret.enc --old-key-ref env:OLD_KEK --new-key-ref env:NEW_KEK -o secret.rewrapped
|
|
281
|
+
|
|
282
|
+
# Recursive scan with CI gate
|
|
283
|
+
ikiprotect detect . --recursive --format ndjson --fail-on 1
|
|
284
|
+
|
|
285
|
+
# Tokenize values deterministically (requires keyed strategy)
|
|
286
|
+
ikiprotect mask foo.txt --strategy tokenize --key-ref file:./token_key.bin
|
|
287
|
+
|
|
288
|
+
# Secret sharing (split/combine)
|
|
289
|
+
ikiprotect keys split secret.bin --n 5 --k 3 -o shares.json
|
|
290
|
+
ikiprotect keys combine shares.json -o recovered.bin
|
|
291
|
+
|
|
292
|
+
# Sign and verify a release artifact
|
|
293
|
+
ikiprotect generate-keypair --algo ed25519 -o ./keys
|
|
294
|
+
ikiprotect sign release.tar.gz --algo ed25519 --private-key ./keys/ed25519_private.key -o release.sig
|
|
295
|
+
ikiprotect verify-signature release.tar.gz release.sig --algo ed25519 --public-key ./keys/ed25519_public.key
|
|
296
|
+
|
|
297
|
+
# JWT
|
|
298
|
+
ikiprotect jwt encode claims.json --algo HS256 --key-ref env:JWT_SECRET
|
|
299
|
+
ikiprotect jwt verify "<token>" --algo HS256 --key-ref env:JWT_SECRET
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
> **Before using `--passphrase`/`sha256` defaults for anything real, read `AUDIT.md` — item C1/C2 covers weak defaults you should override (`--kdf argon2id` and a real `--salt`).**
|
|
303
|
+
|
|
304
|
+
## 🧠 Design principles
|
|
305
|
+
|
|
306
|
+
- Every command operates on **one** value/file at a time — this is not a dataset/batch tool.
|
|
307
|
+
- Ciphertext is **self-describing**: a version byte + implied nonce length means `decrypt` never needs the nonce or algorithm re-supplied separately.
|
|
308
|
+
- Two distinct key-loading paths exist on purpose: `KeyManager.resolve()` normalizes any input to a 32-byte key; `KeyManager.load_raw()` returns exact bytes for algorithms that need precise key material.
|
|
309
|
+
|
|
310
|
+
## License
|
|
311
|
+
|
|
312
|
+
MIT
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# 🛡️ Iki-Protect
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/iki-protect/)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
**One tool. Every data-protection primitive you'll ever need.**
|
|
7
|
+
Find PII and secrets, hide them, hash things, encrypt things, sign things, and issue JWTs — from a single CLI command or a single Python object. No servers, no accounts, no external services required.
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install ikiprotect
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from iki_protect import IkiProtect
|
|
17
|
+
protect = IkiProtect()
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
That's it — everything below is one method call or one CLI command away.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🚀 Why people reach for this
|
|
25
|
+
|
|
26
|
+
- **🔍 Finds what shouldn't be there** — emails, credit cards, IBANs, SSNs, IP addresses, and 12 different flavors of leaked API key/secret, in any text or file.
|
|
27
|
+
- **🙈 Hides it your way** — full redaction, partial masking (`j***e@example.com`), or deterministic tokenization that stays consistent every time.
|
|
28
|
+
- **🔐 Locks it down** — 6 modern AEAD ciphers, layered/chained encryption, envelope (DEK/KEK) encryption with key rotation, chunked encryption for huge files, and public-key encryption (Hybrid KEM / HPKE).
|
|
29
|
+
- **#️⃣ Hashes anything** — fast digests for checksums, keyed HMACs for integrity, and slow Argon2/PBKDF2 KDFs for passwords — done right by default.
|
|
30
|
+
- **✍️ Proves authenticity** — Ed25519, RSA-PSS, and ECDSA signatures; full JWT encode/decode/verify across 11 algorithms.
|
|
31
|
+
- **🔑 Manages your keys** — generate keypairs, derive keys from passphrases, resolve keys from env vars/files, split a secret into shares and recombine it later.
|
|
32
|
+
- **🖥️ CLI or 🐍 Python — your choice** — every capability works as a terminal command _and_ as a plain Python method call through the `IkiProtect` facade.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 🧩 The complete feature set
|
|
37
|
+
|
|
38
|
+
### 🔍 Find sensitive data — `detect`
|
|
39
|
+
|
|
40
|
+
Scans a string, file, or an entire folder and tells you exactly what it found and where.
|
|
41
|
+
|
|
42
|
+
| Category | What it catches |
|
|
43
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
44
|
+
| **PII** | Emails, phone numbers, US Social Security numbers, IPv4 addresses, credit card numbers, IBANs |
|
|
45
|
+
| **Secrets** | AWS keys, GCP keys, GitHub tokens (classic + fine-grained), GitLab tokens, Slack tokens, Stripe keys, OpenAI keys, Twilio keys, NPM tokens, PEM private-key blocks, JWTs |
|
|
46
|
+
|
|
47
|
+
- Group findings with easy shorthands: `--types pii`, `--types secrets`, or both.
|
|
48
|
+
- Overlapping matches are automatically de-duplicated so you don't get double hits on the same text.
|
|
49
|
+
- Scan a whole repo with `--recursive`, respect a `.ikiprotectignore` file, and fail your CI pipeline with `--fail-on` if anything's found.
|
|
50
|
+
- Extendable with your own detectors via a plugin system.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
ikiprotect detect notes.txt --format json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
findings = protect.detect("email me at a@b.com", types="pii,secrets")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 🙈 Hide sensitive data — `mask`
|
|
61
|
+
|
|
62
|
+
Once something's found, replace it in place or write a cleaned copy.
|
|
63
|
+
|
|
64
|
+
| Strategy | Example | Best for |
|
|
65
|
+
| ------------ | ----------------------------------------- | ------------------------------------------------------------------- |
|
|
66
|
+
| **redact** | `john@example.com` → `[REDACTED]` | Logs, tickets, anything shared externally |
|
|
67
|
+
| **partial** | `john@example.com` → `j****************m` | Support screenshots, debugging |
|
|
68
|
+
| **tokenize** | `john@example.com` → `V-ntuFR9wvlZhRp-` | Analytics/pseudonymization — same input always gives the same token |
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
ikiprotect mask notes.txt --types pii,secrets --strategy partial
|
|
72
|
+
ikiprotect mask foo.txt --strategy tokenize --key-ref file:./token_key.bin
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### #️⃣ Hash anything — `hash`
|
|
76
|
+
|
|
77
|
+
One command covers everything from "checksum a file" to "store a password correctly."
|
|
78
|
+
|
|
79
|
+
- **General-purpose digests:** SHA-256, SHA-512, SHA3-256, SHA3-512, BLAKE2b, BLAKE2s, BLAKE3 (plus keyed and extendable-output BLAKE3 modes), CRC32
|
|
80
|
+
- **Keyed MACs (integrity/authenticity):** HMAC-SHA256, HMAC-SHA512
|
|
81
|
+
- **Password-grade KDFs (slow & salted on purpose):** Argon2id, Argon2i, Argon2d, PBKDF2-SHA256, PBKDF2-SHA512 — with Argon2's cost parameters tunable via environment variables for production hardening
|
|
82
|
+
- Verifying a password hash auto-detects which algorithm produced it, so you don't have to remember or store that separately
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
echo -n "correct horse battery staple" | ikiprotect hash --algo argon2id
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
pw_hash = protect.hash_password("correct horse battery staple")
|
|
90
|
+
protect.verify_password(pw_hash, "correct horse battery staple")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 🔐 Encrypt anything — `encrypt` / `decrypt`
|
|
94
|
+
|
|
95
|
+
From a quick one-off secret to a full key-management pipeline.
|
|
96
|
+
|
|
97
|
+
- **6 authenticated ciphers:** AES-256-GCM, AES-192-GCM, AES-128-GCM, AES-256-GCM-SIV, ChaCha20-Poly1305, XChaCha20-Poly1305
|
|
98
|
+
- **Self-describing ciphertext** — the algorithm and nonce length travel with the ciphertext, so `decrypt` just works without extra bookkeeping
|
|
99
|
+
- **Layered encryption** — chain multiple algorithms together for defense-in-depth
|
|
100
|
+
- **Envelope encryption (DEK/KEK)** — generate a fresh data key per message, wrap it under a master key, and **rotate the master key later without re-encrypting the payload**
|
|
101
|
+
- **Chunked/streaming encryption** — handles multi-gigabyte files in fixed-size, independently-authenticated chunks
|
|
102
|
+
- **Public-key encryption** — Hybrid KEM (X25519) and a minimal HPKE-compatible mode, so you can encrypt _to someone's public key_ with no shared secret needed
|
|
103
|
+
- **Built-in KMS simulator** — generate and unwrap data keys the same way you would with AWS KMS, entirely offline (with a placeholder ready for a real AWS KMS integration)
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
ikiprotect encrypt secret.txt --key-ref env:MY_KEY -o secret.enc
|
|
107
|
+
ikiprotect encrypt secret.txt --envelope --key-ref env:MY_KEK -o secret.enc
|
|
108
|
+
ikiprotect encrypt rewrap secret.enc --old-key-ref env:OLD_KEK --new-key-ref env:NEW_KEK -o secret.rewrapped
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
ciphertext = protect.encrypt(b"secret data", key)
|
|
113
|
+
envelope = protect.envelope_encrypt(kek, b"secret data", ["aes-256-gcm"])
|
|
114
|
+
encap, shared_key = protect.hybrid_encapsulate(recipient_public_key)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### ✍️ Prove authenticity — `sign` / `verify-signature`, `jwt`
|
|
118
|
+
|
|
119
|
+
- **Digital signatures:** Ed25519, RSA-PSS, ECDSA (P-256, P-384, P-521) — sign a release artifact, verify it came from you
|
|
120
|
+
- **JWTs:** encode, decode, and verify across HS256/384/512, RS256/384/512, PS256/384/512, ES256/384/512, and EdDSA, with issuer/audience/leeway checks built in
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
ikiprotect generate-keypair --algo ed25519 -o ./keys
|
|
124
|
+
ikiprotect sign release.tar.gz --algo ed25519 --private-key ./keys/ed25519_private.key -o release.sig
|
|
125
|
+
ikiprotect jwt encode claims.json --algo HS256 --key-ref env:JWT_SECRET
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
priv, pub = protect.generate_keypair("ed25519")
|
|
130
|
+
signature = protect.sign(b"message", priv)
|
|
131
|
+
token = protect.jwt_encode({"sub": "1234"}, b"hs256-secret", "HS256")
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 🔑 Manage your keys
|
|
135
|
+
|
|
136
|
+
- Generate keypairs (Ed25519, RSA, ECDSA P-256/384/521) with one command
|
|
137
|
+
- Derive an encryption key from a human passphrase (SHA-256, PBKDF2, or Argon2id)
|
|
138
|
+
- Resolve keys from `env:VAR_NAME`, `file:path`, or a raw path — with file-permission checks so you don't accidentally use a world-readable key
|
|
139
|
+
- **Split a secret into N shares with a K-of-N recovery threshold**, then recombine them later (true Shamir secret sharing, or an XOR fallback)
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
ikiprotect keys split secret.bin --n 5 --k 3 -o shares.json
|
|
143
|
+
ikiprotect keys combine shares.json -o recovered.bin
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
shares = protect.split_secret(secret_bytes, n=5, k=3)
|
|
148
|
+
recovered = protect.combine_shares(shares)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 📄 Works with structured files, too
|
|
152
|
+
|
|
153
|
+
Beyond plain text/log files, Iki-Protect can target a single field inside one JSON or YAML config file by dot-path (e.g. `database.password`) instead of scanning/replacing the whole document.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 🖥️ CLI or 🐍 Python — everything, either way
|
|
158
|
+
|
|
159
|
+
Every feature above works two ways:
|
|
160
|
+
|
|
161
|
+
1. **From the terminal**, via the `ikiprotect` command (see the command table and examples above).
|
|
162
|
+
2. **From Python**, via one object: `IkiProtect` from `iki_protect.facade`. No need to know which internal class implements `"aes-256-gcm"` or `"argon2id"` — just call the method.
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
from iki_protect.facade import IkiProtect
|
|
166
|
+
|
|
167
|
+
protect = IkiProtect()
|
|
168
|
+
|
|
169
|
+
# Detect & mask
|
|
170
|
+
findings = protect.detect("email me at a@b.com", types="pii,secrets")
|
|
171
|
+
masked = protect.mask("email me at a@b.com")
|
|
172
|
+
|
|
173
|
+
# Hashing
|
|
174
|
+
digest = protect.hash(b"data", algorithm="sha256")
|
|
175
|
+
pw_hash = protect.hash_password("correct horse battery staple")
|
|
176
|
+
protect.verify_password(pw_hash, "correct horse battery staple")
|
|
177
|
+
|
|
178
|
+
# Encryption
|
|
179
|
+
key = protect.derive_passphrase_key("my passphrase")
|
|
180
|
+
ciphertext = protect.encrypt(b"secret data", key)
|
|
181
|
+
plaintext = protect.decrypt(ciphertext, key)
|
|
182
|
+
|
|
183
|
+
# Keys, signing, JWT
|
|
184
|
+
priv, pub = protect.generate_keypair("ed25519")
|
|
185
|
+
signature = protect.sign(b"message", priv)
|
|
186
|
+
protect.verify_signature(signature, b"message", pub)
|
|
187
|
+
|
|
188
|
+
token = protect.jwt_encode({"sub": "1234"}, b"hs256-secret", "HS256")
|
|
189
|
+
claims = protect.jwt_verify(token, b"hs256-secret", "HS256")
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Want the underlying strategy classes instead of the facade? `iki_protect.api` re-exports every building block flat, for `from iki_protect.api import Aes256GcmStrategy` style imports. See `examples/example_usage.py` for a full end-to-end walkthrough of every single feature in one runnable script.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 📦 Project layout
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
src/iki_protect/
|
|
200
|
+
├── cli/ # Typer-based CLI commands (detect, mask, hash, encrypt, decrypt, sign, jwt, keys)
|
|
201
|
+
├── content/ # Plain text, JSON, YAML readers (one file at a time)
|
|
202
|
+
├── core/
|
|
203
|
+
│ ├── detectors/ # Regex + checksum-based PII/secret detectors, plugin registry
|
|
204
|
+
│ ├── keys/ # Key resolution, generation (Ed25519/RSA/ECDSA), passphrase derivation, KMS, secret sharing
|
|
205
|
+
│ └── strategies/
|
|
206
|
+
│ ├── masking/ # Redact / partial-mask / tokenize transforms
|
|
207
|
+
│ ├── hashing/ # Fast hashes, HKDF, Argon2/PBKDF2 slow hashes
|
|
208
|
+
│ ├── encryption/ # AEAD ciphers, layered/envelope/chunked encryption, Hybrid KEM, HPKE
|
|
209
|
+
│ ├── signing/ # Ed25519 / RSA-PSS / ECDSA
|
|
210
|
+
│ └── jwt/ # JWT encode/decode/verify
|
|
211
|
+
├── api.py # Flat re-export of every public symbol
|
|
212
|
+
└── facade.py # `IkiProtect` — one object, name-driven method for every feature
|
|
213
|
+
examples/example_usage.py # Runnable end-to-end demo of the whole feature set
|
|
214
|
+
tests/ # Unit + security test suites
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## 🛠️ Installation
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
pip install ikiprotect
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Requires Python ≥ 3.9. Core dependencies (installed automatically): `typer`, `rich`, `cryptography`, `blake3`, `argon2-cffi`, `PyYAML`.
|
|
224
|
+
|
|
225
|
+
Working on the source directly instead of installing from PyPI:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
git clone <this-repo>
|
|
229
|
+
cd iki-protect
|
|
230
|
+
pip install -e ".[dev]"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## ⚡ Quick examples
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Detect and mask PII/secrets in a file
|
|
237
|
+
ikiprotect detect notes.txt --format json
|
|
238
|
+
ikiprotect mask notes.txt --types pii,secrets --strategy partial
|
|
239
|
+
|
|
240
|
+
# Hash a value with Argon2id (password-grade)
|
|
241
|
+
echo -n "correct horse battery staple" | ikiprotect hash --algo argon2id
|
|
242
|
+
|
|
243
|
+
# Encrypt/decrypt a file (key-ref based)
|
|
244
|
+
ikiprotect encrypt secret.txt --key-ref env:MY_KEY -o secret.enc
|
|
245
|
+
ikiprotect decrypt secret.enc --key-ref env:MY_KEY -o secret.txt
|
|
246
|
+
|
|
247
|
+
# Envelope mode (DEK/KEK): generate a random DEK, wrap under KEK
|
|
248
|
+
ikiprotect encrypt secret.txt --envelope --key-ref env:MY_KEK -o secret.enc
|
|
249
|
+
# Rotate the KEK that wraps the DEK without re-encrypting payload
|
|
250
|
+
ikiprotect encrypt rewrap secret.enc --old-key-ref env:OLD_KEK --new-key-ref env:NEW_KEK -o secret.rewrapped
|
|
251
|
+
|
|
252
|
+
# Recursive scan with CI gate
|
|
253
|
+
ikiprotect detect . --recursive --format ndjson --fail-on 1
|
|
254
|
+
|
|
255
|
+
# Tokenize values deterministically (requires keyed strategy)
|
|
256
|
+
ikiprotect mask foo.txt --strategy tokenize --key-ref file:./token_key.bin
|
|
257
|
+
|
|
258
|
+
# Secret sharing (split/combine)
|
|
259
|
+
ikiprotect keys split secret.bin --n 5 --k 3 -o shares.json
|
|
260
|
+
ikiprotect keys combine shares.json -o recovered.bin
|
|
261
|
+
|
|
262
|
+
# Sign and verify a release artifact
|
|
263
|
+
ikiprotect generate-keypair --algo ed25519 -o ./keys
|
|
264
|
+
ikiprotect sign release.tar.gz --algo ed25519 --private-key ./keys/ed25519_private.key -o release.sig
|
|
265
|
+
ikiprotect verify-signature release.tar.gz release.sig --algo ed25519 --public-key ./keys/ed25519_public.key
|
|
266
|
+
|
|
267
|
+
# JWT
|
|
268
|
+
ikiprotect jwt encode claims.json --algo HS256 --key-ref env:JWT_SECRET
|
|
269
|
+
ikiprotect jwt verify "<token>" --algo HS256 --key-ref env:JWT_SECRET
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
> **Before using `--passphrase`/`sha256` defaults for anything real, read `AUDIT.md` — item C1/C2 covers weak defaults you should override (`--kdf argon2id` and a real `--salt`).**
|
|
273
|
+
|
|
274
|
+
## 🧠 Design principles
|
|
275
|
+
|
|
276
|
+
- Every command operates on **one** value/file at a time — this is not a dataset/batch tool.
|
|
277
|
+
- Ciphertext is **self-describing**: a version byte + implied nonce length means `decrypt` never needs the nonce or algorithm re-supplied separately.
|
|
278
|
+
- Two distinct key-loading paths exist on purpose: `KeyManager.resolve()` normalizes any input to a 32-byte key; `KeyManager.load_raw()` returns exact bytes for algorithms that need precise key material.
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
MIT
|
|
Binary file
|