Metadata-Version: 2.4
Name: ikiprotect
Version: 1.0.1
Summary: A portable Swiss Army knife for protecting a single piece of text or file: detect, mask, hash, encrypt, tokenize.
License: Apache-2.0
License-File: LICENSE
Keywords: cli,encryption,pii,privacy,secrets
Requires-Python: >=3.9
Requires-Dist: argon2-cffi>=23.0
Requires-Dist: blake3>=0.3
Requires-Dist: cryptography>=41.0
Requires-Dist: hpke<0.4,>=0.3
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Requires-Dist: typer>=0.12
Provides-Extra: age
Requires-Dist: pyrage>=1.1; extra == 'age'
Provides-Extra: faker
Requires-Dist: faker>=24.0; extra == 'faker'
Provides-Extra: keyring
Requires-Dist: keyring>=25.0; extra == 'keyring'
Provides-Extra: kms-aws
Requires-Dist: boto3>=1.34; extra == 'kms-aws'
Provides-Extra: office
Requires-Dist: pypdf>=4.0; extra == 'office'
Requires-Dist: python-docx>=1.1; extra == 'office'
Provides-Extra: pqc
Requires-Dist: pqcrypto>=0.3; extra == 'pqc'
Description-Content-Type: text/markdown

# 🛡️ Iki-Protect

[![PyPI version](https://img.shields.io/pypi/v/ikiprotect.svg)](https://pypi.org/project/ikiprotect/)
[![License: Apache-2.0](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)

**One tool. Every data-protection primitive you'll ever need.**
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.

![Image_Cover](assets/image.png)

```bash
pip install ikiprotect
```

```python
from iki_protect import IkiProtect
protect = IkiProtect()
```

That's it — everything below is one method call or one CLI command away.

---

## 🚀 Why people reach for this

- **🔍 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.
- **🙈 Hides it your way** — full redaction, partial masking (`j***e@example.com`), or deterministic tokenization that stays consistent every time.
- **🔐 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).
- **#️⃣ Hashes anything** — fast digests for checksums, keyed HMACs for integrity, and slow Argon2/PBKDF2 KDFs for passwords — done right by default.
- **✍️ Proves authenticity** — Ed25519, RSA-PSS, and ECDSA signatures; full JWT encode/decode/verify across 11 algorithms.
- **🔑 Manages your keys** — generate keypairs, derive keys from passphrases, resolve keys from env vars/files, split a secret into shares and recombine it later.
- **🖥️ CLI or 🐍 Python — your choice** — every capability works as a terminal command _and_ as a plain Python method call through the `IkiProtect` facade.

---

## 🧩 The complete feature set

### 🔍 Find sensitive data — `detect`

Scans a string, file, or an entire folder and tells you exactly what it found and where.

| Category    | What it catches                                                                                                                                                          |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **PII**     | Emails, phone numbers, US Social Security numbers, IPv4 addresses, credit card numbers, IBANs                                                                            |
| **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 |

- Group findings with easy shorthands: `--types pii`, `--types secrets`, or both.
- Overlapping matches are automatically de-duplicated so you don't get double hits on the same text.
- Scan a whole repo with `--recursive`, respect a `.ikiprotectignore` file, and fail your CI pipeline with `--fail-on` if anything's found.
- Extendable with your own detectors via a plugin system.

```bash
ikiprotect detect notes.txt --format json
```

```python
findings = protect.detect("email me at a@b.com", types="pii,secrets")
```

### 🙈 Hide sensitive data — `mask`

Once something's found, replace it in place or write a cleaned copy.

| Strategy     | Example                                   | Best for                                                            |
| ------------ | ----------------------------------------- | ------------------------------------------------------------------- |
| **redact**   | `john@example.com` → `[REDACTED]`         | Logs, tickets, anything shared externally                           |
| **partial**  | `john@example.com` → `j****************m` | Support screenshots, debugging                                      |
| **tokenize** | `john@example.com` → `V-ntuFR9wvlZhRp-`   | Analytics/pseudonymization — same input always gives the same token |

```bash
ikiprotect mask notes.txt --types pii,secrets --strategy partial
ikiprotect mask foo.txt --strategy tokenize --key-ref file:./token_key.bin
```

### #️⃣ Hash anything — `hash`

One command covers everything from "checksum a file" to "store a password correctly."

- **General-purpose digests:** SHA-256, SHA-512, SHA3-256, SHA3-512, BLAKE2b, BLAKE2s, BLAKE3 (plus keyed and extendable-output BLAKE3 modes), CRC32
- **Keyed MACs (integrity/authenticity):** HMAC-SHA256, HMAC-SHA512
- **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
- Verifying a password hash auto-detects which algorithm produced it, so you don't have to remember or store that separately

```bash
echo -n "correct horse battery staple" | ikiprotect hash --algo argon2id
```

```python
pw_hash = protect.hash_password("correct horse battery staple")
protect.verify_password(pw_hash, "correct horse battery staple")
```

### 🔐 Encrypt anything — `encrypt` / `decrypt`

From a quick one-off secret to a full key-management pipeline.

- **6 authenticated ciphers:** AES-256-GCM, AES-192-GCM, AES-128-GCM, AES-256-GCM-SIV, ChaCha20-Poly1305, XChaCha20-Poly1305
- **Self-describing ciphertext** — the algorithm and nonce length travel with the ciphertext, so `decrypt` just works without extra bookkeeping
- **Layered encryption** — chain multiple algorithms together for defense-in-depth
- **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**
- **Chunked/streaming encryption** — handles multi-gigabyte files in fixed-size, independently-authenticated chunks
- **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
- **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)

```bash
ikiprotect encrypt secret.txt --key-ref env:MY_KEY -o secret.enc
ikiprotect encrypt secret.txt --envelope --key-ref env:MY_KEK -o secret.enc
ikiprotect encrypt rewrap secret.enc --old-key-ref env:OLD_KEK --new-key-ref env:NEW_KEK -o secret.rewrapped
```

```python
ciphertext = protect.encrypt(b"secret data", key)
envelope = protect.envelope_encrypt(kek, b"secret data", ["aes-256-gcm"])
encap, shared_key = protect.hybrid_encapsulate(recipient_public_key)
```

### ✍️ Prove authenticity — `sign` / `verify-signature`, `jwt`

- **Digital signatures:** Ed25519, RSA-PSS, ECDSA (P-256, P-384, P-521) — sign a release artifact, verify it came from you
- **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

```bash
ikiprotect generate-keypair --algo ed25519 -o ./keys
ikiprotect sign release.tar.gz --algo ed25519 --private-key ./keys/ed25519_private.key -o release.sig
ikiprotect jwt encode claims.json --algo HS256 --key-ref env:JWT_SECRET
```

```python
priv, pub = protect.generate_keypair("ed25519")
signature = protect.sign(b"message", priv)
token = protect.jwt_encode({"sub": "1234"}, b"hs256-secret", "HS256")
```

### 🔑 Manage your keys

- Generate keypairs (Ed25519, RSA, ECDSA P-256/384/521) with one command
- Derive an encryption key from a human passphrase (SHA-256, PBKDF2, or Argon2id)
- 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
- **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)

```bash
ikiprotect keys split secret.bin --n 5 --k 3 -o shares.json
ikiprotect keys combine shares.json -o recovered.bin
```

```python
shares = protect.split_secret(secret_bytes, n=5, k=3)
recovered = protect.combine_shares(shares)
```

### 📄 Works with structured files, too

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.

---

## 🖥️ CLI or 🐍 Python — everything, either way

Every feature above works two ways:

1. **From the terminal**, via the `ikiprotect` command (see the command table and examples above).
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.

```python
from iki_protect.facade import IkiProtect

protect = IkiProtect()

# Detect & mask
findings = protect.detect("email me at a@b.com", types="pii,secrets")
masked = protect.mask("email me at a@b.com")

# Hashing
digest = protect.hash(b"data", algorithm="sha256")
pw_hash = protect.hash_password("correct horse battery staple")
protect.verify_password(pw_hash, "correct horse battery staple")

# Encryption
key = protect.derive_passphrase_key("my passphrase")
ciphertext = protect.encrypt(b"secret data", key)
plaintext = protect.decrypt(ciphertext, key)

# Keys, signing, JWT
priv, pub = protect.generate_keypair("ed25519")
signature = protect.sign(b"message", priv)
protect.verify_signature(signature, b"message", pub)

token = protect.jwt_encode({"sub": "1234"}, b"hs256-secret", "HS256")
claims = protect.jwt_verify(token, b"hs256-secret", "HS256")
```

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.

---

## 📦 Project layout

```
src/iki_protect/
├── cli/                    # Typer-based CLI commands (detect, mask, hash, encrypt, decrypt, sign, jwt, keys)
├── content/                 # Plain text, JSON, YAML readers (one file at a time)
├── core/
│   ├── detectors/           # Regex + checksum-based PII/secret detectors, plugin registry
│   ├── keys/                 # Key resolution, generation (Ed25519/RSA/ECDSA), passphrase derivation, KMS, secret sharing
│   └── strategies/
│       ├── masking/          # Redact / partial-mask / tokenize transforms
│       ├── hashing/            # Fast hashes, HKDF, Argon2/PBKDF2 slow hashes
│       ├── encryption/          # AEAD ciphers, layered/envelope/chunked encryption, Hybrid KEM, HPKE
│       ├── signing/              # Ed25519 / RSA-PSS / ECDSA
│       └── jwt/                    # JWT encode/decode/verify
├── api.py                   # Flat re-export of every public symbol
└── facade.py                 # `IkiProtect` — one object, name-driven method for every feature
examples/example_usage.py    # Runnable end-to-end demo of the whole feature set
tests/                       # Unit + security test suites
```

## 🛠️ Installation

```bash
pip install ikiprotect
```

Requires Python ≥ 3.9. Core dependencies (installed automatically): `typer`, `rich`, `cryptography`, `blake3`, `argon2-cffi`, `PyYAML`.

Working on the source directly instead of installing from PyPI:

```bash
git clone <this-repo>
cd iki-protect
pip install -e ".[dev]"
```

## ⚡ Quick examples

```bash
# Detect and mask PII/secrets in a file
ikiprotect detect notes.txt --format json
ikiprotect mask notes.txt --types pii,secrets --strategy partial

# Hash a value with Argon2id (password-grade)
echo -n "correct horse battery staple" | ikiprotect hash --algo argon2id

# Encrypt/decrypt a file (key-ref based)
ikiprotect encrypt secret.txt --key-ref env:MY_KEY -o secret.enc
ikiprotect decrypt secret.enc --key-ref env:MY_KEY -o secret.txt

# Envelope mode (DEK/KEK): generate a random DEK, wrap under KEK
ikiprotect encrypt secret.txt --envelope --key-ref env:MY_KEK -o secret.enc
# Rotate the KEK that wraps the DEK without re-encrypting payload
ikiprotect encrypt rewrap secret.enc --old-key-ref env:OLD_KEK --new-key-ref env:NEW_KEK -o secret.rewrapped

# Recursive scan with CI gate
ikiprotect detect . --recursive --format ndjson --fail-on 1

# Tokenize values deterministically (requires keyed strategy)
ikiprotect mask foo.txt --strategy tokenize --key-ref file:./token_key.bin

# Secret sharing (split/combine)
ikiprotect keys split secret.bin --n 5 --k 3 -o shares.json
ikiprotect keys combine shares.json -o recovered.bin

# Sign and verify a release artifact
ikiprotect generate-keypair --algo ed25519 -o ./keys
ikiprotect sign release.tar.gz --algo ed25519 --private-key ./keys/ed25519_private.key -o release.sig
ikiprotect verify-signature release.tar.gz release.sig --algo ed25519 --public-key ./keys/ed25519_public.key

# JWT
ikiprotect jwt encode claims.json --algo HS256 --key-ref env:JWT_SECRET
ikiprotect jwt verify "<token>" --algo HS256 --key-ref env:JWT_SECRET
```

> **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`).**

## 🧠 Design principles

- Every command operates on **one** value/file at a time — this is not a dataset/batch tool.
- Ciphertext is **self-describing**: a version byte + implied nonce length means `decrypt` never needs the nonce or algorithm re-supplied separately.
- 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.

## License

MIT
