]> git.codecow.com Git - nano25519.git/commitdiff
Discard nonce prefix `z` as sensitive material unnecessary for public key derivation...
authorChris Duncan <chris@zoso.dev>
Sat, 15 Aug 2026 19:29:13 +0000 (12:29 -0700)
committerChris Duncan <chris@zoso.dev>
Sat, 15 Aug 2026 19:29:13 +0000 (12:29 -0700)
src/assembly/index.ts

index 549d116cd939dc8d369c8bd8f70339b4e4542188..be6705eb778c644bb9862ab3e65f2505d6d0553a 100644 (file)
@@ -21,6 +21,13 @@ const MESSAGE_BUFFER = memory.data(32768)
 // crypto_hash function\r
 const blake2b = new Blake2b()\r
 \r
+/**\r
+ * Clears the 3 least significant bits to guarantee multiple of 8 and prevent\r
+ * small-subgroup attacks based on Curve25519's cofactor of 8. Also sets bit 254\r
+ * and clears bit 255 to guarantee a fixed bit length for constant time\r
+ * performance.\r
+ * @param k 32-byte scalar\r
+ */\r
 //@ts-expect-error\r
 @inline\r
 function clamp (k: StaticArray<u8>): void {\r
@@ -29,14 +36,23 @@ function clamp (k: StaticArray<u8>): void {
        k[31] |= 64\r
 }\r
 \r
-const crypto_derive_pk: StaticArray<u8> = new StaticArray<u8>(PUBLICKEY_BYTES)\r
-function crypto_derive (sk: StaticArray<u8>, seed: StaticArray<u8>): void {\r
-       const pk = crypto_derive_pk\r
-       blake2b.init().update(changetype<usize>(seed), 32).digest(sk)\r
-       clamp(sk)\r
-\r
-       ge_scalarmult_base_tobytes(pk, sk)\r
-       memory.copy(changetype<usize>(sk), changetype<usize>(pk), PUBLICKEY_BYTES)\r
+const crypto_derive_a: StaticArray<u8> = new StaticArray<u8>(PRIVATEKEY_BYTES)\r
+const crypto_derive_az: StaticArray<u8> = new StaticArray<u8>(SECRETKEY_BYTES)\r
+/**\r
+ * Hash seed to 32-byte scalar `a`, clamp it, then point-multiply it by the\r
+ * Ed25519 base point.\r
+ * @param pk 32-byte output buffer for the compressed public key\r
+ * @param seed 32-byte input buffer for the securely-random secret seed value\r
+ */\r
+function crypto_derive (pk: StaticArray<u8>, seed: StaticArray<u8>): void {\r
+       const a = crypto_derive_a\r
+       const az = crypto_derive_az\r
+       blake2b.init().update(changetype<usize>(seed), 32).digest(az)\r
+       memory.copy(changetype<usize>(a), changetype<usize>(az), 32)\r
+       az.fill(0)\r
+       clamp(a)\r
+       ge_scalarmult_base_tobytes(pk, a)\r
+       a.fill(0)\r
 }\r
 \r
 const crypto_sign_az = new StaticArray<u8>(64)\r