An open API service indexing awesome lists of open source software.

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

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.