&& a.byteLength !== 0
}
-let outbuf, result, test, passes = 0, failures = 0
+let outbuf, length, result, test, passes = 0, failures = 0
// Check string input validation
try {
passes += +test
failures += +!test
+// Check output buffer offset handling
+try {
+ outbuf = new Uint8Array(33)
+ result = derive(NANO_ORG_VECTOR.privateKeyBytes, outbuf)
+ result = false
+} catch (err) {
+ if (err != null && typeof err === 'object' && 'message' in err) {
+ result = err.message === 'Derive output buffer must be 32-byte Uint8Array<ArrayBuffer>'
+ } else {
+ result = false
+ }
+}
+test = result === true
+check(`derive offset outbuf wrong length`, test)
+passes += +test
+failures += +!test
+
+try {
+ outbuf = new Uint8Array(65)
+ result = sign(NANO_ORG_VECTOR.blockHashBytes, NANO_ORG_VECTOR.secretKeyBytes, outbuf)
+ result = false
+} catch (err) {
+ if (err != null && typeof err === 'object' && 'message' in err) {
+ result = err.message === 'Sign output buffer must be 64-byte Uint8Array<ArrayBuffer>'
+ } else {
+ result = false
+ }
+}
+test = result === true
+check(`sign offset outbuf wrong length`, test)
+passes += +test
+failures += +!test
+
// Check combined imports
result = await Nano25519.deriveAsync(NANO_ORG_VECTOR.privateKeyBytes)
-console.log(`RESULT`, result)
test = [...result].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.publicKey.toLowerCase()
check(`async derive from ${NANO_ORG_VECTOR.privateKey}`, test)
passes += +test
// Check async imports with string inputs
result = await deriveAsync(NANO_ORG_VECTOR.privateKey)
test = result.toLowerCase() === NANO_ORG_VECTOR.publicKey.toLowerCase()
-console.log(result)
-console.log()
check(`async derive from private key string ${NANO_ORG_VECTOR.privateKey}`, test)
passes += +test
failures += +!test
// Check async imports with byte inputs
result = await deriveAsync(NANO_ORG_VECTOR.privateKeyBytes)
-console.log(`RESULT`, result)
test = [...result].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.publicKey.toLowerCase()
check(`async derive from private key bytes ${NANO_ORG_VECTOR.privateKey}`, test)
passes += +test
// Check sync imports with byte inputs and preallocated output buffer
outbuf = new Uint8Array(32)
result = derive(NANO_ORG_VECTOR.privateKeyBytes, outbuf)
-test = overlaps(result, outbuf) && [...result].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.publicKey.toLowerCase()
+test = overlaps(result, outbuf)
+test &&= [...result].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.publicKey.toLowerCase()
+test &&= [...outbuf].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.publicKey.toLowerCase()
check(`derive from private key bytes ${NANO_ORG_VECTOR.privateKey} and allocate result to output buffer`, test)
passes += +test
failures += +!test
outbuf = new Uint8Array(64)
result = sign(NANO_ORG_VECTOR.blockHashBytes, NANO_ORG_VECTOR.secretKeyBytes, outbuf)
-test = overlaps(result, outbuf) && [...result].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.signature.toLowerCase()
+test = overlaps(result, outbuf)
+test &&= [...result].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.signature.toLowerCase()
+test &&= [...outbuf].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.signature.toLowerCase()
check(`sign message bytes ${NANO_ORG_VECTOR.blockHash} and allocate result to output buffer`, test)
passes += +test
failures += +!test
+// Check sync imports with byte inputs and offset output buffer
+length = 33 + crypto.getRandomValues(new Uint8Array(1))[0]
+outbuf = new Uint8Array(new ArrayBuffer(length), length - 32, 32)
+result = derive(NANO_ORG_VECTOR.privateKeyBytes, outbuf)
+test = overlaps(result, outbuf)
+test &&= [...result].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.publicKey.toLowerCase()
+test &&= [...outbuf].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.publicKey.toLowerCase()
+test &&= [...new Uint8Array(result.buffer)].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() !== NANO_ORG_VECTOR.publicKey.toLowerCase()
+test &&= [...new Uint8Array(outbuf.buffer)].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() !== NANO_ORG_VECTOR.publicKey.toLowerCase()
+check(`derive from private key bytes ${NANO_ORG_VECTOR.privateKey} to offset outbuf`, test)
+passes += +test
+failures += +!test
+
+length = 65 + crypto.getRandomValues(new Uint8Array(1))[0]
+outbuf = new Uint8Array(new ArrayBuffer(length), length - 64, 64)
+result = sign(NANO_ORG_VECTOR.blockHashBytes, NANO_ORG_VECTOR.secretKeyBytes, outbuf)
+test = overlaps(result, outbuf)
+test &&= [...result].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.signature.toLowerCase()
+test &&= [...outbuf].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.signature.toLowerCase()
+test &&= [...new Uint8Array(result.buffer)].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() !== NANO_ORG_VECTOR.publicKey.toLowerCase()
+test &&= [...new Uint8Array(outbuf.buffer)].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() !== NANO_ORG_VECTOR.publicKey.toLowerCase()
+check(`sign message bytes ${NANO_ORG_VECTOR.blockHash} to offset outbuf`, test)
+passes += +test
+failures += +!test
+
// test both string inputs and byte inputs
for (const { privateKey, publicKey, message, signature } of PYTHON_ED25519_BLAKE2B_VECTORS) {
result = derive(privateKey)