feat: release OTP and Passkey Tools 0.1.0
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
exportCsv,
|
||||
importCsv,
|
||||
importOtpAuthList,
|
||||
importPlainPskc,
|
||||
} from "../../src/otp/migration";
|
||||
import { utf8ToBytes } from "../../src/crypto/encoding";
|
||||
import type { OtpProfile } from "../../src/otp/profile";
|
||||
|
||||
const profile: OtpProfile = {
|
||||
kind: "totp",
|
||||
account: 'alice,"admin"',
|
||||
issuer: "Example",
|
||||
secret: utf8ToBytes("12345678901234567890"),
|
||||
algorithm: "SHA-256",
|
||||
digits: 8,
|
||||
period: 45,
|
||||
counter: 0n,
|
||||
extensions: new Map(),
|
||||
};
|
||||
|
||||
describe("OTP migrations", () => {
|
||||
it("round-trips the documented CSV including quoting", () => {
|
||||
const result = importCsv(exportCsv([profile]));
|
||||
expect(result.profiles[0]).toMatchObject({
|
||||
account: profile.account,
|
||||
issuer: "Example",
|
||||
algorithm: "SHA-256",
|
||||
digits: 8,
|
||||
period: 45,
|
||||
});
|
||||
expect([...result.profiles[0]!.secret]).toEqual([...profile.secret]);
|
||||
});
|
||||
|
||||
it("neutralizes spreadsheet formulas without changing a round trip", () => {
|
||||
const dangerous = { ...profile, account: '=HYPERLINK("https://bad")' };
|
||||
const csv = exportCsv([dangerous]);
|
||||
expect(csv).toContain("'=HYPERLINK");
|
||||
expect(importCsv(csv).profiles[0]!.account).toBe(dangerous.account);
|
||||
});
|
||||
|
||||
it("reports the failing line in URI lists", () => {
|
||||
expect(() =>
|
||||
importOtpAuthList("otpauth://totp/Good?secret=JBSWY3DPEHPK3PXP\nnope"),
|
||||
).toThrow(/Line 2/iu);
|
||||
});
|
||||
|
||||
it("imports plain-secret PSKC and refuses encrypted keys", () => {
|
||||
const xml = `<KeyContainer xmlns="urn:ietf:params:xml:ns:keyprov:pskc"><KeyPackage><Key Id="alice" Algorithm="urn:ietf:params:xml:ns:keyprov:pskc:totp"><Issuer>Example</Issuer><Data><Secret><PlainValue>MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=</PlainValue></Secret><TimeInterval><PlainValue>30</PlainValue></TimeInterval></Data><Policy><KeyUsage>OTP</KeyUsage></Policy><ResponseFormat Length="6" Encoding="DECIMAL"/></Key></KeyPackage></KeyContainer>`;
|
||||
expect(importPlainPskc(xml).profiles[0]).toMatchObject({
|
||||
kind: "totp",
|
||||
account: "alice",
|
||||
issuer: "Example",
|
||||
digits: 6,
|
||||
});
|
||||
expect(() =>
|
||||
importPlainPskc(
|
||||
xml.replace(
|
||||
"<PlainValue>MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=</PlainValue>",
|
||||
"<EncryptedValue/>",
|
||||
),
|
||||
),
|
||||
).toThrow(/encrypted/iu);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user