Files
salvium-rs/test/blake2b.test.js
T
Matt Hess 3658a0c33f New Features:
- generateSeed() - Cryptographically secure random seed generation
  - deriveKeys() - CryptoNote key derivation (spend/view secret & public keys)
  - deriveCarrotKeys() - CARROT key derivation (all 6 CARROT keys)
  - Blake2b tests with RFC 7693 test vectors
  - CryptoNote key derivation tests
  - CARROT key derivation tests
  - Updated exports in index.js
2026-01-14 23:59:27 +00:00

266 lines
8.2 KiB
JavaScript

/**
* Blake2b Tests
*
* Tests for Blake2b hash function with RFC 7693 test vectors.
*/
import { blake2b, blake2bHex } from '../src/blake2b.js';
import { bytesToHex, hexToBytes } from '../src/index.js';
let passed = 0;
let failed = 0;
function test(name, fn) {
try {
fn();
console.log(`${name}`);
passed++;
} catch (error) {
console.log(`${name}`);
console.log(` Error: ${error.message}`);
failed++;
}
}
function assertEqual(actual, expected, message = '') {
if (actual !== expected) {
throw new Error(`${message} Expected "${expected}", got "${actual}"`);
}
}
function assertLength(value, length, message = '') {
if (value.length !== length) {
throw new Error(`${message} Expected length ${length}, got ${value.length}`);
}
}
function assertTrue(value, message = '') {
if (!value) {
throw new Error(`${message} Expected true, got ${value}`);
}
}
// ============================================================
// RFC 7693 Test Vectors
// ============================================================
console.log('\n--- RFC 7693 Test Vectors ---');
// From RFC 7693 Appendix A (empty input, 64-byte output, no key)
test('Empty input, 64-byte output (RFC 7693)', () => {
const hash = blake2b(new Uint8Array(0), 64);
const expected = '786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce';
assertEqual(bytesToHex(hash), expected);
});
// From RFC 7693 Appendix A ("abc", 64-byte output, no key)
test('"abc" input, 64-byte output (RFC 7693)', () => {
const input = new TextEncoder().encode('abc');
const hash = blake2b(input, 64);
const expected = 'ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923';
assertEqual(bytesToHex(hash), expected);
});
// ============================================================
// Variable Output Length Tests
// ============================================================
console.log('\n--- Variable Output Length Tests ---');
test('blake2b returns correct length for 32 bytes', () => {
const hash = blake2b(new Uint8Array(0), 32);
assertLength(hash, 32);
});
test('blake2b returns correct length for 64 bytes', () => {
const hash = blake2b(new Uint8Array(0), 64);
assertLength(hash, 64);
});
test('blake2b returns correct length for 1 byte', () => {
const hash = blake2b(new Uint8Array(0), 1);
assertLength(hash, 1);
});
test('blake2b throws for output length 0', () => {
let threw = false;
try {
blake2b(new Uint8Array(0), 0);
} catch (e) {
threw = true;
}
assertTrue(threw, 'Should throw for output length 0');
});
test('blake2b throws for output length > 64', () => {
let threw = false;
try {
blake2b(new Uint8Array(0), 65);
} catch (e) {
threw = true;
}
assertTrue(threw, 'Should throw for output length 65');
});
// ============================================================
// Determinism Tests
// ============================================================
console.log('\n--- Determinism Tests ---');
test('blake2b is deterministic', () => {
const input = new Uint8Array([1, 2, 3, 4, 5]);
const h1 = blake2b(input, 32);
const h2 = blake2b(input, 32);
assertEqual(bytesToHex(h1), bytesToHex(h2));
});
test('blake2b produces different output for different input', () => {
const input1 = new Uint8Array([1, 2, 3]);
const input2 = new Uint8Array([1, 2, 4]);
const h1 = blake2b(input1, 32);
const h2 = blake2b(input2, 32);
assertTrue(bytesToHex(h1) !== bytesToHex(h2));
});
test('blake2b produces different output for different lengths', () => {
const input = new Uint8Array([1, 2, 3]);
const h32 = blake2b(input, 32);
const h64 = blake2b(input, 64);
// First 32 bytes should NOT be the same (different output length affects computation)
assertTrue(bytesToHex(h32) !== bytesToHex(h64).substring(0, 64));
});
// ============================================================
// Keyed Hashing Tests
// ============================================================
console.log('\n--- Keyed Hashing Tests ---');
test('blake2b with key returns different result than without', () => {
const input = new TextEncoder().encode('test');
const key = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
const h1 = blake2b(input, 32);
const h2 = blake2b(input, 32, key);
assertTrue(bytesToHex(h1) !== bytesToHex(h2));
});
test('blake2b with key is deterministic', () => {
const input = new TextEncoder().encode('test');
const key = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
const h1 = blake2b(input, 32, key);
const h2 = blake2b(input, 32, key);
assertEqual(bytesToHex(h1), bytesToHex(h2));
});
test('blake2b with different keys produces different output', () => {
const input = new TextEncoder().encode('test');
const key1 = new Uint8Array([1, 2, 3, 4]);
const key2 = new Uint8Array([1, 2, 3, 5]);
const h1 = blake2b(input, 32, key1);
const h2 = blake2b(input, 32, key2);
assertTrue(bytesToHex(h1) !== bytesToHex(h2));
});
test('blake2b throws for key > 64 bytes', () => {
let threw = false;
try {
blake2b(new Uint8Array(0), 32, new Uint8Array(65));
} catch (e) {
threw = true;
}
assertTrue(threw, 'Should throw for key > 64 bytes');
});
test('blake2b accepts 64-byte key', () => {
const key = new Uint8Array(64);
for (let i = 0; i < 64; i++) key[i] = i;
const hash = blake2b(new TextEncoder().encode('test'), 32, key);
assertLength(hash, 32);
});
// ============================================================
// blake2bHex Tests
// ============================================================
console.log('\n--- blake2bHex Tests ---');
test('blake2bHex returns hex string', () => {
const hash = blake2bHex(new TextEncoder().encode('test'), 32);
assertEqual(typeof hash, 'string');
assertLength(hash, 64); // 32 bytes = 64 hex chars
});
test('blake2bHex matches bytesToHex of blake2b', () => {
const input = new TextEncoder().encode('hello');
const hashBytes = blake2b(input, 32);
const hashHex = blake2bHex(input, 32);
assertEqual(hashHex, bytesToHex(hashBytes));
});
// ============================================================
// Large Input Tests
// ============================================================
console.log('\n--- Large Input Tests ---');
test('blake2b handles input larger than block size (128 bytes)', () => {
const input = new Uint8Array(256);
for (let i = 0; i < 256; i++) input[i] = i & 0xff;
const hash = blake2b(input, 32);
assertLength(hash, 32);
});
test('blake2b handles input exactly one block (128 bytes)', () => {
const input = new Uint8Array(128);
for (let i = 0; i < 128; i++) input[i] = i;
const hash = blake2b(input, 32);
assertLength(hash, 32);
});
test('blake2b handles input of multiple blocks', () => {
const input = new Uint8Array(512);
for (let i = 0; i < 512; i++) input[i] = i & 0xff;
const hash = blake2b(input, 32);
assertLength(hash, 32);
});
// ============================================================
// Additional Test Vectors (from other implementations)
// ============================================================
console.log('\n--- Additional Test Vectors ---');
// Empty input, 32-byte output
test('Empty input, 32-byte output', () => {
const hash = blake2b(new Uint8Array(0), 32);
const expected = '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8';
assertEqual(bytesToHex(hash), expected);
});
// Test with sequential bytes
test('Sequential byte input (0-255)', () => {
const input = new Uint8Array(256);
for (let i = 0; i < 256; i++) input[i] = i;
const hash = blake2b(input, 64);
// This should produce a consistent output (determinism check)
assertLength(hash, 64);
assertTrue(bytesToHex(hash).length === 128);
});
// ============================================================
// Summary
// ============================================================
console.log('\n--- Blake2b Test Summary ---');
console.log(`Passed: ${passed}`);
console.log(`Failed: ${failed}`);
console.log(`Total: ${passed + failed}`);
if (failed > 0) {
console.log('\n⚠️ Some tests failed!');
process.exit(1);
} else {
console.log('\n✓ All blake2b tests passed!');
}