]> git.codecow.com Git - nano25519.git/commitdiff
Use same endian-aware buffer copy from message for keys and signatures.
authorChris Duncan <chris@zoso.dev>
Sun, 27 Sep 2026 07:53:03 +0000 (00:53 -0700)
committerChris Duncan <chris@zoso.dev>
Sun, 27 Sep 2026 07:53:03 +0000 (00:53 -0700)
src/lib/wasm.ts

index 595540ea6cdc4c7b20928f8d8ce2a94f9e8ccf61..cf14aafbd105db7556ba305cc11937b01728b693 100644 (file)
@@ -82,6 +82,8 @@ const MAX_VERIFY_BLOCKS = exports.MAX_VERIFY_BLOCKS.value
 const MAX_VERIFY_BLOCKS_BYTELENGTH = exports.MAX_VERIFY_BLOCKS_BYTELENGTH.value
 const MAX_MESSAGE_BYTELENGTH = exports.MAX_MESSAGE_BYTELENGTH.value
 
+const setInputView = isLE ? words : (b: Bytes): Bytes => b
+
 /**
  * Packs 32 bytes of message `m` starting at byte `i` into the static message
  * input buffer of the WASM module in little-endian order to align with the WASM
@@ -92,30 +94,30 @@ const MAX_MESSAGE_BYTELENGTH = exports.MAX_MESSAGE_BYTELENGTH.value
  * This is the path for partial words. It runs for the short final chunk of any
  * message and ensures little-endian byte order and zero-padded filler.
  */
-function setInputMsgShift (m: Bytes, i: number): void {
+function setInputMsgShift (b: Bytes, i: number): void {
        exports.setInputMsg(i,
-               (m[i] ?? 0) | ((m[i + 1] ?? 0) << 8) | ((m[i + 2] ?? 0) << 16) | ((m[i + 3] ?? 0) << 24),
-               (m[i + 4] ?? 0) | ((m[i + 5] ?? 0) << 8) | ((m[i + 6] ?? 0) << 16) | ((m[i + 7] ?? 0) << 24),
-               (m[i + 8] ?? 0) | ((m[i + 9] ?? 0) << 8) | ((m[i + 10] ?? 0) << 16) | ((m[i + 11] ?? 0) << 24),
-               (m[i + 12] ?? 0) | ((m[i + 13] ?? 0) << 8) | ((m[i + 14] ?? 0) << 16) | ((m[i + 15] ?? 0) << 24),
-               (m[i + 16] ?? 0) | ((m[i + 17] ?? 0) << 8) | ((m[i + 18] ?? 0) << 16) | ((m[i + 19] ?? 0) << 24),
-               (m[i + 20] ?? 0) | ((m[i + 21] ?? 0) << 8) | ((m[i + 22] ?? 0) << 16) | ((m[i + 23] ?? 0) << 24),
-               (m[i + 24] ?? 0) | ((m[i + 25] ?? 0) << 8) | ((m[i + 26] ?? 0) << 16) | ((m[i + 27] ?? 0) << 24),
-               (m[i + 28] ?? 0) | ((m[i + 29] ?? 0) << 8) | ((m[i + 30] ?? 0) << 16) | ((m[i + 31] ?? 0) << 24)
+               (b[i] ?? 0) | ((b[i + 1] ?? 0) << 8) | ((b[i + 2] ?? 0) << 16) | ((b[i + 3] ?? 0) << 24),
+               (b[i + 4] ?? 0) | ((b[i + 5] ?? 0) << 8) | ((b[i + 6] ?? 0) << 16) | ((b[i + 7] ?? 0) << 24),
+               (b[i + 8] ?? 0) | ((b[i + 9] ?? 0) << 8) | ((b[i + 10] ?? 0) << 16) | ((b[i + 11] ?? 0) << 24),
+               (b[i + 12] ?? 0) | ((b[i + 13] ?? 0) << 8) | ((b[i + 14] ?? 0) << 16) | ((b[i + 15] ?? 0) << 24),
+               (b[i + 16] ?? 0) | ((b[i + 17] ?? 0) << 8) | ((b[i + 18] ?? 0) << 16) | ((b[i + 19] ?? 0) << 24),
+               (b[i + 20] ?? 0) | ((b[i + 21] ?? 0) << 8) | ((b[i + 22] ?? 0) << 16) | ((b[i + 23] ?? 0) << 24),
+               (b[i + 24] ?? 0) | ((b[i + 25] ?? 0) << 8) | ((b[i + 26] ?? 0) << 16) | ((b[i + 27] ?? 0) << 24),
+               (b[i + 28] ?? 0) | ((b[i + 29] ?? 0) << 8) | ((b[i + 30] ?? 0) << 16) | ((b[i + 31] ?? 0) << 24)
        )
 }
 
-function setInputMsgWords (m: Words, i: number): void {
+function setInputMsgWords (w: Words, i: number): void {
        const p = i >> 2
        exports.setInputMsg(i,
-               m[p],
-               m[p + 1],
-               m[p + 2],
-               m[p + 3],
-               m[p + 4],
-               m[p + 5],
-               m[p + 6],
-               m[p + 7]
+               w[p],
+               w[p + 1],
+               w[p + 2],
+               w[p + 3],
+               w[p + 4],
+               w[p + 5],
+               w[p + 6],
+               w[p + 7]
        )
 }
 
@@ -138,7 +140,7 @@ const setInputMsgEndian = isLE ? setInputMsgWords : setInputMsgShift
 function setInputMsg (message: Bytes): void {
        const mlen = byteLength(message)
        const mlentrunc = mlen & ~31
-       const m = words(message)
+       const m = setInputView(message)
        for (let i = 0; i < mlentrunc; i += 32) {
                //@ts-expect-error
                setInputMsgEndian(m, i)
@@ -148,6 +150,34 @@ function setInputMsg (message: Bytes): void {
        }
 }
 
+function setInputPrvShift (b: Bytes): void {
+       exports.setInputPrv(
+               (b[0] ?? 0) | ((b[1] ?? 0) << 8) | ((b[2] ?? 0) << 16) | ((b[3] ?? 0) << 24),
+               (b[4] ?? 0) | ((b[5] ?? 0) << 8) | ((b[6] ?? 0) << 16) | ((b[7] ?? 0) << 24),
+               (b[8] ?? 0) | ((b[9] ?? 0) << 8) | ((b[10] ?? 0) << 16) | ((b[11] ?? 0) << 24),
+               (b[12] ?? 0) | ((b[13] ?? 0) << 8) | ((b[14] ?? 0) << 16) | ((b[15] ?? 0) << 24),
+               (b[16] ?? 0) | ((b[17] ?? 0) << 8) | ((b[18] ?? 0) << 16) | ((b[19] ?? 0) << 24),
+               (b[20] ?? 0) | ((b[21] ?? 0) << 8) | ((b[22] ?? 0) << 16) | ((b[23] ?? 0) << 24),
+               (b[24] ?? 0) | ((b[25] ?? 0) << 8) | ((b[26] ?? 0) << 16) | ((b[27] ?? 0) << 24),
+               (b[28] ?? 0) | ((b[29] ?? 0) << 8) | ((b[30] ?? 0) << 16) | ((b[31] ?? 0) << 24)
+       )
+}
+
+function setInputPrvWords (w: Words): void {
+       exports.setInputPrv(
+               w[0],
+               w[1],
+               w[2],
+               w[3],
+               w[4],
+               w[5],
+               w[6],
+               w[7]
+       )
+}
+
+const setInputPrvEndian = isLE ? setInputPrvWords : setInputPrvShift
+
 /**
  * Copies the bytes of a private key into the static private key input buffer of
  * the WASM module. Bytes are packed in little-endian order to align with the
@@ -155,18 +185,39 @@ function setInputMsg (message: Bytes): void {
  * intermediate array because allocating costs more than the copy itself.
  */
 function setInputPrv (prv: Bytes): void {
-       exports.setInputPrv(
-               prv[0] | (prv[1] << 8) | (prv[2] << 16) | (prv[3] << 24),
-               prv[4] | (prv[5] << 8) | (prv[6] << 16) | (prv[7] << 24),
-               prv[8] | (prv[9] << 8) | (prv[10] << 16) | (prv[11] << 24),
-               prv[12] | (prv[13] << 8) | (prv[14] << 16) | (prv[15] << 24),
-               prv[16] | (prv[17] << 8) | (prv[18] << 16) | (prv[19] << 24),
-               prv[20] | (prv[21] << 8) | (prv[22] << 16) | (prv[23] << 24),
-               prv[24] | (prv[25] << 8) | (prv[26] << 16) | (prv[27] << 24),
-               prv[28] | (prv[29] << 8) | (prv[30] << 16) | (prv[31] << 24)
+       const p = setInputView(prv)
+       //@ts-expect-error
+       setInputPrvEndian(p)
+}
+
+function setInputPubShift (b: Bytes): void {
+       exports.setInputPub(
+               b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24),
+               b[4] | (b[5] << 8) | (b[6] << 16) | (b[7] << 24),
+               b[8] | (b[9] << 8) | (b[10] << 16) | (b[11] << 24),
+               b[12] | (b[13] << 8) | (b[14] << 16) | (b[15] << 24),
+               b[16] | (b[17] << 8) | (b[18] << 16) | (b[19] << 24),
+               b[20] | (b[21] << 8) | (b[22] << 16) | (b[23] << 24),
+               b[24] | (b[25] << 8) | (b[26] << 16) | (b[27] << 24),
+               b[28] | (b[29] << 8) | (b[30] << 16) | (b[31] << 24)
+       )
+}
+
+function setInputPubWords (w: Words): void {
+       exports.setInputPub(
+               w[0],
+               w[1],
+               w[2],
+               w[3],
+               w[4],
+               w[5],
+               w[6],
+               w[7]
        )
 }
 
+const setInputPubEndian = isLE ? setInputPubWords : setInputPubShift
+
 /**
  * Copies the bytes of a public key into the static public key input buffer of
  * the WASM module. Bytes are packed in little-endian order to align with the
@@ -174,18 +225,55 @@ function setInputPrv (prv: Bytes): void {
  * intermediate array because allocating costs more than the copy itself.
  */
 function setInputPub (pub: Bytes): void {
-       exports.setInputPub(
-               pub[0] | (pub[1] << 8) | (pub[2] << 16) | (pub[3] << 24),
-               pub[4] | (pub[5] << 8) | (pub[6] << 16) | (pub[7] << 24),
-               pub[8] | (pub[9] << 8) | (pub[10] << 16) | (pub[11] << 24),
-               pub[12] | (pub[13] << 8) | (pub[14] << 16) | (pub[15] << 24),
-               pub[16] | (pub[17] << 8) | (pub[18] << 16) | (pub[19] << 24),
-               pub[20] | (pub[21] << 8) | (pub[22] << 16) | (pub[23] << 24),
-               pub[24] | (pub[25] << 8) | (pub[26] << 16) | (pub[27] << 24),
-               pub[28] | (pub[29] << 8) | (pub[30] << 16) | (pub[31] << 24)
+       const p = setInputView(pub)
+       //@ts-expect-error
+       setInputPubEndian(p)
+}
+
+function setInputSigShift (b: Bytes): void {
+       exports.setInputSig(
+               b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24),
+               b[4] | (b[5] << 8) | (b[6] << 16) | (b[7] << 24),
+               b[8] | (b[9] << 8) | (b[10] << 16) | (b[11] << 24),
+               b[12] | (b[13] << 8) | (b[14] << 16) | (b[15] << 24),
+               b[16] | (b[17] << 8) | (b[18] << 16) | (b[19] << 24),
+               b[20] | (b[21] << 8) | (b[22] << 16) | (b[23] << 24),
+               b[24] | (b[25] << 8) | (b[26] << 16) | (b[27] << 24),
+               b[28] | (b[29] << 8) | (b[30] << 16) | (b[31] << 24),
+               b[32] | (b[33] << 8) | (b[34] << 16) | (b[35] << 24),
+               b[36] | (b[37] << 8) | (b[38] << 16) | (b[39] << 24),
+               b[40] | (b[41] << 8) | (b[42] << 16) | (b[43] << 24),
+               b[44] | (b[45] << 8) | (b[46] << 16) | (b[47] << 24),
+               b[48] | (b[49] << 8) | (b[50] << 16) | (b[51] << 24),
+               b[52] | (b[53] << 8) | (b[54] << 16) | (b[55] << 24),
+               b[56] | (b[57] << 8) | (b[58] << 16) | (b[59] << 24),
+               b[60] | (b[61] << 8) | (b[62] << 16) | (b[63] << 24)
        )
 }
 
+function setInputSigWords (w: Words): void {
+       exports.setInputSig(
+               w[0],
+               w[1],
+               w[2],
+               w[3],
+               w[4],
+               w[5],
+               w[6],
+               w[7],
+               w[8],
+               w[9],
+               w[10],
+               w[11],
+               w[12],
+               w[13],
+               w[14],
+               w[15]
+       )
+}
+
+const setInputSigEndian = isLE ? setInputSigWords : setInputSigShift
+
 /**
  * Copies the bytes of a detached signature into the static signature input
  * buffer of the WASM module. Bytes are packed in little-endian order to align
@@ -193,24 +281,9 @@ function setInputPub (pub: Bytes): void {
  * intermediate array because allocating costs more than the copy itself.
  */
 function setInputSig (sig: Bytes): void {
-       exports.setInputSig(
-               sig[0] | (sig[1] << 8) | (sig[2] << 16) | (sig[3] << 24),
-               sig[4] | (sig[5] << 8) | (sig[6] << 16) | (sig[7] << 24),
-               sig[8] | (sig[9] << 8) | (sig[10] << 16) | (sig[11] << 24),
-               sig[12] | (sig[13] << 8) | (sig[14] << 16) | (sig[15] << 24),
-               sig[16] | (sig[17] << 8) | (sig[18] << 16) | (sig[19] << 24),
-               sig[20] | (sig[21] << 8) | (sig[22] << 16) | (sig[23] << 24),
-               sig[24] | (sig[25] << 8) | (sig[26] << 16) | (sig[27] << 24),
-               sig[28] | (sig[29] << 8) | (sig[30] << 16) | (sig[31] << 24),
-               sig[32] | (sig[33] << 8) | (sig[34] << 16) | (sig[35] << 24),
-               sig[36] | (sig[37] << 8) | (sig[38] << 16) | (sig[39] << 24),
-               sig[40] | (sig[41] << 8) | (sig[42] << 16) | (sig[43] << 24),
-               sig[44] | (sig[45] << 8) | (sig[46] << 16) | (sig[47] << 24),
-               sig[48] | (sig[49] << 8) | (sig[50] << 16) | (sig[51] << 24),
-               sig[52] | (sig[53] << 8) | (sig[54] << 16) | (sig[55] << 24),
-               sig[56] | (sig[57] << 8) | (sig[58] << 16) | (sig[59] << 24),
-               sig[60] | (sig[61] << 8) | (sig[62] << 16) | (sig[63] << 24)
-       )
+       const s = setInputView(sig)
+       //@ts-expect-error
+       setInputSigEndian(s)
 }
 
 /**