]> git.codecow.com Git - nano25519.git/commitdiff
Add canary for equalbytes. Add fabricated valid signature for identity public key.
authorChris Duncan <chris@codecow.com>
Fri, 4 Sep 2026 20:52:03 +0000 (13:52 -0700)
committerChris Duncan <chris@codecow.com>
Fri, 4 Sep 2026 20:52:03 +0000 (13:52 -0700)
test/node.mjs
test/vectors.mjs

index f26e4b5039459797c95c3207142ac63949aa36fb..4dcf2e5f49215cf49b2e9dc0650bd92cbe45d3a9 100644 (file)
@@ -2,7 +2,7 @@
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
 import { constants, derive, sign, verify, verify_blocks } from 'nano25519'
-import { NANO_ORG_VECTOR, PROBLEM_VECTOR, PYTHON_ED25519_BLAKE2B_VECTORS } from './vectors.mjs'
+import { IDENTITY, NANO_ORG_VECTOR, PROBLEM_VECTOR, PYTHON_ED25519_BLAKE2B_VECTORS } from './vectors.mjs'
 
 /**
  * @param {string} name
@@ -189,6 +189,24 @@ check(`verify_blocks relaxed check passes problematic signature string ${PROBLEM
 passes += +test
 failures += +!test
 
+// identity A and S=0 pin check_r so only R moves; any other A hides equalbytes bugs
+const forgery = IDENTITY.signatureBytes.slice()
+const accepted = []
+for (let i = 0; i < constants.KEY_BYTELENGTH; i++) {
+       for (let j = 1; j < 256; j++) {
+               forgery[i] ^= j
+               result = verify_blocks(IDENTITY.publicKeyBytes, [{ signature: forgery, hash: new Uint8Array(32) }])[0]
+               forgery[i] = IDENTITY.signatureBytes[i]
+               if (result !== false) {
+                       accepted.push({ byte: i, mask: `0x${j.toString(16).padStart(2, '0')}` })
+               }
+       }
+}
+test = accepted.length === 0
+check(`verify_blocks rejects R xor mask${test ? '' : ` (failed to reject ${accepted})`}`, test)
+passes += +test
+failures += +!test
+
 // Check output buffer offset handling
 try {
        outbuf = new Uint8Array(33)
index 0d119dc3219a8309c242a2e5874f9d65929c5a13..1922f8c9288662ba90ff3f7471d8060ee42b24d9 100644 (file)
@@ -6,6 +6,8 @@ export { PYTHON_ED25519_BLAKE2B_VECTORS } from './python_ed25519_blake2b_vectors
 export const IDENTITY = {
        publicKey: '0100000000000000000000000000000000000000000000000000000000000000',
        publicKeyBytes: new Uint8Array([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
+       signature: '01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+       signatureBytes: new Uint8Array([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
 }
 
 /**
@@ -27,7 +29,7 @@ export const NANO_ORG_VECTOR = {
 /**
  * https://github.com/rsnano-node/rsnano-node/blob/develop/types/src/private_key.rs
  *
- * Small-order public key producing malleable signatures
+ * Identity point as public key producing malleable signatures
  *
  * Address: nano_11a11111111111111111111111111111111111111111111111116iq5p4i8
  */