
The `crypto` module wraps JVM cryptography primitives behind safe, opinionated APIs. All algorithms use modern defaults: SHA-256/512, AES-256-GCM, HMAC-SHA-256, and Ed25519.

```vary
from crypto import sha256, encrypt, generate_secret_key
```

## Hashing

```vary-snippet
from crypto import sha256, sha512

let h = sha256("hello")
print(h)    # CryptoHash with hex digest

let h2 = sha512("hello")
```

| **Function** | **Returns** | **Description** |
|----------|---------|-------------|
| `sha256(text)` | `CryptoHash` | SHA-256 hash |
| `sha512(text)` | `CryptoHash` | SHA-512 hash |

## Secure random

```vary
from crypto import random_bytes, random_hex, random_int

let bytes = random_bytes(32)
let hex = random_hex(16)
let n = random_int(1, 100)
```

| **Function** | **Returns** | **Description** |
|----------|---------|-------------|
| `random_bytes(n)` | `Str` | n cryptographically random bytes |
| `random_hex(n)` | `Str` | n random bytes as hex string |
| `random_int(min, max)` | `Int` | Random integer in [min, max] |

## Password hashing

Hash and verify passwords using a secure key derivation function:

```vary
from crypto import hash_password, verify_password

let stored = hash_password("s3cret")
let ok = verify_password("s3cret", stored)    # True
let bad = verify_password("wrong", stored)    # False
```

| **Function** | **Returns** | **Description** |
|----------|---------|-------------|
| `hash_password(password)` | `CryptoPasswordHash` | Hash a password |
| `verify_password(password, stored)` | `Bool` | Check password against stored hash |

## Symmetric encryption (AES-GCM)

Encrypt and decrypt with a shared secret key. Uses AES-256-GCM with a random nonce per encryption.

```vary-snippet
from crypto import generate_secret_key, encrypt, decrypt

let key = generate_secret_key()
let ct = encrypt(key, "secret message")
let pt = decrypt(key, ct)    # "secret message"
```

| **Function** | **Returns** | **Description** |
|----------|---------|-------------|
| `generate_secret_key()` | `CryptoSecretKey` | Generate an AES-256 key |
| `encrypt(key, plaintext)` | `CryptoCipherText` | Encrypt with AES-GCM |
| `decrypt(key, ciphertext)` | `Str` | Decrypt ciphertext |

## Message authentication (HMAC-SHA-256)

Create and verify message authentication codes:

```vary-snippet
from crypto import generate_hmac_key, hmac_sha256, verify_hmac

let key = generate_hmac_key()
let tag = hmac_sha256(key, "important data")
let valid = verify_hmac(key, "important data", tag)    # True
```

| **Function** | **Returns** | **Description** |
|----------|---------|-------------|
| `generate_hmac_key()` | `CryptoHmacKey` | Generate an HMAC key |
| `hmac_sha256(key, msg)` | `CryptoMacTag` | Compute HMAC-SHA-256 tag |
| `verify_hmac(key, msg, tag)` | `Bool` | Verify HMAC tag |

## Public-key signatures (Ed25519)

Sign and verify messages with asymmetric key pairs:

```vary-snippet
from crypto import generate_signing_keypair, sign, verify_signature

let kp = generate_signing_keypair()
let sig = sign(kp.private_key(), "message")
let ok = verify_signature(kp.public_key(), "message", sig)    # True
```

| **Function** | **Returns** | **Description** |
|----------|---------|-------------|
| `generate_signing_keypair()` | `CryptoKeyPair` | Generate Ed25519 key pair |
| `sign(private_key, msg)` | `CryptoSignature` | Sign a message |
| `verify_signature(public_key, msg, sig)` | `Bool` | Verify a signature |

## Encoding helpers

```vary-snippet
from crypto import base64_encode, base64_decode, hex_encode, hex_decode

let b64 = base64_encode("hello")     # "aGVsbG8="
let raw = base64_decode(b64)         # "hello"

let hex = hex_encode("hi")
let raw2 = hex_decode(hex)           # "hi"
```

| **Function** | **Returns** | **Description** |
|----------|---------|-------------|
| `base64_encode(input)` | `Str` | Base64-encode a string |
| `base64_decode(encoded)` | `Str` | Base64-decode a string |
| `hex_encode(input)` | `Str` | Hex-encode a string |
| `hex_decode(encoded)` | `Str` | Hex-decode a string |

## Test mode

For deterministic tests, seed the random number generator:

```vary
from crypto import set_test_seed, clear_test_seed

set_test_seed(42)
# random_bytes, random_hex, random_int now produce repeatable output
clear_test_seed()
```

| **Function** | **Returns** | **Description** |
|----------|---------|-------------|
| `set_test_seed(seed)` | `None` | Fix RNG seed for deterministic output |
| `clear_test_seed()` | `None` | Restore cryptographic randomness |
