feat: release OTP and Passkey Tools 0.1.0
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
bytesToArrayBuffer,
|
||||
bytesToHex,
|
||||
utf8ToBytes,
|
||||
} from "../../src/crypto/encoding";
|
||||
import { encodeQr, qrSvg } from "../../src/qr/encoder";
|
||||
|
||||
async function matrixHash(text: string): Promise<string> {
|
||||
const bits = encodeQr(text)
|
||||
.map((row) => row.map((value) => (value ? "1" : "0")).join(""))
|
||||
.join("");
|
||||
return bytesToHex(
|
||||
new Uint8Array(
|
||||
await crypto.subtle.digest(
|
||||
"SHA-256",
|
||||
bytesToArrayBuffer(utf8ToBytes(bits)),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
describe("QR encoder", () => {
|
||||
it("matches the reviewed reference matrices", async () => {
|
||||
await expect(matrixHash("Hello")).resolves.toBe(
|
||||
"ac69828947e29c188c38459b3eab69d0071aeedc825c41277d82ca3141033afe",
|
||||
);
|
||||
await expect(
|
||||
matrixHash(
|
||||
"otpauth://totp/Example:alice?secret=JBSWY3DPEHPK3PXP&issuer=Example",
|
||||
),
|
||||
).resolves.toBe(
|
||||
"d39d6eed126c0bc3ca92a851a062613e8cfa178adf9a8e2b3c399ba77cbb0187",
|
||||
);
|
||||
});
|
||||
|
||||
it("emits a self-contained SVG with a quiet zone", () => {
|
||||
const svg = qrSvg("Hello");
|
||||
expect(svg).toMatch(/^<svg xmlns=/u);
|
||||
expect(svg).toContain("<rect");
|
||||
expect(svg).not.toContain("script");
|
||||
});
|
||||
|
||||
it("rejects oversized values instead of allocating unbounded matrices", () => {
|
||||
expect(() => encodeQr("x".repeat(500))).toThrow(/version 10/iu);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user