UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

213 lines (161 loc) β€’ 7.19 kB
import { Alepha } from "alepha"; import { describe, expect, it } from "vitest"; import { CryptoProvider } from "../providers/CryptoProvider.ts"; describe("CryptoProvider", () => { it("should hash and verify a password", async () => { const crypto = Alepha.create().inject(CryptoProvider); const hash = await crypto.hashPassword("secret123"); expect(hash).toContain(":"); expect(await crypto.verifyPassword("secret123", hash)).toBe(true); }); it("should reject wrong password", async () => { const crypto = Alepha.create().inject(CryptoProvider); const hash = await crypto.hashPassword("correct"); expect(await crypto.verifyPassword("wrong", hash)).toBe(false); }); it("should produce different hashes for same password", async () => { const crypto = Alepha.create().inject(CryptoProvider); const hash1 = await crypto.hashPassword("same"); const hash2 = await crypto.hashPassword("same"); expect(hash1).not.toEqual(hash2); }); it("should reject invalid stored hash formats", async () => { const crypto = Alepha.create().inject(CryptoProvider); expect(await crypto.verifyPassword("any", "")).toBe(false); expect(await crypto.verifyPassword("any", "nocolon")).toBe(false); expect(await crypto.verifyPassword("any", "a:b:c")).toBe(false); expect(await crypto.verifyPassword("any", ":hash")).toBe(false); expect(await crypto.verifyPassword("any", "salt:")).toBe(false); expect(await crypto.verifyPassword("any", "salt:invalidhex!")).toBe(false); expect(await crypto.verifyPassword("any", "salt:abc")).toBe(false); // odd-length hex }); it("should generate a valid UUID", () => { const crypto = Alepha.create().inject(CryptoProvider); const uuid = crypto.randomUUID(); expect(uuid).toMatch( /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, ); }); it("should generate unique UUIDs", () => { const crypto = Alepha.create().inject(CryptoProvider); const a = crypto.randomUUID(); const b = crypto.randomUUID(); expect(a).not.toEqual(b); }); it("should generate random text of requested length", () => { const crypto = Alepha.create().inject(CryptoProvider); expect(crypto.randomText(16)).toHaveLength(16); expect(crypto.randomText(32)).toHaveLength(32); expect(crypto.randomText(1)).toHaveLength(1); }); it("should generate unique random text", () => { const crypto = Alepha.create().inject(CryptoProvider); const a = crypto.randomText(32); const b = crypto.randomText(32); expect(a).not.toEqual(b); }); it("should generate url-safe random text", () => { const crypto = Alepha.create().inject(CryptoProvider); const text = crypto.randomText(100); expect(text).toMatch(/^[A-Za-z0-9_-]+$/); }); it("should produce a deterministic sha256 hash", () => { const crypto = Alepha.create().inject(CryptoProvider); const a = crypto.hash("hello"); const b = crypto.hash("hello"); expect(a).toEqual(b); expect(a).toHaveLength(64); // 256 bits = 64 hex chars }); it("should produce different hashes for different inputs", () => { const crypto = Alepha.create().inject(CryptoProvider); expect(crypto.hash("a")).not.toEqual(crypto.hash("b")); }); it("should support alternative hash algorithms", () => { const crypto = Alepha.create().inject(CryptoProvider); const sha512 = crypto.hash("hello", "sha512"); expect(sha512).toHaveLength(128); // 512 bits = 128 hex chars }); it("should produce a deterministic hmac", () => { const crypto = Alepha.create().inject(CryptoProvider); const a = crypto.hmac("payload", "secret"); const b = crypto.hmac("payload", "secret"); expect(a).toEqual(b); expect(a).toHaveLength(64); }); it("should produce different hmacs for different secrets", () => { const crypto = Alepha.create().inject(CryptoProvider); const a = crypto.hmac("payload", "key1"); const b = crypto.hmac("payload", "key2"); expect(a).not.toEqual(b); }); it("should verify a valid hmac", () => { const crypto = Alepha.create().inject(CryptoProvider); const sig = crypto.hmac("data", "secret"); expect(crypto.verifyHmac("data", sig, "secret")).toBe(true); }); it("should reject an invalid hmac", () => { const crypto = Alepha.create().inject(CryptoProvider); const sig = crypto.hmac("data", "secret"); expect(crypto.verifyHmac("tampered", sig, "secret")).toBe(false); expect(crypto.verifyHmac("data", "badsig", "secret")).toBe(false); expect(crypto.verifyHmac("data", sig, "wrongkey")).toBe(false); }); it("should encrypt and decrypt a string", () => { const crypto = Alepha.create().inject(CryptoProvider); const encrypted = crypto.encrypt("hello world", "mykey"); expect(encrypted).toContain(":"); expect(encrypted).not.toContain("hello"); const decrypted = crypto.decrypt(encrypted, "mykey"); expect(decrypted).toEqual("hello world"); }); it("should produce different ciphertexts for same plaintext", () => { const crypto = Alepha.create().inject(CryptoProvider); const a = crypto.encrypt("same", "key"); const b = crypto.encrypt("same", "key"); expect(a).not.toEqual(b); }); it("should fail to decrypt with wrong key", () => { const crypto = Alepha.create().inject(CryptoProvider); const encrypted = crypto.encrypt("secret", "correct"); expect(() => crypto.decrypt(encrypted, "wrong")).toThrow(); }); it("should fail to decrypt invalid ciphertext format", () => { const crypto = Alepha.create().inject(CryptoProvider); expect(() => crypto.decrypt("invalid", "key")).toThrow( "Invalid ciphertext format", ); }); it("should handle unicode in encrypt/decrypt", () => { const crypto = Alepha.create().inject(CryptoProvider); const plaintext = "Hello δΈ–η•Œ 🌍"; const encrypted = crypto.encrypt(plaintext, "key"); expect(crypto.decrypt(encrypted, "key")).toEqual(plaintext); }); it("should compare strings in constant time", () => { const crypto = Alepha.create().inject(CryptoProvider); expect(crypto.equals("abc", "abc")).toBe(true); expect(crypto.equals("abc", "xyz")).toBe(false); expect(crypto.equals("short", "longer")).toBe(false); }); it("should generate numeric codes of requested length", () => { const crypto = Alepha.create().inject(CryptoProvider); const code = crypto.randomCode(6); expect(code).toHaveLength(6); expect(code).toMatch(/^\d{6}$/); }); it("should pad short codes with leading zeros", () => { const crypto = Alepha.create().inject(CryptoProvider); // Run enough times to statistically hit a code starting with 0 const codes = Array.from({ length: 100 }, () => crypto.randomCode(6)); for (const code of codes) { expect(code).toHaveLength(6); expect(code).toMatch(/^\d{6}$/); } }); it("should generate single-digit codes", () => { const crypto = Alepha.create().inject(CryptoProvider); const code = crypto.randomCode(1); expect(code).toHaveLength(1); expect(code).toMatch(/^\d$/); }); });