@zaeniahmad/kpwgen
Version:
Deterministic password generation core logic
116 lines (82 loc) โข 2.75 kB
Markdown
# @zaeniahmad/kpwgen
Generate **secure, reproducible passwords** with absolute consistency. As long as your inputs remain the same, the result is **bit-identical**. Works **100% offline**, no telemetry, no network calls.
## โจ Features
* **Deterministic**: Same input โ same output, always.
* **Cryptographically secure**: HMAC-based derivation (SHA-2).
* **Offline**: No external requests.
* **Configurable**: Prefix, suffix, target length, normalization.
* **Isomorphic**: Works in Node.js and Browser.
* **No storage**: Does not save secrets or passwords.
## ๐ฆ Installation
```bash
npm install @zaeniahmad/kpwgen
# or
yarn add @zaeniahmad/kpwgen
# or
pnpm add @zaeniahmad/kpwgen
```
## โก๏ธ Quick Start
**ESM (Node.js / Browser)**
```ts
import { generatePassword } from "@zaeniahmad/kpwgen";
const pwd = await generatePassword({
masterSecret: process.env.MASTER_SECRET!,
platform: "google",
version: 1,
lengthTarget: 18,
prefix: "Qx9",
suffix: "K7",
normalize: true,
});
console.log(pwd);
```
## ๐ง How It Works
1. **Normalize**: Clean `platform` input.
2. **Derive**: Create message from `{platform, version}`.
3. **HMAC**: Compute SHA-256 HMAC with `masterSecret`.
4. **Encode**: Convert digest to base32/charset.
5. **Shape**: Apply length, prefix, suffix.
## ๐งฉ API
### `generatePassword(options: GenOptions): Promise<string>`
**Options**
* `masterSecret: string` โ Required.
* `platform: string` โ Required.
* `version?: number` โ Default `1`.
* `prefix?: string`
* `suffix?: string`
* `lengthTarget?: number` โ Default `18`.
* `normalize?: boolean` โ Default `true`.
**Utilities**
* `normalizePlatform(raw: string): string`
* `toBase32(buf: Uint8Array): string`
## ๐ Security Best Practices
* Never hardcode `masterSecret`.
* Use `version` for rotation.
* Add policy rules for site-specific requirements.
* Avoid storing secrets in local storage.
## ๐งช Testing
```bash
npm run lint
npm test
```
Example:
```ts
import { generatePassword } from "@zaeniahmad/kpwgen";
import { describe, it, expect } from "vitest";
describe("deterministic", () => {
it("same input, same output", async () => {
const a = await generatePassword({ masterSecret: "a", platform: "github", version: 1 });
const b = await generatePassword({ masterSecret: "a", platform: "github", version: 1 });
expect(a).toBe(b);
});
});
```
## ๐ FAQ
**Why not use a normal password manager?**
> Stateless & reproducible. No sync needed.
**Does it work offline?**
> Yes.
**Can I enforce special characters?**
> Yes, via prefix/suffix or post-processing.
## ๐ License
ISC