sec-ry 1.1.5
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/dist/cli.bundle.js +7211 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +37 -0
- package/dist/cmd/changelog.d.ts +2 -0
- package/dist/cmd/changelog.js +726 -0
- package/dist/cmd/denc.d.ts +2 -0
- package/dist/cmd/denc.js +74 -0
- package/dist/cmd/enc.d.ts +2 -0
- package/dist/cmd/enc.js +225 -0
- package/dist/cmd/example.d.ts +1 -0
- package/dist/cmd/example.js +92 -0
- package/dist/cmd/fp.d.ts +2 -0
- package/dist/cmd/fp.js +29 -0
- package/dist/cmd/gen.d.ts +2 -0
- package/dist/cmd/gen.js +76 -0
- package/dist/cmd/history.d.ts +2 -0
- package/dist/cmd/history.js +25 -0
- package/dist/cmd/info.d.ts +2 -0
- package/dist/cmd/info.js +28 -0
- package/dist/cmd/root.d.ts +1 -0
- package/dist/cmd/root.js +191 -0
- package/dist/cmd/seal.d.ts +3 -0
- package/dist/cmd/seal.js +81 -0
- package/dist/cmd/upgrade.d.ts +1 -0
- package/dist/cmd/upgrade.js +44 -0
- package/dist/cmd/verify.d.ts +2 -0
- package/dist/cmd/verify.js +30 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +27 -0
- package/dist/lib/args.d.ts +8 -0
- package/dist/lib/args.js +43 -0
- package/dist/lib/clip.d.ts +2 -0
- package/dist/lib/clip.js +39 -0
- package/dist/lib/crypto.d.ts +29 -0
- package/dist/lib/crypto.js +312 -0
- package/dist/lib/env.d.ts +13 -0
- package/dist/lib/env.js +42 -0
- package/dist/lib/errors.d.ts +1 -0
- package/dist/lib/errors.js +61 -0
- package/dist/lib/history.d.ts +9 -0
- package/dist/lib/history.js +35 -0
- package/dist/lib/password.d.ts +2 -0
- package/dist/lib/password.js +31 -0
- package/dist/lib/rc.d.ts +7 -0
- package/dist/lib/rc.js +45 -0
- package/dist/lib/ui.d.ts +21 -0
- package/dist/lib/ui.js +137 -0
- package/package.json +44 -0
package/dist/cmd/root.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.cmdRoot = cmdRoot;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const os = __importStar(require("os"));
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const crypto = __importStar(require("crypto"));
|
|
41
|
+
const cp = __importStar(require("child_process"));
|
|
42
|
+
const _D = path.join(os.homedir(), ".secry");
|
|
43
|
+
const _PF = path.join(_D, ".adm");
|
|
44
|
+
const _FF = path.join(_D, ".fgp");
|
|
45
|
+
const _LF = path.join(_D, "changelog.audit.log");
|
|
46
|
+
const $ = {
|
|
47
|
+
r: "\x1b[0m", d: "\x1b[2m", b: "\x1b[1m",
|
|
48
|
+
w: "\x1b[97m", c: "\x1b[96m", g: "\x1b[92m",
|
|
49
|
+
e: "\x1b[91m", y: "\x1b[93m",
|
|
50
|
+
};
|
|
51
|
+
const _w = (s) => process.stderr.write(s);
|
|
52
|
+
function _box(title) {
|
|
53
|
+
const l = "─".repeat(48);
|
|
54
|
+
_w(`\n ${$.d}${l}${$.r}\n ${$.b}${$.w} ${title}${$.r}\n ${$.d}${l}${$.r}\n\n`);
|
|
55
|
+
}
|
|
56
|
+
function _audit(action, detail) {
|
|
57
|
+
try {
|
|
58
|
+
if (!fs.existsSync(_D))
|
|
59
|
+
fs.mkdirSync(_D, { recursive: true });
|
|
60
|
+
fs.appendFileSync(_LF, `${new Date().toISOString()} ${action.padEnd(12)} ${detail}\n`, "utf8");
|
|
61
|
+
}
|
|
62
|
+
catch { }
|
|
63
|
+
}
|
|
64
|
+
function _exec(cmd) {
|
|
65
|
+
try {
|
|
66
|
+
return cp.execSync(cmd, { encoding: "utf8", timeout: 2000, stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function _gatherFp() {
|
|
73
|
+
const home = os.homedir();
|
|
74
|
+
const hardware = _exec("grep 'Hardware' /proc/cpuinfo | head -1");
|
|
75
|
+
const prefix = process.env.PREFIX ?? "";
|
|
76
|
+
const uid = _exec("id -u");
|
|
77
|
+
return [home, hardware, prefix, uid].join("|");
|
|
78
|
+
}
|
|
79
|
+
function _hashFp(data, salt) {
|
|
80
|
+
return crypto.scryptSync(Buffer.from(data, "utf8"), salt, 32, { N: 4096, r: 8, p: 1 }).toString("hex");
|
|
81
|
+
}
|
|
82
|
+
function _registerFp() {
|
|
83
|
+
const salt = crypto.randomBytes(16);
|
|
84
|
+
const hashed = _hashFp(_gatherFp(), salt);
|
|
85
|
+
const store = { salt: salt.toString("hex"), stable: hashed };
|
|
86
|
+
if (!fs.existsSync(_D))
|
|
87
|
+
fs.mkdirSync(_D, { recursive: true });
|
|
88
|
+
fs.writeFileSync(_FF, Buffer.from(JSON.stringify(store)).toString("base64"), "utf8");
|
|
89
|
+
try {
|
|
90
|
+
fs.chmodSync(_FF, 0o600);
|
|
91
|
+
}
|
|
92
|
+
catch { }
|
|
93
|
+
_audit("fp-register", "device fingerprint registered");
|
|
94
|
+
}
|
|
95
|
+
function _verifyFp() {
|
|
96
|
+
try {
|
|
97
|
+
if (!fs.existsSync(_FF))
|
|
98
|
+
return false;
|
|
99
|
+
const store = JSON.parse(Buffer.from(fs.readFileSync(_FF, "utf8").trim(), "base64").toString("utf8"));
|
|
100
|
+
const salt = Buffer.from(store.salt, "hex");
|
|
101
|
+
const hashed = _hashFp(_gatherFp(), salt);
|
|
102
|
+
const expected = Buffer.from(store.stable, "hex");
|
|
103
|
+
const got = Buffer.from(hashed, "hex");
|
|
104
|
+
if (expected.length !== got.length)
|
|
105
|
+
return false;
|
|
106
|
+
return crypto.timingSafeEqual(expected, got);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
let _mr = false;
|
|
113
|
+
function _menu(items) {
|
|
114
|
+
return new Promise(resolve => {
|
|
115
|
+
let idx = 0;
|
|
116
|
+
while (items[idx]?.dim)
|
|
117
|
+
idx = (idx + 1) % items.length;
|
|
118
|
+
function render() {
|
|
119
|
+
if (_mr)
|
|
120
|
+
process.stderr.write(`\x1b[${items.length}A`);
|
|
121
|
+
_mr = true;
|
|
122
|
+
for (let i = 0; i < items.length; i++) {
|
|
123
|
+
const item = items[i];
|
|
124
|
+
if (item.dim) {
|
|
125
|
+
_w(` ${$.d} ${item.label}${$.r}\n`);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const sel = i === idx;
|
|
129
|
+
_w(` ${sel ? `${$.b}${$.c}›${$.r} ` : `${$.d} `}${sel ? $.b : ""}${item.label}${$.r}\n`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
process.stdin.setRawMode?.(true);
|
|
133
|
+
process.stdin.resume();
|
|
134
|
+
process.stdin.setEncoding("utf8");
|
|
135
|
+
render();
|
|
136
|
+
process.stdin.on("data", function h(ch) {
|
|
137
|
+
if (ch === "\u0003")
|
|
138
|
+
process.exit(0);
|
|
139
|
+
if (ch === "\u001b[A") {
|
|
140
|
+
do {
|
|
141
|
+
idx = (idx - 1 + items.length) % items.length;
|
|
142
|
+
} while (items[idx]?.dim);
|
|
143
|
+
render();
|
|
144
|
+
}
|
|
145
|
+
else if (ch === "\u001b[B") {
|
|
146
|
+
do {
|
|
147
|
+
idx = (idx + 1) % items.length;
|
|
148
|
+
} while (items[idx]?.dim);
|
|
149
|
+
render();
|
|
150
|
+
}
|
|
151
|
+
else if (ch === "\r" || ch === "\n") {
|
|
152
|
+
process.stdin.setRawMode?.(false);
|
|
153
|
+
process.stdin.pause();
|
|
154
|
+
process.stdin.removeListener("data", h);
|
|
155
|
+
_mr = false;
|
|
156
|
+
_w("\n");
|
|
157
|
+
resolve(items[idx].key);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
async function cmdRoot() {
|
|
163
|
+
const { adminPanel } = await Promise.resolve().then(() => __importStar(require("./changelog")));
|
|
164
|
+
if (!fs.existsSync(_FF)) {
|
|
165
|
+
_registerFp();
|
|
166
|
+
}
|
|
167
|
+
if (!_verifyFp()) {
|
|
168
|
+
_audit("fp-deny", "fingerprint mismatch");
|
|
169
|
+
_w(`\n unknown command\n\n`);
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
if (!fs.existsSync(_PF)) {
|
|
173
|
+
_w(`\n ${$.y}no admin password set yet.${$.r}\n`);
|
|
174
|
+
_w(` ${$.d}run: secry changelog --admin${$.r}\n\n`);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
_audit("fp-ok", "fingerprint verified");
|
|
178
|
+
while (true) {
|
|
179
|
+
_box("secry — root");
|
|
180
|
+
const choice = await _menu([
|
|
181
|
+
{ label: "changelog", key: "changelog" },
|
|
182
|
+
{ label: "───────────────", key: "_", dim: true },
|
|
183
|
+
{ label: "exit", key: "0" },
|
|
184
|
+
]);
|
|
185
|
+
if (choice === "changelog")
|
|
186
|
+
await adminPanel();
|
|
187
|
+
else
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
_w(`\n ${$.d}exiting root.${$.r}\n\n`);
|
|
191
|
+
}
|
package/dist/cmd/seal.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cmdSeal = cmdSeal;
|
|
4
|
+
exports.cmdSealVerify = cmdSealVerify;
|
|
5
|
+
const crypto_1 = require("../lib/crypto");
|
|
6
|
+
const password_1 = require("../lib/password");
|
|
7
|
+
const ui_1 = require("../lib/ui");
|
|
8
|
+
const clip_1 = require("../lib/clip");
|
|
9
|
+
const rc_1 = require("../lib/rc");
|
|
10
|
+
const args_1 = require("../lib/args");
|
|
11
|
+
async function cmdSeal(parsed) {
|
|
12
|
+
const rc = (0, rc_1.loadRC)();
|
|
13
|
+
const text = parsed.positional[0];
|
|
14
|
+
if (!text)
|
|
15
|
+
(0, ui_1.err)("missing <value> argument");
|
|
16
|
+
const rawPw = (0, args_1.getFlag)(parsed.flags, "sw") ?? rc.password;
|
|
17
|
+
const secret = (0, password_1.resolvePassword)(rawPw ?? "");
|
|
18
|
+
const useClip = (0, args_1.hasFlag)(parsed.flags, "clip") || !!rc.clip;
|
|
19
|
+
const quiet = (0, args_1.hasFlag)(parsed.flags, "quiet") || (0, args_1.hasFlag)(parsed.flags, "q");
|
|
20
|
+
const useS2 = (0, args_1.hasFlag)(parsed.flags, "s2");
|
|
21
|
+
const t0 = Date.now();
|
|
22
|
+
const token = useS2
|
|
23
|
+
? await (0, crypto_1.sealS2)(text, secret)
|
|
24
|
+
: (0, crypto_1.seal)(text, secret);
|
|
25
|
+
const elapsed = Date.now() - t0;
|
|
26
|
+
if (!quiet) {
|
|
27
|
+
(0, ui_1.section)("seal");
|
|
28
|
+
(0, ui_1.box)([
|
|
29
|
+
{ label: "input", value: text.length > 52 ? text.slice(0, 52) + "…" : text },
|
|
30
|
+
{ label: "algo", value: useS2 ? "BLAKE3 / scrypt N=2^16" : "HMAC-SHA256 / scrypt" },
|
|
31
|
+
{ label: "version", value: useS2 ? "s2" : "s1" },
|
|
32
|
+
{ label: "note", value: "one-way — cannot be reversed" },
|
|
33
|
+
{ label: "token", value: token },
|
|
34
|
+
]);
|
|
35
|
+
(0, ui_1.ms)(elapsed);
|
|
36
|
+
if (!useS2)
|
|
37
|
+
(0, ui_1.warn)("s1 is less secure — consider using --s2 for stronger protection");
|
|
38
|
+
}
|
|
39
|
+
if (useClip) {
|
|
40
|
+
const copied = (0, clip_1.copyToClipboard)(token);
|
|
41
|
+
if (copied) {
|
|
42
|
+
const { info } = require("../lib/ui");
|
|
43
|
+
if (!quiet)
|
|
44
|
+
info("copied to clipboard");
|
|
45
|
+
}
|
|
46
|
+
else if (!quiet)
|
|
47
|
+
(0, ui_1.warn)("--clip: no clipboard tool found");
|
|
48
|
+
}
|
|
49
|
+
(0, ui_1.data)(token);
|
|
50
|
+
}
|
|
51
|
+
async function cmdSealVerify(parsed) {
|
|
52
|
+
const rc = (0, rc_1.loadRC)();
|
|
53
|
+
const text = parsed.positional[0];
|
|
54
|
+
const token = (0, args_1.getFlag)(parsed.flags, "token");
|
|
55
|
+
if (!text)
|
|
56
|
+
(0, ui_1.err)("missing <value> argument");
|
|
57
|
+
if (!token)
|
|
58
|
+
(0, ui_1.err)("--token <token> is required");
|
|
59
|
+
const rawPw = (0, args_1.getFlag)(parsed.flags, "sw") ?? rc.password;
|
|
60
|
+
if (!rawPw)
|
|
61
|
+
(0, ui_1.err)("-sw <secret> is required");
|
|
62
|
+
const secret = (0, password_1.resolvePassword)(rawPw);
|
|
63
|
+
const quiet = (0, args_1.hasFlag)(parsed.flags, "quiet") || (0, args_1.hasFlag)(parsed.flags, "q");
|
|
64
|
+
const isS2 = token.startsWith("secry:s2:");
|
|
65
|
+
const t0 = Date.now();
|
|
66
|
+
const ok = isS2
|
|
67
|
+
? await (0, crypto_1.sealVerifyS2)(text, secret, token)
|
|
68
|
+
: (0, crypto_1.sealVerify)(text, secret, token);
|
|
69
|
+
const elapsed = Date.now() - t0;
|
|
70
|
+
if (!quiet) {
|
|
71
|
+
(0, ui_1.section)("seal verify");
|
|
72
|
+
(0, ui_1.box)([
|
|
73
|
+
{ label: "input", value: text.length > 52 ? text.slice(0, 52) + "…" : text },
|
|
74
|
+
{ label: "version", value: isS2 ? "s2" : "s1" },
|
|
75
|
+
{ label: "result", value: ok ? "match" : "no match" },
|
|
76
|
+
]);
|
|
77
|
+
(0, ui_1.ms)(elapsed);
|
|
78
|
+
}
|
|
79
|
+
if (!ok)
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cmdUpgrade(): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cmdUpgrade = cmdUpgrade;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const ui_1 = require("../lib/ui");
|
|
6
|
+
function _latest() {
|
|
7
|
+
try {
|
|
8
|
+
return (0, child_process_1.execSync)("npm info secry version", { encoding: "utf8", timeout: 8000 }).trim();
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function _cmp(a, b) {
|
|
15
|
+
const pa = a.split(".").map(Number);
|
|
16
|
+
const pb = b.split(".").map(Number);
|
|
17
|
+
for (let i = 0; i < 3; i++) {
|
|
18
|
+
const d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
19
|
+
if (d)
|
|
20
|
+
return d;
|
|
21
|
+
}
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
function cmdUpgrade() {
|
|
25
|
+
(0, ui_1.section)("upgrade");
|
|
26
|
+
(0, ui_1.row)("current", ui_1.VERSION);
|
|
27
|
+
process.stderr.write("\n");
|
|
28
|
+
(0, ui_1.info)("checking npm registry...");
|
|
29
|
+
process.stderr.write("\n");
|
|
30
|
+
const latest = _latest();
|
|
31
|
+
if (!latest)
|
|
32
|
+
(0, ui_1.err)("could not reach npm registry. check your connection.", 1);
|
|
33
|
+
(0, ui_1.row)("latest", latest);
|
|
34
|
+
process.stderr.write("\n");
|
|
35
|
+
if (_cmp(latest, ui_1.VERSION) <= 0) {
|
|
36
|
+
(0, ui_1.ok)("already up to date");
|
|
37
|
+
process.stderr.write("\n");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
(0, ui_1.info)(`update available ${ui_1.VERSION} → ${latest}`);
|
|
41
|
+
process.stderr.write("\n");
|
|
42
|
+
process.stdout.write("npm install -g secry\n");
|
|
43
|
+
process.stderr.write("\n");
|
|
44
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cmdVerify = cmdVerify;
|
|
4
|
+
const crypto_1 = require("../lib/crypto");
|
|
5
|
+
const password_1 = require("../lib/password");
|
|
6
|
+
const ui_1 = require("../lib/ui");
|
|
7
|
+
const rc_1 = require("../lib/rc");
|
|
8
|
+
const args_1 = require("../lib/args");
|
|
9
|
+
function cmdVerify(parsed) {
|
|
10
|
+
const rc = (0, rc_1.loadRC)();
|
|
11
|
+
const token = parsed.positional[0];
|
|
12
|
+
if (!token)
|
|
13
|
+
(0, ui_1.err)("missing <token> argument");
|
|
14
|
+
const rawPw = (0, args_1.getFlag)(parsed.flags, "sw") ?? rc.password;
|
|
15
|
+
if (!rawPw)
|
|
16
|
+
(0, ui_1.err)("-sw <password> is required");
|
|
17
|
+
const password = (0, password_1.resolvePassword)(rawPw);
|
|
18
|
+
const t0 = Date.now();
|
|
19
|
+
const isOk = (0, crypto_1.verify)(token, password);
|
|
20
|
+
const elapsed = Date.now() - t0;
|
|
21
|
+
(0, ui_1.section)("verify");
|
|
22
|
+
(0, ui_1.box)([
|
|
23
|
+
{ label: "token", value: token.length > 40 ? token.slice(0, 40) + "…" : token },
|
|
24
|
+
{ label: "status", value: isOk ? "valid" : "invalid", valueColor: isOk ? "\x1b[32m" : "\x1b[31m" },
|
|
25
|
+
]);
|
|
26
|
+
(0, ui_1.ms)(elapsed);
|
|
27
|
+
process.stdout.write((isOk ? "valid" : "invalid") + "\n");
|
|
28
|
+
if (!isOk)
|
|
29
|
+
process.exit(2);
|
|
30
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
interface DecryptChain {
|
|
2
|
+
key(password: string): string;
|
|
3
|
+
k(password: string): string;
|
|
4
|
+
}
|
|
5
|
+
interface InspectResult {
|
|
6
|
+
version: string;
|
|
7
|
+
prefix: string;
|
|
8
|
+
saltHex: string;
|
|
9
|
+
nonceHex: string;
|
|
10
|
+
payloadBytes: number;
|
|
11
|
+
algo: string;
|
|
12
|
+
}
|
|
13
|
+
interface XH32 {
|
|
14
|
+
readonly version: string;
|
|
15
|
+
readonly TOKEN_PREFIX: string;
|
|
16
|
+
encrypt(text: string, password: string, opts?: {
|
|
17
|
+
expiresMs?: number;
|
|
18
|
+
}): string;
|
|
19
|
+
decrypt(token: string): DecryptChain;
|
|
20
|
+
verify(token: string, password: string): boolean;
|
|
21
|
+
fingerprint(text: string, secret: string): string;
|
|
22
|
+
generate(bytes?: number): string;
|
|
23
|
+
inspect(token: string): InspectResult;
|
|
24
|
+
}
|
|
25
|
+
declare const secry: XH32;
|
|
26
|
+
export default secry;
|
|
27
|
+
export { secry };
|
|
28
|
+
export type { XH32, DecryptChain, InspectResult };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.secry = void 0;
|
|
4
|
+
const crypto_1 = require("./lib/crypto");
|
|
5
|
+
const secry = {
|
|
6
|
+
version: crypto_1.VERSION, TOKEN_PREFIX: crypto_1.TOKEN_PREFIX,
|
|
7
|
+
encrypt(text, password, opts = {}) {
|
|
8
|
+
if (!text)
|
|
9
|
+
throw new TypeError("text must be a non-empty string");
|
|
10
|
+
if (!password)
|
|
11
|
+
throw new TypeError("password must be a non-empty string");
|
|
12
|
+
return (0, crypto_1.encrypt)(text, password, opts);
|
|
13
|
+
},
|
|
14
|
+
decrypt(token) {
|
|
15
|
+
if (!token)
|
|
16
|
+
throw new TypeError("token must be a non-empty string");
|
|
17
|
+
const _r = (pw) => { if (!pw)
|
|
18
|
+
throw new TypeError("password required"); return (0, crypto_1.decrypt)(token, pw).plaintext; };
|
|
19
|
+
return { key: _r, k: _r };
|
|
20
|
+
},
|
|
21
|
+
verify: (t, p) => (0, crypto_1.verify)(t, p),
|
|
22
|
+
fingerprint: (t, s) => (0, crypto_1.hmacFingerprint)(t, s),
|
|
23
|
+
generate: (b = 24) => (0, crypto_1.generatePassword)(b),
|
|
24
|
+
inspect: (t) => (0, crypto_1.inspectToken)(t),
|
|
25
|
+
};
|
|
26
|
+
exports.secry = secry;
|
|
27
|
+
exports.default = secry;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ParsedArgs {
|
|
2
|
+
cmd: string;
|
|
3
|
+
positional: string[];
|
|
4
|
+
flags: Record<string, string | true>;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
7
|
+
export declare function getFlag(flags: Record<string, string | true>, ...keys: string[]): string | undefined;
|
|
8
|
+
export declare function hasFlag(flags: Record<string, string | true>, ...keys: string[]): boolean;
|
package/dist/lib/args.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseArgs = parseArgs;
|
|
4
|
+
exports.getFlag = getFlag;
|
|
5
|
+
exports.hasFlag = hasFlag;
|
|
6
|
+
function parseArgs(argv) {
|
|
7
|
+
const flags = {};
|
|
8
|
+
const positional = [];
|
|
9
|
+
let i = 0;
|
|
10
|
+
const cmd = argv[0] ?? "";
|
|
11
|
+
i = 1;
|
|
12
|
+
while (i < argv.length) {
|
|
13
|
+
const a = argv[i];
|
|
14
|
+
if (a.startsWith("-")) {
|
|
15
|
+
const key = a.replace(/^-+/, "");
|
|
16
|
+
const next = argv[i + 1];
|
|
17
|
+
if (next && !next.startsWith("-")) {
|
|
18
|
+
flags[key] = next;
|
|
19
|
+
i += 2;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
flags[key] = true;
|
|
23
|
+
i++;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
positional.push(a);
|
|
28
|
+
i++;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { cmd, positional, flags };
|
|
32
|
+
}
|
|
33
|
+
function getFlag(flags, ...keys) {
|
|
34
|
+
for (const k of keys) {
|
|
35
|
+
const v = flags[k];
|
|
36
|
+
if (typeof v === "string")
|
|
37
|
+
return v;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
function hasFlag(flags, ...keys) {
|
|
42
|
+
return keys.some((k) => k in flags);
|
|
43
|
+
}
|
package/dist/lib/clip.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.copyToClipboard = copyToClipboard;
|
|
4
|
+
exports.clipAvailable = clipAvailable;
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const env_1 = require("./env");
|
|
7
|
+
function _cmd() {
|
|
8
|
+
if (env_1.env.isMacOS)
|
|
9
|
+
return "pbcopy";
|
|
10
|
+
if (env_1.env.isTermux) {
|
|
11
|
+
try {
|
|
12
|
+
(0, child_process_1.execSync)("which termux-clipboard-set", { stdio: "ignore" });
|
|
13
|
+
return "termux-clipboard-set";
|
|
14
|
+
}
|
|
15
|
+
catch { }
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
for (const [bin, cmd] of [["xclip", "xclip -selection clipboard"], ["xsel", "xsel --clipboard --input"], ["wl-copy", "wl-copy"]]) {
|
|
19
|
+
try {
|
|
20
|
+
(0, child_process_1.execSync)(`which ${bin}`, { stdio: "ignore" });
|
|
21
|
+
return cmd;
|
|
22
|
+
}
|
|
23
|
+
catch { }
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
function copyToClipboard(text) {
|
|
28
|
+
const cmd = _cmd();
|
|
29
|
+
if (!cmd)
|
|
30
|
+
return false;
|
|
31
|
+
try {
|
|
32
|
+
(0, child_process_1.execSync)(cmd, { input: text, stdio: ["pipe", "ignore", "ignore"] });
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function clipAvailable() { return _cmd() !== null; }
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const TOKEN_PREFIX = "secry:v2:";
|
|
2
|
+
export declare const VERSION = "v2";
|
|
3
|
+
export interface EncryptOptions {
|
|
4
|
+
expiresMs?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function encrypt(plaintext: string, password: string, opts?: EncryptOptions, version?: 1 | 2 | 3, compact?: boolean): string;
|
|
7
|
+
export interface DecryptResult {
|
|
8
|
+
plaintext: string;
|
|
9
|
+
expiresAt?: Date;
|
|
10
|
+
tokenVersion: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function decrypt(token: string, password: string): DecryptResult;
|
|
13
|
+
export declare function verify(token: string, password: string): boolean;
|
|
14
|
+
export declare function hmacFingerprint(input: string, secret: string): string;
|
|
15
|
+
export declare function inspectToken(token: string): {
|
|
16
|
+
version: string;
|
|
17
|
+
saltHex: string;
|
|
18
|
+
nonceHex: string;
|
|
19
|
+
payloadBytes: number;
|
|
20
|
+
prefix: string;
|
|
21
|
+
algo: string;
|
|
22
|
+
compact: boolean;
|
|
23
|
+
};
|
|
24
|
+
export declare function generatePassword(bytes?: number): string;
|
|
25
|
+
export declare function parseExpiry(raw: string): number;
|
|
26
|
+
export declare function seal(input: string, secret: string): string;
|
|
27
|
+
export declare function sealVerify(input: string, secret: string, token: string): boolean;
|
|
28
|
+
export declare function sealS2(input: string, secret: string): Promise<string>;
|
|
29
|
+
export declare function sealVerifyS2(input: string, secret: string, token: string): Promise<boolean>;
|