credvault 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +49 -0
- package/dist/audit.d.ts +23 -0
- package/dist/audit.js +29 -0
- package/dist/audit.js.map +1 -0
- package/dist/canary.d.ts +30 -0
- package/dist/canary.js +44 -0
- package/dist/canary.js.map +1 -0
- package/dist/chain.d.ts +26 -0
- package/dist/chain.js +117 -0
- package/dist/chain.js.map +1 -0
- package/dist/cipher.d.ts +26 -0
- package/dist/cipher.js +103 -0
- package/dist/cipher.js.map +1 -0
- package/dist/credentials.d.ts +106 -0
- package/dist/credentials.js +314 -0
- package/dist/credentials.js.map +1 -0
- package/dist/env-store.d.ts +61 -0
- package/dist/env-store.js +288 -0
- package/dist/env-store.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/passwords.d.ts +2 -0
- package/dist/passwords.js +19 -0
- package/dist/passwords.js.map +1 -0
- package/dist/secrets.d.ts +17 -0
- package/dist/secrets.js +37 -0
- package/dist/secrets.js.map +1 -0
- package/dist/tail.d.ts +4 -0
- package/dist/tail.js +56 -0
- package/dist/tail.js.map +1 -0
- package/dist/totp.d.ts +24 -0
- package/dist/totp.js +111 -0
- package/dist/totp.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place a secret lives across machines: SSM Parameter Store, one
|
|
3
|
+
* SecureString per name under the app's path (`/myapp/config/NAME`). KMS
|
|
4
|
+
* at rest, IAM at the door, every read in CloudTrail. Values never enter
|
|
5
|
+
* argv, logs or errors.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { DeleteParameterCommand, DescribeParametersCommand, GetParameterCommand, GetParametersByPathCommand, ParameterNotFound, PutParameterCommand, } from "@aws-sdk/client-ssm";
|
|
10
|
+
/** SSM throttles writes at a few a second; a push of thirty keys backs off and goes on rather than dying. */
|
|
11
|
+
async function patient(call, sleep = (ms) => new Promise((r) => setTimeout(r, ms))) {
|
|
12
|
+
for (let attempt = 0;; attempt++) {
|
|
13
|
+
try {
|
|
14
|
+
return await call();
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
const throttled = err instanceof Error &&
|
|
18
|
+
(err.name === "ThrottlingException" || /Rate exceeded/i.test(err.message));
|
|
19
|
+
if (!throttled || attempt >= 8)
|
|
20
|
+
throw err;
|
|
21
|
+
await sleep(200 * 2 ** attempt);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export const ENV_KEY = /^[A-Z][A-Z0-9_]*$/;
|
|
26
|
+
/**
|
|
27
|
+
* Entries that stop working within `withinMs` of `now` (already expired
|
|
28
|
+
* included), soonest first: what a watcher re-mints.
|
|
29
|
+
*/
|
|
30
|
+
export function expiring(entries, withinMs, now = Date.now()) {
|
|
31
|
+
return entries
|
|
32
|
+
.filter((e) => e.expiresAt !== null && Date.parse(e.expiresAt) - now <= withinMs)
|
|
33
|
+
.sort((a, b) => (a.expiresAt ?? "").localeCompare(b.expiresAt ?? ""));
|
|
34
|
+
}
|
|
35
|
+
/** SSM keeps expiry in the parameter's description, which reads without decrypting. */
|
|
36
|
+
const EXPIRES = "expires ";
|
|
37
|
+
const describe = (o = {}) => o.expiresAt ? `${EXPIRES}${new Date(o.expiresAt).toISOString()}` : "no expiry";
|
|
38
|
+
const expiryOf = (description) => description?.startsWith(EXPIRES) ? description.slice(EXPIRES.length) : null;
|
|
39
|
+
/** SSM under `prefix`: `/prefix/NAME`. The client comes in so tests pass a fake. */
|
|
40
|
+
export function ssmEnvStore(ssm, prefix) {
|
|
41
|
+
const path = (name) => {
|
|
42
|
+
if (!ENV_KEY.test(name))
|
|
43
|
+
throw new Error(`env store: bad name ${name}`);
|
|
44
|
+
return `${prefix}/${name}`;
|
|
45
|
+
};
|
|
46
|
+
const nameOf = (p) => p?.slice(prefix.length + 1) ?? "";
|
|
47
|
+
const byName = (rows) => rows.sort((a, b) => a.name.localeCompare(b.name));
|
|
48
|
+
return {
|
|
49
|
+
async list() {
|
|
50
|
+
const out = [];
|
|
51
|
+
let next;
|
|
52
|
+
do {
|
|
53
|
+
const r = await patient(() => ssm.send(new DescribeParametersCommand({
|
|
54
|
+
ParameterFilters: [{ Key: "Path", Option: "OneLevel", Values: [prefix] }],
|
|
55
|
+
NextToken: next,
|
|
56
|
+
})));
|
|
57
|
+
for (const p of r.Parameters ?? [])
|
|
58
|
+
out.push({
|
|
59
|
+
name: nameOf(p.Name),
|
|
60
|
+
updatedAt: p.LastModifiedDate?.toISOString() ?? null,
|
|
61
|
+
expiresAt: expiryOf(p.Description),
|
|
62
|
+
});
|
|
63
|
+
next = r.NextToken;
|
|
64
|
+
} while (next);
|
|
65
|
+
return byName(out);
|
|
66
|
+
},
|
|
67
|
+
async all() {
|
|
68
|
+
const out = [];
|
|
69
|
+
let next;
|
|
70
|
+
do {
|
|
71
|
+
const r = await patient(() => ssm.send(new GetParametersByPathCommand({
|
|
72
|
+
Path: prefix,
|
|
73
|
+
Recursive: false,
|
|
74
|
+
WithDecryption: true,
|
|
75
|
+
NextToken: next,
|
|
76
|
+
})));
|
|
77
|
+
for (const p of r.Parameters ?? [])
|
|
78
|
+
out.push({ name: nameOf(p.Name), value: p.Value ?? "" });
|
|
79
|
+
next = r.NextToken;
|
|
80
|
+
} while (next);
|
|
81
|
+
return byName(out);
|
|
82
|
+
},
|
|
83
|
+
async get(name) {
|
|
84
|
+
try {
|
|
85
|
+
const r = await ssm.send(new GetParameterCommand({ Name: path(name), WithDecryption: true }));
|
|
86
|
+
return r.Parameter?.Value ?? null;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
if (err instanceof ParameterNotFound)
|
|
90
|
+
return null;
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
async put(name, value, o) {
|
|
95
|
+
if (!value)
|
|
96
|
+
throw new Error(`env store: ${name} is empty`);
|
|
97
|
+
await patient(() => ssm.send(new PutParameterCommand({
|
|
98
|
+
Name: path(name),
|
|
99
|
+
Value: value,
|
|
100
|
+
// Always said, so a re-mint without an expiry clears the old one.
|
|
101
|
+
Description: describe(o),
|
|
102
|
+
Type: "SecureString",
|
|
103
|
+
// Past 4 KB (a service-account JSON) SSM needs the advanced tier; this picks it only then.
|
|
104
|
+
Tier: "Intelligent-Tiering",
|
|
105
|
+
Overwrite: true,
|
|
106
|
+
})));
|
|
107
|
+
},
|
|
108
|
+
async remove(name) {
|
|
109
|
+
try {
|
|
110
|
+
await ssm.send(new DeleteParameterCommand({ Name: path(name) }));
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
if (err instanceof ParameterNotFound)
|
|
115
|
+
return false;
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
export function memoryEnvStore(initial = {}) {
|
|
122
|
+
const values = { ...initial };
|
|
123
|
+
const expires = new Map();
|
|
124
|
+
return {
|
|
125
|
+
values,
|
|
126
|
+
list: async () => Object.keys(values)
|
|
127
|
+
.sort()
|
|
128
|
+
.map((name) => ({ name, updatedAt: null, expiresAt: expiryOf(expires.get(name)) })),
|
|
129
|
+
all: async () => Object.entries(values)
|
|
130
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
131
|
+
.map(([name, value]) => ({ name, value })),
|
|
132
|
+
get: async (name) => values[name] ?? null,
|
|
133
|
+
async put(name, value, o) {
|
|
134
|
+
if (!ENV_KEY.test(name))
|
|
135
|
+
throw new Error(`env store: bad name ${name}`);
|
|
136
|
+
values[name] = value;
|
|
137
|
+
expires.set(name, describe(o));
|
|
138
|
+
},
|
|
139
|
+
async remove(name) {
|
|
140
|
+
const had = name in values;
|
|
141
|
+
delete values[name];
|
|
142
|
+
expires.delete(name);
|
|
143
|
+
return had;
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** The comment above a line that says when its value stops working: `# NAME expires <ISO>`. */
|
|
148
|
+
const EXPIRY_LINE = /^# ([A-Z][A-Z0-9_]*) expires (\S+)$/;
|
|
149
|
+
/**
|
|
150
|
+
* A local `.env` as a store: 0600, one line per name, other lines untouched.
|
|
151
|
+
* Expiry is a comment directly above the line, so a person reading the file
|
|
152
|
+
* sees it too. A put also sets `env[name]`, so this process sees the value.
|
|
153
|
+
*/
|
|
154
|
+
export function envFileStore(path, env = process.env) {
|
|
155
|
+
const file = path.startsWith("~/") ? `${homedir()}${path.slice(1)}` : path;
|
|
156
|
+
const text = () => (existsSync(file) ? readFileSync(file, "utf8") : "");
|
|
157
|
+
const lines = () => {
|
|
158
|
+
const out = text().split("\n");
|
|
159
|
+
if (out.at(-1) === "")
|
|
160
|
+
out.pop();
|
|
161
|
+
return out;
|
|
162
|
+
};
|
|
163
|
+
const write = (out) => {
|
|
164
|
+
const tmp = `${file}.tmp`;
|
|
165
|
+
writeFileSync(tmp, out.length ? `${out.join("\n")}\n` : "", { mode: 0o600 });
|
|
166
|
+
renameSync(tmp, file);
|
|
167
|
+
};
|
|
168
|
+
/** The file without `name`'s line and expiry comment; where the line was, or -1. */
|
|
169
|
+
const without = (name) => {
|
|
170
|
+
const out = [];
|
|
171
|
+
let at = -1;
|
|
172
|
+
for (const l of lines()) {
|
|
173
|
+
if (EXPIRY_LINE.exec(l)?.[1] === name)
|
|
174
|
+
continue;
|
|
175
|
+
if (l.startsWith(`${name}=`)) {
|
|
176
|
+
at = out.length;
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
out.push(l);
|
|
180
|
+
}
|
|
181
|
+
return { out, at };
|
|
182
|
+
};
|
|
183
|
+
return {
|
|
184
|
+
async list() {
|
|
185
|
+
const expires = new Map();
|
|
186
|
+
for (const l of lines()) {
|
|
187
|
+
const m = EXPIRY_LINE.exec(l);
|
|
188
|
+
if (m?.[1] && m[2])
|
|
189
|
+
expires.set(m[1], m[2]);
|
|
190
|
+
}
|
|
191
|
+
return parseDotenv(text()).map(({ name }) => ({
|
|
192
|
+
name,
|
|
193
|
+
updatedAt: null,
|
|
194
|
+
expiresAt: expires.get(name) ?? null,
|
|
195
|
+
}));
|
|
196
|
+
},
|
|
197
|
+
all: async () => parseDotenv(text()),
|
|
198
|
+
get: async (name) => parseDotenv(text()).find((e) => e.name === name)?.value ?? null,
|
|
199
|
+
async put(name, value, o) {
|
|
200
|
+
if (!ENV_KEY.test(name))
|
|
201
|
+
throw new Error(`env file: bad name ${name}`);
|
|
202
|
+
if (/[\r\n]/.test(value))
|
|
203
|
+
throw new Error(`env file: ${name} spans lines`);
|
|
204
|
+
const { out, at } = without(name);
|
|
205
|
+
const add = [...(o?.expiresAt ? [`# ${name} ${describe(o)}`] : []), `${name}=${value}`];
|
|
206
|
+
out.splice(at < 0 ? out.length : at, 0, ...add);
|
|
207
|
+
write(out);
|
|
208
|
+
env[name] = value;
|
|
209
|
+
},
|
|
210
|
+
async remove(name) {
|
|
211
|
+
const { out, at } = without(name);
|
|
212
|
+
if (at < 0)
|
|
213
|
+
return false;
|
|
214
|
+
write(out);
|
|
215
|
+
delete env[name];
|
|
216
|
+
return true;
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* `KEY=VALUE` lines → entries. Comments, blanks and quotes as a shell would
|
|
222
|
+
* read them; a value naming a readable file whose content is JSON (a
|
|
223
|
+
* service account) is inlined so the store holds the secret, not a path.
|
|
224
|
+
*/
|
|
225
|
+
export function parseDotenv(text, readFile) {
|
|
226
|
+
const out = [];
|
|
227
|
+
for (const raw of text.split("\n")) {
|
|
228
|
+
const line = raw.trim();
|
|
229
|
+
if (!line || line.startsWith("#") || !line.includes("="))
|
|
230
|
+
continue;
|
|
231
|
+
const i = line.indexOf("=");
|
|
232
|
+
const name = line
|
|
233
|
+
.slice(0, i)
|
|
234
|
+
.trim()
|
|
235
|
+
.replace(/^export\s+/, "");
|
|
236
|
+
let value = line.slice(i + 1).trim();
|
|
237
|
+
const q = value[0];
|
|
238
|
+
if (q === '"' || q === "'") {
|
|
239
|
+
const end = value.indexOf(q, 1);
|
|
240
|
+
value = end > 0 ? value.slice(1, end) : value.slice(1);
|
|
241
|
+
}
|
|
242
|
+
else
|
|
243
|
+
value = value.replace(/\s+#.*$/, "");
|
|
244
|
+
if (!ENV_KEY.test(name) || !value)
|
|
245
|
+
continue;
|
|
246
|
+
if (readFile && !value.trimStart().startsWith("{") && /\.json$/.test(value)) {
|
|
247
|
+
const inlined = readFile(value);
|
|
248
|
+
if (inlined?.trimStart().startsWith("{"))
|
|
249
|
+
value = inlined;
|
|
250
|
+
}
|
|
251
|
+
out.push({ name, value });
|
|
252
|
+
}
|
|
253
|
+
return out;
|
|
254
|
+
}
|
|
255
|
+
/** Entries → `KEY=VALUE` lines. A multi-line value cannot live in one line: `files` takes it and the line names the path. */
|
|
256
|
+
export function toDotenv(entries, files) {
|
|
257
|
+
return `${entries
|
|
258
|
+
.map(({ name, value }) => {
|
|
259
|
+
if (!/[\r\n]/.test(value))
|
|
260
|
+
return `${name}=${value}`;
|
|
261
|
+
if (!files)
|
|
262
|
+
throw new Error(`${name} spans lines; give it a file`);
|
|
263
|
+
return `${name}=${files(name, value)}`;
|
|
264
|
+
})
|
|
265
|
+
.join("\n")}\n`;
|
|
266
|
+
}
|
|
267
|
+
/** Entries → `export KEY='…'` lines for `eval "$(…)"`; single quotes are the one thing escaped. */
|
|
268
|
+
export function toExports(entries) {
|
|
269
|
+
return `${entries
|
|
270
|
+
.map(({ name, value }) => `export ${name}='${value.replace(/'/g, `'\\''`)}'`)
|
|
271
|
+
.join("\n")}\n`;
|
|
272
|
+
}
|
|
273
|
+
/** Upsert `entries` into an env file's text; other lines untouched. */
|
|
274
|
+
export function upsertDotenv(text, entries) {
|
|
275
|
+
const lines = text.split("\n");
|
|
276
|
+
if (lines.at(-1) === "")
|
|
277
|
+
lines.pop();
|
|
278
|
+
for (const { name, value } of entries) {
|
|
279
|
+
const line = `${name}=${value}`;
|
|
280
|
+
const i = lines.findIndex((l) => l.startsWith(`${name}=`));
|
|
281
|
+
if (i >= 0)
|
|
282
|
+
lines[i] = line;
|
|
283
|
+
else
|
|
284
|
+
lines.push(line);
|
|
285
|
+
}
|
|
286
|
+
return `${lines.join("\n")}\n`;
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=env-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-store.js","sourceRoot":"","sources":["../src/env-store.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { fileAudit, memoryAudit, type SecretAudit, type SecretUse } from "./audit.js";
|
|
2
|
+
export { type CanaryOptions, CanaryTripped, canaryCredential, canaryStore, isCanary, } from "./canary.js";
|
|
3
|
+
export { type Chained, type ChainedFile, chainedFile, rowHash, type Verification, verifyChain, } from "./chain.js";
|
|
4
|
+
export { aesGcmCipher, type Cipher, isSealed, type KeychainItem, keychainKey, plainCipher, trustKeychainKey, } from "./cipher.js";
|
|
5
|
+
export { CREDENTIAL_ENV_FIELDS, type Credential, type CredentialEnvStore, type CredentialInput, type CredentialStore, credentialEnv, credentialEnvName, credentialSchema, type EnvNaming, envCredentials, fileCredentials, layeredCredentials, memoryCredentials, mirroredCredentials, pullCredentials, pushCredentials, } from "./credentials.js";
|
|
6
|
+
export { ENV_KEY, type EnvEntry, type EnvListing, type EnvStore, envFileStore, expiring, memoryEnvStore, type PutOptions, parseDotenv, ssmEnvStore, toDotenv, toExports, upsertDotenv, } from "./env-store.js";
|
|
7
|
+
export { newPassword } from "./passwords.js";
|
|
8
|
+
export { envSecrets, memorySecrets, type SecretSource, type TrackingSecrets, trackingSecrets, } from "./secrets.js";
|
|
9
|
+
export { tailJson, tailLines } from "./tail.js";
|
|
10
|
+
export { base32Decode, findTotpSecret, parseOtpauth, type TotpAlgorithm, type TotpOptions, type TotpParams, totp, totpRemainingMs, } from "./totp.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { fileAudit, memoryAudit } from "./audit.js";
|
|
2
|
+
export { CanaryTripped, canaryCredential, canaryStore, isCanary, } from "./canary.js";
|
|
3
|
+
export { chainedFile, rowHash, verifyChain, } from "./chain.js";
|
|
4
|
+
export { aesGcmCipher, isSealed, keychainKey, plainCipher, trustKeychainKey, } from "./cipher.js";
|
|
5
|
+
export { CREDENTIAL_ENV_FIELDS, credentialEnv, credentialEnvName, credentialSchema, envCredentials, fileCredentials, layeredCredentials, memoryCredentials, mirroredCredentials, pullCredentials, pushCredentials, } from "./credentials.js";
|
|
6
|
+
export { ENV_KEY, envFileStore, expiring, memoryEnvStore, parseDotenv, ssmEnvStore, toDotenv, toExports, upsertDotenv, } from "./env-store.js";
|
|
7
|
+
export { newPassword } from "./passwords.js";
|
|
8
|
+
export { envSecrets, memorySecrets, trackingSecrets, } from "./secrets.js";
|
|
9
|
+
export { tailJson, tailLines } from "./tail.js";
|
|
10
|
+
export { base32Decode, findTotpSecret, parseOtpauth, totp, totpRemainingMs, } from "./totp.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAoC,MAAM,YAAY,CAAC;AACtF,OAAO,EAEL,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,QAAQ,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EAGL,WAAW,EACX,OAAO,EAEP,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,YAAY,EAEZ,QAAQ,EAER,WAAW,EACX,WAAW,EACX,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EAKrB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAEhB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,OAAO,EAIP,YAAY,EACZ,QAAQ,EACR,cAAc,EAEd,WAAW,EACX,WAAW,EACX,QAAQ,EACR,SAAS,EACT,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EACL,UAAU,EACV,aAAa,EAGb,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EACL,YAAY,EACZ,cAAc,EACd,YAAY,EAIZ,IAAI,EACJ,eAAe,GAChB,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Passwords drawn here: nobody picks them, nobody sees them. */
|
|
2
|
+
import { randomInt } from "node:crypto";
|
|
3
|
+
const LOWER = "abcdefghijkmnopqrstuvwxyz";
|
|
4
|
+
const UPPER = "ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
5
|
+
const DIGIT = "23456789";
|
|
6
|
+
const SYMBOL = "!@#$%^&*-_=+";
|
|
7
|
+
const ALL = LOWER + UPPER + DIGIT + SYMBOL;
|
|
8
|
+
/** A password no site refuses: 24 chars, at least one of each class, no look-alikes (l/1/O/0). */
|
|
9
|
+
export function newPassword(length = 24, pick = randomInt) {
|
|
10
|
+
const chars = [LOWER, UPPER, DIGIT, SYMBOL].map((set) => set[pick(set.length)] ?? "a");
|
|
11
|
+
while (chars.length < length)
|
|
12
|
+
chars.push(ALL[pick(ALL.length)] ?? "a");
|
|
13
|
+
for (let i = chars.length - 1; i > 0; i--) {
|
|
14
|
+
const j = pick(i + 1);
|
|
15
|
+
[chars[i], chars[j]] = [chars[j], chars[i]];
|
|
16
|
+
}
|
|
17
|
+
return chars.join("");
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=passwords.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passwords.js","sourceRoot":"","sources":["../src/passwords.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,KAAK,GAAG,2BAA2B,CAAC;AAC1C,MAAM,KAAK,GAAG,0BAA0B,CAAC;AACzC,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,MAAM,GAAG,cAAc,CAAC;AAC9B,MAAM,GAAG,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3C,kGAAkG;AAClG,MAAM,UAAU,WAAW,CAAC,MAAM,GAAG,EAAE,EAAE,OAA8B,SAAS;IAC9E,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IACvF,OAAO,KAAK,CAAC,MAAM,GAAG,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IACvE,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAW,EAAE,KAAK,CAAC,CAAC,CAAW,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One named value, asked for by key at the moment it is needed (a card
|
|
3
|
+
* number, an API key), never carried on a plan or in a log. Env is the
|
|
4
|
+
* default source; the shared store (env-store.ts) is another.
|
|
5
|
+
*/
|
|
6
|
+
export interface SecretSource {
|
|
7
|
+
get(key: string): Promise<string>;
|
|
8
|
+
}
|
|
9
|
+
/** A key in camelCase (`cardCvv`) → `SECRET_CARD_CVV` in the environment, under the app's prefix. */
|
|
10
|
+
export declare function envSecrets(env?: NodeJS.ProcessEnv, prefix?: string): SecretSource;
|
|
11
|
+
export declare function memorySecrets(values: Record<string, string>): SecretSource;
|
|
12
|
+
/** A secret source that remembers what it handed out, so a caller can tell a secret's value from any other. */
|
|
13
|
+
export interface TrackingSecrets extends SecretSource {
|
|
14
|
+
/** The key a value was handed out under, or null. */
|
|
15
|
+
keyOf(value: string): string | null;
|
|
16
|
+
}
|
|
17
|
+
export declare function trackingSecrets(source: SecretSource): TrackingSecrets;
|
package/dist/secrets.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** A key in camelCase (`cardCvv`) → `SECRET_CARD_CVV` in the environment, under the app's prefix. */
|
|
2
|
+
export function envSecrets(env = process.env, prefix = "SECRET_") {
|
|
3
|
+
return {
|
|
4
|
+
async get(key) {
|
|
5
|
+
const name = `${prefix}${key
|
|
6
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1_$2")
|
|
7
|
+
.replace(/[^a-zA-Z0-9]+/g, "_")
|
|
8
|
+
.toUpperCase()}`;
|
|
9
|
+
const value = env[name];
|
|
10
|
+
if (!value)
|
|
11
|
+
throw new Error(`secret ${key}: set ${name}`);
|
|
12
|
+
return value;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function memorySecrets(values) {
|
|
17
|
+
return {
|
|
18
|
+
async get(key) {
|
|
19
|
+
const v = values[key];
|
|
20
|
+
if (v === undefined)
|
|
21
|
+
throw new Error(`secret ${key}: not set`);
|
|
22
|
+
return v;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function trackingSecrets(source) {
|
|
27
|
+
const keys = new Map();
|
|
28
|
+
return {
|
|
29
|
+
async get(key) {
|
|
30
|
+
const value = await source.get(key);
|
|
31
|
+
keys.set(value, key);
|
|
32
|
+
return value;
|
|
33
|
+
},
|
|
34
|
+
keyOf: (value) => keys.get(value) ?? null,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AASA,qGAAqG;AACrG,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IACjF,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,MAAM,IAAI,GAAG,GAAG,MAAM,GAAG,GAAG;iBACzB,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;iBACtC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;iBAC9B,WAAW,EAAE,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;YACxB,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,SAAS,IAAI,EAAE,CAAC,CAAC;YAC1D,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAA8B;IAC1D,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YACtB,IAAI,CAAC,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC;YAC/D,OAAO,CAAC,CAAC;QACX,CAAC;KACF,CAAC;AACJ,CAAC;AAQD,MAAM,UAAU,eAAe,CAAC,MAAoB;IAClD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACrB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI;KAC1C,CAAC;AACJ,CAAC"}
|
package/dist/tail.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The last `n` non-empty lines of `path`, oldest first; [] for a missing file. */
|
|
2
|
+
export declare function tailLines(path: string, n: number): Promise<string[]>;
|
|
3
|
+
/** Each of the last `n` lines parsed as JSON; a torn line is skipped. */
|
|
4
|
+
export declare function tailJson<T>(path: string, n: number): Promise<T[]>;
|
package/dist/tail.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The last lines of an append-only file, read from its end in blocks: a
|
|
3
|
+
* ledger that grows for months costs the same to consult as a fresh one.
|
|
4
|
+
*/
|
|
5
|
+
import { open } from "node:fs/promises";
|
|
6
|
+
const BLOCK = 64 * 1024;
|
|
7
|
+
/** The last `n` non-empty lines of `path`, oldest first; [] for a missing file. */
|
|
8
|
+
export async function tailLines(path, n) {
|
|
9
|
+
if (n <= 0)
|
|
10
|
+
return [];
|
|
11
|
+
let fh;
|
|
12
|
+
try {
|
|
13
|
+
fh = await open(path, "r");
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const { size } = await fh.stat();
|
|
20
|
+
const chunks = [];
|
|
21
|
+
let pos = size;
|
|
22
|
+
let newlines = 0;
|
|
23
|
+
// Stop once the read-back text holds n+1 line breaks: the first partial line is then cut whole.
|
|
24
|
+
while (pos > 0 && newlines <= n) {
|
|
25
|
+
const len = Math.min(BLOCK, pos);
|
|
26
|
+
pos -= len;
|
|
27
|
+
const buf = Buffer.alloc(len);
|
|
28
|
+
await fh.read(buf, 0, len, pos);
|
|
29
|
+
chunks.unshift(buf);
|
|
30
|
+
for (let i = 0; i < len; i++)
|
|
31
|
+
if (buf[i] === 10)
|
|
32
|
+
newlines++;
|
|
33
|
+
}
|
|
34
|
+
// With n+1 line breaks in hand the last n lines are whole; the window's first line may be a
|
|
35
|
+
// fragment and is the one `slice(-n)` leaves behind.
|
|
36
|
+
const lines = Buffer.concat(chunks).toString("utf8").split("\n").filter(Boolean);
|
|
37
|
+
return lines.slice(-n);
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
await fh.close();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Each of the last `n` lines parsed as JSON; a torn line is skipped. */
|
|
44
|
+
export async function tailJson(path, n) {
|
|
45
|
+
const out = [];
|
|
46
|
+
for (const l of await tailLines(path, n)) {
|
|
47
|
+
try {
|
|
48
|
+
out.push(JSON.parse(l));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// a line still being written, or a fragment at the window's start
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=tail.js.map
|
package/dist/tail.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tail.js","sourceRoot":"","sources":["../src/tail.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,MAAM,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC;AAExB,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,CAAS;IACrD,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACtB,IAAI,EAAoC,CAAC;IACzC,IAAI,CAAC;QACH,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QACjC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,GAAG,GAAG,IAAI,CAAC;QACf,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,gGAAgG;QAChG,OAAO,GAAG,GAAG,CAAC,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACjC,GAAG,IAAI,GAAG,CAAC;YACX,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAChC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE;gBAAE,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;oBAAE,QAAQ,EAAE,CAAC;QAC9D,CAAC;QACD,4FAA4F;QAC5F,qDAAqD;QACrD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjF,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAI,IAAY,EAAE,CAAS;IACvD,MAAM,GAAG,GAAQ,EAAE,CAAC;IACpB,KAAK,MAAM,CAAC,IAAI,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;QACpE,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/totp.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare function base32Decode(text: string): Buffer;
|
|
2
|
+
export type TotpAlgorithm = "sha1" | "sha256" | "sha512";
|
|
3
|
+
export interface TotpOptions {
|
|
4
|
+
/** Unix ms; defaults to now. */
|
|
5
|
+
at?: number;
|
|
6
|
+
period?: number;
|
|
7
|
+
digits?: number;
|
|
8
|
+
algorithm?: TotpAlgorithm;
|
|
9
|
+
}
|
|
10
|
+
/** The code for `secret` (base32) at `at`. */
|
|
11
|
+
export declare function totp(secret: string, opts?: TotpOptions): string;
|
|
12
|
+
/** Milliseconds until the current code rolls over; wait it out when a site rejects a code that is about to expire. */
|
|
13
|
+
export declare function totpRemainingMs(at?: number, period?: number): number;
|
|
14
|
+
export interface TotpParams {
|
|
15
|
+
secret: string;
|
|
16
|
+
issuer: string | null;
|
|
17
|
+
account: string | null;
|
|
18
|
+
digits: number;
|
|
19
|
+
period: number;
|
|
20
|
+
algorithm: TotpAlgorithm;
|
|
21
|
+
}
|
|
22
|
+
export declare function parseOtpauth(uri: string): TotpParams;
|
|
23
|
+
/** The seed in page text or HTML: a URI wins, then a manual-entry key. Null when neither is there. */
|
|
24
|
+
export declare function findTotpSecret(text: string): string | null;
|
package/dist/totp.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TOTP (RFC 6238) with node:crypto, no dependency: the codes an
|
|
3
|
+
* authenticator app would show, so a login's second factor is ours to
|
|
4
|
+
* type. `findTotpSecret` pulls the seed out of an enrollment page (the
|
|
5
|
+
* otpauth:// link behind the QR, or the "enter this key manually" text).
|
|
6
|
+
*/
|
|
7
|
+
import { createHmac } from "node:crypto";
|
|
8
|
+
const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
9
|
+
export function base32Decode(text) {
|
|
10
|
+
const clean = text.toUpperCase().replace(/[\s=-]/g, "");
|
|
11
|
+
let bits = 0;
|
|
12
|
+
let value = 0;
|
|
13
|
+
const out = [];
|
|
14
|
+
for (const ch of clean) {
|
|
15
|
+
const idx = ALPHABET.indexOf(ch);
|
|
16
|
+
if (idx < 0)
|
|
17
|
+
throw new Error(`base32: bad character ${JSON.stringify(ch)}`);
|
|
18
|
+
value = (value << 5) | idx;
|
|
19
|
+
bits += 5;
|
|
20
|
+
if (bits >= 8) {
|
|
21
|
+
out.push((value >>> (bits - 8)) & 0xff);
|
|
22
|
+
bits -= 8;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return Buffer.from(out);
|
|
26
|
+
}
|
|
27
|
+
/** The code for `secret` (base32) at `at`. */
|
|
28
|
+
export function totp(secret, opts = {}) {
|
|
29
|
+
const period = opts.period ?? 30;
|
|
30
|
+
const digits = opts.digits ?? 6;
|
|
31
|
+
const counter = Math.floor((opts.at ?? Date.now()) / 1000 / period);
|
|
32
|
+
const msg = Buffer.alloc(8);
|
|
33
|
+
msg.writeBigUInt64BE(BigInt(counter));
|
|
34
|
+
const mac = createHmac(opts.algorithm ?? "sha1", base32Decode(secret))
|
|
35
|
+
.update(msg)
|
|
36
|
+
.digest();
|
|
37
|
+
const offset = (mac[mac.length - 1] ?? 0) & 0x0f;
|
|
38
|
+
const code = (mac.readUInt32BE(offset) & 0x7fffffff) % 10 ** digits;
|
|
39
|
+
return String(code).padStart(digits, "0");
|
|
40
|
+
}
|
|
41
|
+
/** Milliseconds until the current code rolls over; wait it out when a site rejects a code that is about to expire. */
|
|
42
|
+
export function totpRemainingMs(at = Date.now(), period = 30) {
|
|
43
|
+
const step = period * 1000;
|
|
44
|
+
return step - (at % step);
|
|
45
|
+
}
|
|
46
|
+
export function parseOtpauth(uri) {
|
|
47
|
+
const u = new URL(uri);
|
|
48
|
+
if (u.protocol !== "otpauth:" || u.host !== "totp")
|
|
49
|
+
throw new Error("not an otpauth://totp URI");
|
|
50
|
+
const secret = u.searchParams.get("secret");
|
|
51
|
+
if (!secret)
|
|
52
|
+
throw new Error("otpauth URI has no secret");
|
|
53
|
+
const label = decodeURIComponent(u.pathname.replace(/^\/+/, ""));
|
|
54
|
+
const [labelIssuer, account] = label.includes(":") ? label.split(":", 2) : [null, label];
|
|
55
|
+
const algo = (u.searchParams.get("algorithm") ?? "SHA1").toLowerCase();
|
|
56
|
+
return {
|
|
57
|
+
secret: secret.replace(/[\s=-]/g, "").toUpperCase(),
|
|
58
|
+
issuer: u.searchParams.get("issuer") ?? labelIssuer,
|
|
59
|
+
account: account || null,
|
|
60
|
+
digits: Number(u.searchParams.get("digits") ?? 6),
|
|
61
|
+
period: Number(u.searchParams.get("period") ?? 30),
|
|
62
|
+
algorithm: algo === "sha256" || algo === "sha512" ? algo : "sha1",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const OTPAUTH = /otpauth:\/\/totp\/[^\s"'<>]+/i;
|
|
66
|
+
/**
|
|
67
|
+
* 16+ base32 characters in one case, optionally in spaced or dashed groups
|
|
68
|
+
* of 4. One case because a page prints its key in one case, and the words
|
|
69
|
+
* around it ("Make sure Time based") are mixed: they must not join the run.
|
|
70
|
+
*/
|
|
71
|
+
const MANUAL_KEYS = [
|
|
72
|
+
/\b(?:[a-z2-7]{4}[\s-]?){4,}[a-z2-7]*\b/g,
|
|
73
|
+
/\b(?:[A-Z2-7]{4}[\s-]?){4,}[A-Z2-7]*\b/g,
|
|
74
|
+
];
|
|
75
|
+
/**
|
|
76
|
+
* Seed lengths sites hand out, most common first (Google/Cloudflare 32,
|
|
77
|
+
* GitHub/Microsoft 16, AWS 64). A run is cut to the first of these some
|
|
78
|
+
* prefix of its groups adds up to, so a 4-letter word after the key
|
|
79
|
+
* ("then") does not join it. A wrong cut fails the confirm step, nothing worse.
|
|
80
|
+
*/
|
|
81
|
+
const SEED_LENGTHS = [32, 16, 64, 26, 52, 20, 24, 40];
|
|
82
|
+
function manualKey(text) {
|
|
83
|
+
for (const re of MANUAL_KEYS)
|
|
84
|
+
for (const m of text.matchAll(re)) {
|
|
85
|
+
const tokens = m[0].trim().split(/[\s-]+/);
|
|
86
|
+
const prefixes = tokens.map((_, i) => tokens.slice(0, i + 1).join(""));
|
|
87
|
+
for (const len of SEED_LENGTHS) {
|
|
88
|
+
const key = prefixes.find((p) => p.length === len);
|
|
89
|
+
if (key)
|
|
90
|
+
return key.toUpperCase();
|
|
91
|
+
}
|
|
92
|
+
const whole = tokens.join("");
|
|
93
|
+
if (whole.length >= 16 && whole.length % 2 === 0)
|
|
94
|
+
return whole.toUpperCase();
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
/** The seed in page text or HTML: a URI wins, then a manual-entry key. Null when neither is there. */
|
|
99
|
+
export function findTotpSecret(text) {
|
|
100
|
+
const uri = text.match(OTPAUTH);
|
|
101
|
+
if (uri) {
|
|
102
|
+
try {
|
|
103
|
+
return parseOtpauth(uri[0].replace(/&/g, "&")).secret;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// fall through to a manual key
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return manualKey(text);
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=totp.js.map
|
package/dist/totp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"totp.js","sourceRoot":"","sources":["../src/totp.ts"],"names":[],"mappings":"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"}
|