51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
|
|
import { describe, test, expect } from 'bun:test';
|
||
|
|
import { readFileSync } from 'fs';
|
||
|
|
import { join } from 'path';
|
||
|
|
import {
|
||
|
|
deriveBlobSlotId,
|
||
|
|
deriveBlobKey,
|
||
|
|
deriveBlobSigningSeed,
|
||
|
|
} from '../src/crypto/kdf.js';
|
||
|
|
import { ed25519PublicKeyFromSeed } from '@shade/crypto-web';
|
||
|
|
|
||
|
|
function fromHex(s: string): Uint8Array {
|
||
|
|
const out = new Uint8Array(s.length / 2);
|
||
|
|
for (let i = 0; i < out.length; i++) {
|
||
|
|
out[i] = parseInt(s.substr(i * 2, 2), 16);
|
||
|
|
}
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
function toHex(b: Uint8Array): string {
|
||
|
|
let s = '';
|
||
|
|
for (const x of b) s += x.toString(16).padStart(2, '0');
|
||
|
|
return s;
|
||
|
|
}
|
||
|
|
|
||
|
|
describe('V4.9 blob-storage KDF vectors', () => {
|
||
|
|
// Resolve relative to this file, not to cwd, so the test passes
|
||
|
|
// regardless of which directory `bun test` is invoked from.
|
||
|
|
const vectorPath = join(import.meta.dir, '..', '..', '..', 'test-vectors', 'blob-storage.json');
|
||
|
|
const vectors = JSON.parse(readFileSync(vectorPath, 'utf-8')) as {
|
||
|
|
kdf: Array<{
|
||
|
|
masterKey: string;
|
||
|
|
app: string;
|
||
|
|
slotId: string;
|
||
|
|
blobKey: string;
|
||
|
|
signingSeed: string;
|
||
|
|
ownerPubkey: string;
|
||
|
|
}>;
|
||
|
|
};
|
||
|
|
|
||
|
|
for (const v of vectors.kdf) {
|
||
|
|
test(`(master=${v.masterKey.slice(0, 8)}…, app=${v.app})`, () => {
|
||
|
|
const km = fromHex(v.masterKey);
|
||
|
|
expect(toHex(deriveBlobSlotId(km, v.app))).toBe(v.slotId);
|
||
|
|
expect(toHex(deriveBlobKey(km, v.app))).toBe(v.blobKey);
|
||
|
|
const seed = deriveBlobSigningSeed(km, v.app);
|
||
|
|
expect(toHex(seed)).toBe(v.signingSeed);
|
||
|
|
expect(toHex(ed25519PublicKeyFromSeed(seed))).toBe(v.ownerPubkey);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|