https://github.com/vercingetorx/dilithium-nim
CRYSTALS-Dilithium in pure Nim
https://github.com/vercingetorx/dilithium-nim
cryptography crystals-dilithium digital-signature dilithium nim nim-lang post-quantum-cryptography
Last synced: 9 months ago
JSON representation
CRYSTALS-Dilithium in pure Nim
- Host: GitHub
- URL: https://github.com/vercingetorx/dilithium-nim
- Owner: vercingetorx
- License: unlicense
- Created: 2025-09-11T04:34:39.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2025-09-11T17:45:28.000Z (10 months ago)
- Last Synced: 2025-09-21T14:52:00.147Z (9 months ago)
- Topics: cryptography, crystals-dilithium, digital-signature, dilithium, nim, nim-lang, post-quantum-cryptography
- Language: Nim
- Homepage:
- Size: 972 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# dilithium-nim — Pure Nim CRYSTALS-Dilithium (signatures)
A **pure Nim** port of the CRYSTALS-Dilithium digital signature scheme (post-quantum).
Uses SHAKE (Keccak) and constant-time helpers implemented in Nim.
Dilithium lets you create a **public key**, sign messages with a **secret key**, and anyone can verify those signatures with the public key. It’s NIST-standardized.
## Status
* Implements the full signature API (keygen, sign, verify) for **Dilithium2/3/5**.
* Passes the official **NIST KAT (.rsp)** vectors.
* Supports both **deterministic** and **randomized** signing (compile-time toggle).
* Optional **context label** (up to 255 bytes).
## Sizes (by parameter set)
| Set | Public Key | Secret Key | Signature |
| ---------- | ---------- | ---------- | --------- |
| Dilithium2 | 1312 B | 2528 B | 2420 B |
| Dilithium3 | 1952 B | 4000 B | 3293 B |
| Dilithium5 | 2592 B | 4864 B | 4595 B |
> Message size is unchanged by signing; only the signature is added.
## Quick API
Simple, human-readable API (see `dilithium.nim`).
```nim
import dilithium # exports: generateKeypair, signDetached, verifyDetached, signMessage, openSignedMessage
# 1) Make a key pair (uses OS randomness).
let (publicKey, secretKey) = generateKeypair()
# 2) Sign a message (detached signature).
let message = "Meet at 12:30 near the cafe."
let signature = signDetached(message, secretKey) # optional label: signDetached(message, secretKey, "orders")
# 3) Verify the detached signature.
let ok = verifyDetached(signature, message, publicKey)
doAssert ok
# 4) Sign a message as a single blob (attached: signature stored before the message).
let signedBlob = signMessage(message, secretKey) # optional label: signMessage(message, secretKey, "chat")
# 5) Verify and recover the original message from a signed blob.
let (valid, recovered) = openSignedMessage(signedBlob, publicKey)
doAssert valid
```
### With a context label (optional)
Use a short label to keep signatures scoped to a feature in your app (e.g., `"login"`, `"invoice"`).
You must pass **the same label** to both sign and verify.
```nim
let label = "orders"
let sig = signDetached("Order #4821: ship today", secretKey, label)
let ok = verifyDetached(sig, "Order #4821: ship today", publicKey, label) # true
let no = verifyDetached(sig, "Order #4821: ship today", publicKey, "WRONG")# false
```
## Deterministic vs randomized signing
By default we follow the reference: **randomized signing** adds fresh randomness to each signature.
**disable** randomized signing at compile time:
```bash
# Deterministic signing (rnd = all zero bytes):
-d:nors or -d:norandsig
```
Enable it (default, can be omitted):
```bash
# Randomized signing (fresh randomness per signature):
-d:rs or -d:randsig
```
## Selecting the parameter set
Default is **Dilithium2**. Choose at compile time:
```bash
-d:mode=2 # Dilithium2
-d:mode=3 # Dilithium3
-d:mode=5 # Dilithium5
```
## Testing (KAT)
A lightweight KAT harness is included (parses NIST `.rsp` and checks `pk/sk/sm`):
```bash
# Example: point to the Dilithium2 vectors
KAT_RSP=/nistkat/PQCsignKAT_Dilithium2.rsp \
nim c -r -d:kat nistkat/test_kat_runner.nim
```
Tips:
* Use `KAT_LIMIT=N` to run only the first N vectors while debugging.
## RNG
* **Public API** uses the OS RNG (e.g., `/dev/urandom`) for keygen and (if enabled) for randomized signing.
* The **KAT harness** uses the same deterministic DRBG as the reference so results match the `.rsp` files.
## Security notes
* Constant-time primitives are used where required, but this code has **not been audited**.
* Nim is GC’d; **secret zeroization is not guaranteed**. Be careful with long-lived secrets.
## Layout
```
src/
ntt.nim # Number-theoretic transform and tables
packing.nim # (Un)packing of keys/signatures
params.nim # Parameter set & sizes; selected by DILITHIUM_MODE (2/3/5)
poly.nim # Polynomial ops
polyvec.nim # Vectors of polynomials
randombytes.nim # OS RNG for public API (e.g., /dev/urandom)
reduce.nim # Modular reduction helpers
rounding.nim # power2round, decompose, hints (make_hint/use_hint)
sign.nim # Keygen, sign, verify (public API)
symmetric.nim # SHAKE256 wrappers (XOF/PRF)
dilithium.nim # high-level, friendly API
test/ # basic tests
nistkat/ # KAT tests
private/ # crypto backends
```
### Note
This project is for reference/education. Do **not** use in production without an independent security review.