diff --git a/src/ml-dsa.ts b/src/ml-dsa.ts index 2cc84cf..409b5a1 100644 --- a/src/ml-dsa.ts +++ b/src/ml-dsa.ts @@ -13,13 +13,15 @@ import { concatBytes, } from './utils.js'; -/* -Lattice-based digital signature algorithm. See -[official site](https://www.pq-crystals.org/dilithium/index.shtml), -[repo](https://github.com/pq-crystals/dilithium). -Dilithium has similar internals to Kyber, but their keys and params are different. - -*/ +/** + * Module Lattice-based Digital Signature Algorithm (ML-DSA). A.k.a. CRYSTALS-Dilithium. + * FIPS-204 is implemented. + * + * Has similar internals to ML-KEM, but their keys and params are different. + * Check out [official site](https://www.pq-crystals.org/dilithium/index.shtml), + * [repo](https://github.com/pq-crystals/dilithium). + * @module + */ // Constants const N = 256; diff --git a/src/ml-kem.ts b/src/ml-kem.ts index 229ced1..8e94a86 100644 --- a/src/ml-kem.ts +++ b/src/ml-kem.ts @@ -12,27 +12,27 @@ import { vecCoder, } from './utils.js'; -/* -Lattice-based key encapsulation mechanism. -See [official site](https://www.pq-crystals.org/kyber/resources.shtml), -[repo](https://github.com/pq-crystals/kyber), -[spec](https://datatracker.ietf.org/doc/draft-cfrg-schwabe-kyber/). - -Key encapsulation is similar to DH / ECDH (think X25519), with important differences: - -- We can't verify if it was "Bob" who've sent the shared secret. - In ECDH, it's always verified -- Kyber is probabalistic and relies on quality of randomness (CSPRNG). - ECDH doesn't (to this extent). -- Kyber decapsulation never throws an error, even when shared secret was - encrypted by a different public key. It will just return a different - shared secret - -There are some concerns with regards to security: see -[djb blog](https://blog.cr.yp.to/20231003-countcorrectly.html) and -[mailing list](https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/W2VOzy0wz_E). - -*/ +/** + * Module Lattice-based Key Encapsulation Mechanism (ML-KEM). A.k.a. CRYSTALS-Kyber. + * FIPS-203 is implemented. + * + * Key encapsulation is similar to DH / ECDH (think X25519), with important differences: + * * Unlike in ECDH, we can't verify if it was "Bob" who've sent the shared secret + * * Unlike ECDH, it is probabalistic and relies on quality of randomness (CSPRNG). + * * Decapsulation never throws an error, even when shared secret was + * encrypted by a different public key. It will just return a different shared secret. + * + * There are some concerns with regards to security: see + * [djb blog](https://blog.cr.yp.to/20231003-countcorrectly.html) and + * [mailing list](https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/W2VOzy0wz_E). + * + * Has similar internals to ML-DSA, but their keys and params are different. + * + * Check out [official site](https://www.pq-crystals.org/kyber/resources.shtml), + * [repo](https://github.com/pq-crystals/kyber), + * [spec](https://datatracker.ietf.org/doc/draft-cfrg-schwabe-kyber/). + * @module + */ const N = 256; // Kyber (not FIPS-203) supports different lengths, but all std modes were using 256 const Q = 3329; // 13*(2**8)+1, modulo prime diff --git a/src/slh-dsa.ts b/src/slh-dsa.ts index dd88d3d..6afb75c 100644 --- a/src/slh-dsa.ts +++ b/src/slh-dsa.ts @@ -14,34 +14,31 @@ import { vecCoder, } from './utils.js'; -/* -Hash-based digital signature algorithm. See [official site](https://sphincs.org). -We implement spec v3.1 with latest FIPS-205 changes. -It's compatible with the latest version in the [official repo](https://github.com/sphincs/sphincsplus). - -*/ - -/* -WOTS: One-time signatures (can be forged if same key used twice) -FORS: Forest of Random Subsets - -Hashes are like signatures. You take private key, hash it, and share the result pubKey. -After that you can verify it was yours by also sharing the private key. -However, it will only work once: after pre-image was disclosed, it can't be used again. -It also doesn't sign the message: can be interceptd and message can be replaced. - -How to solve "one-time" hashing? Instead of hash(k), we can provide merkle tree root hash: - - h(h(h(0) || h(1)) || h(h(2) || h(3)))) - -Now, we have the same pubKey output of hash, but disclosing one path in tree doesn't -invalidate the others, since they are still unknown. By choosing path which is related -to the message, we can "sign" it. - -There is a limitation: only a fixed amount of signatures can be made, -a merkle tree with depth: 8 would mean 2**8 (256) paths aka 256 distinct messages. -Attaching a different tree to each node will solve forgeries, but the key would still degrade. -*/ +/** + * StateLess Hash-based Digital Signature Standard (SLH-DSA). A.k.a. Sphincs+. + * FIPS-205 (spec v3.1) is implemented. + * + * Hashes function similarly to signatures. You hash a private key to get a public key, + * which can be used to verify the private key. However, this only works once since + * disclosing the pre-image invalidates the key. + * + * To address the "one-time" limitation, we can use a Merkle tree root hash: + * h(h(h(0) || h(1)) || h(h(2) || h(3)))) + * + * This allows us to have the same public key output from the hash, but disclosing one + * path in the tree doesn't invalidate the others. By choosing a path related to the + * message, we can "sign" it. + * + * Limitation: Only a fixed number of signatures can be made. For instance, a Merkle tree + * with depth 8 allows 256 distinct messages. Using different trees for each node can + * prevent forgeries, but the key will still degrade over time. + * + * WOTS: One-time signatures (can be forged if same key used twice). + * FORS: Forest of Random Subsets + * + * Check out [official site](https://sphincs.org) & [repo](https://github.com/sphincs/sphincsplus). + * @module + */ /** * * N: Security parameter (in bytes). W: Winternitz parameter