sec-ry 1.1.5 → 1.1.7
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 +346 -26
- package/dist/cli.js +1 -1
- package/dist/cmd/seal.d.ts +3 -0
- package/dist/cmd/seal.js +193 -3
- package/dist/index.d.ts +5 -2
- package/dist/index.js +4 -1
- package/dist/lib/args.d.ts +2 -0
- package/dist/lib/args.js +20 -5
- package/dist/lib/crypto.d.ts +22 -2
- package/dist/lib/crypto.js +126 -16
- package/dist/lib/ui.js +5 -2
- package/package.json +1 -1
package/dist/cli.bundle.js
CHANGED
|
@@ -170,7 +170,7 @@ var require_package = __commonJS({
|
|
|
170
170
|
"package.json"(exports2, module2) {
|
|
171
171
|
module2.exports = {
|
|
172
172
|
name: "sec-ry",
|
|
173
|
-
version: "1.1.
|
|
173
|
+
version: "1.1.7",
|
|
174
174
|
description: "ChaCha20-Poly1305 / AES-256-GCM token encryption CLI and library",
|
|
175
175
|
main: "dist/index.js",
|
|
176
176
|
types: "dist/index.d.ts",
|
|
@@ -300,13 +300,16 @@ var require_ui = __commonJS({
|
|
|
300
300
|
function box(rows) {
|
|
301
301
|
if (exports2.QUIET)
|
|
302
302
|
return;
|
|
303
|
+
const MAX_W = 80;
|
|
303
304
|
const lw = Math.max(...rows.map((r) => r.label.length));
|
|
305
|
+
const valMax = MAX_W - lw - 6;
|
|
304
306
|
const lines = rows.map((r) => {
|
|
305
307
|
const pad = " ".repeat(lw - r.label.length + 1);
|
|
306
308
|
const vc = r.valueColor ?? _c.hi;
|
|
307
|
-
|
|
309
|
+
const val = r.value.length > valMax ? r.value.slice(0, valMax - 1) + "\u2026" : r.value;
|
|
310
|
+
return `${_c.gray}${r.label}${_c.r}${pad}${vc}${val}${_c.r}`;
|
|
308
311
|
});
|
|
309
|
-
const width = Math.max(...lines.map(_visLen)) + 4;
|
|
312
|
+
const width = Math.min(MAX_W, Math.max(...lines.map(_visLen)) + 4);
|
|
310
313
|
const hline = (l, r) => `${_c.gray}${l}${"\u2500".repeat(width - 2)}${r}${_c.r}
|
|
311
314
|
`;
|
|
312
315
|
_ui(hline("\u250C", "\u2510"));
|
|
@@ -428,9 +431,11 @@ var require_args = __commonJS({
|
|
|
428
431
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
429
432
|
exports2.parseArgs = parseArgs;
|
|
430
433
|
exports2.getFlag = getFlag;
|
|
434
|
+
exports2.getFlags = getFlags;
|
|
431
435
|
exports2.hasFlag = hasFlag;
|
|
432
436
|
function parseArgs(argv) {
|
|
433
437
|
const flags = {};
|
|
438
|
+
const multi = {};
|
|
434
439
|
const positional = [];
|
|
435
440
|
let i = 0;
|
|
436
441
|
const cmd = argv[0] ?? "";
|
|
@@ -439,10 +444,16 @@ var require_args = __commonJS({
|
|
|
439
444
|
const a = argv[i];
|
|
440
445
|
if (a.startsWith("-")) {
|
|
441
446
|
const key = a.replace(/^-+/, "");
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
447
|
+
const vals = [];
|
|
448
|
+
let j = i + 1;
|
|
449
|
+
while (j < argv.length && !argv[j].startsWith("-")) {
|
|
450
|
+
vals.push(argv[j]);
|
|
451
|
+
j++;
|
|
452
|
+
}
|
|
453
|
+
if (vals.length > 0) {
|
|
454
|
+
flags[key] = vals[0];
|
|
455
|
+
multi[key] = vals;
|
|
456
|
+
i = j;
|
|
446
457
|
} else {
|
|
447
458
|
flags[key] = true;
|
|
448
459
|
i++;
|
|
@@ -452,7 +463,7 @@ var require_args = __commonJS({
|
|
|
452
463
|
i++;
|
|
453
464
|
}
|
|
454
465
|
}
|
|
455
|
-
return { cmd, positional, flags };
|
|
466
|
+
return { cmd, positional, flags, multi };
|
|
456
467
|
}
|
|
457
468
|
function getFlag(flags, ...keys) {
|
|
458
469
|
for (const k of keys) {
|
|
@@ -462,6 +473,13 @@ var require_args = __commonJS({
|
|
|
462
473
|
}
|
|
463
474
|
return void 0;
|
|
464
475
|
}
|
|
476
|
+
function getFlags(multi, ...keys) {
|
|
477
|
+
for (const k of keys) {
|
|
478
|
+
if (multi[k] && multi[k].length > 0)
|
|
479
|
+
return multi[k];
|
|
480
|
+
}
|
|
481
|
+
return [];
|
|
482
|
+
}
|
|
465
483
|
function hasFlag(flags, ...keys) {
|
|
466
484
|
return keys.some((k) => k in flags);
|
|
467
485
|
}
|
|
@@ -989,6 +1007,9 @@ var require_crypto = __commonJS({
|
|
|
989
1007
|
exports2.inspectToken = inspectToken;
|
|
990
1008
|
exports2.generatePassword = generatePassword;
|
|
991
1009
|
exports2.parseExpiry = parseExpiry;
|
|
1010
|
+
exports2._unseal = _unseal;
|
|
1011
|
+
exports2.sealEnc = sealEnc;
|
|
1012
|
+
exports2.open = open;
|
|
992
1013
|
exports2.seal = seal;
|
|
993
1014
|
exports2.sealVerify = sealVerify;
|
|
994
1015
|
exports2.sealS2 = sealS2;
|
|
@@ -1190,24 +1211,118 @@ var require_crypto = __commonJS({
|
|
|
1190
1211
|
const u = { s: 1e3, m: 6e4, h: 36e5, d: 864e5 };
|
|
1191
1212
|
return Date.now() + parseInt(m[1], 10) * u[m[2]];
|
|
1192
1213
|
}
|
|
1214
|
+
var _PFX_SE = "secry:se:";
|
|
1215
|
+
var _PFX_SEI = "secry:sei:";
|
|
1216
|
+
var _CPX_SE = "sec:se:";
|
|
1217
|
+
var _CPX_SEI = "sec:sei:";
|
|
1218
|
+
var _SYM_VAL = /* @__PURE__ */ Symbol("sealed.value");
|
|
1219
|
+
function _makeSeal(value) {
|
|
1220
|
+
const obj = /* @__PURE__ */ Object.create(null);
|
|
1221
|
+
Object.defineProperty(obj, _SYM_VAL, { value, enumerable: false, configurable: false, writable: false });
|
|
1222
|
+
obj.toString = () => "[sealed]";
|
|
1223
|
+
obj.toJSON = () => "[sealed]";
|
|
1224
|
+
obj.valueOf = () => "[sealed]";
|
|
1225
|
+
obj[Symbol.toPrimitive] = () => "[sealed]";
|
|
1226
|
+
obj[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")] = () => "[sealed]";
|
|
1227
|
+
Object.freeze(obj);
|
|
1228
|
+
return obj;
|
|
1229
|
+
}
|
|
1230
|
+
function _unseal(s) {
|
|
1231
|
+
return s[_SYM_VAL];
|
|
1232
|
+
}
|
|
1233
|
+
var _MAX_IPS = 5;
|
|
1234
|
+
function sealEnc(value, masterKey, opts = {}) {
|
|
1235
|
+
const compact = !!opts.compact;
|
|
1236
|
+
const sl = compact ? _SL_C : _SL;
|
|
1237
|
+
const salt = (0, crypto_1.randomBytes)(sl);
|
|
1238
|
+
const nonce = (0, crypto_1.randomBytes)(_NL);
|
|
1239
|
+
const key = _kdf(masterKey, salt);
|
|
1240
|
+
let ips = [];
|
|
1241
|
+
if (opts.ip) {
|
|
1242
|
+
ips = Array.isArray(opts.ip) ? opts.ip : [opts.ip];
|
|
1243
|
+
if (!opts.ipForce && ips.length > _MAX_IPS)
|
|
1244
|
+
throw Object.assign(new Error(`max ${_MAX_IPS} IPs allowed (use ipForce to override)`), { code: "ERR_TOO_MANY_IPS" });
|
|
1245
|
+
}
|
|
1246
|
+
let inner;
|
|
1247
|
+
if (ips.length > 0) {
|
|
1248
|
+
const hashes = ips.map((ip) => (0, crypto_1.createHmac)("sha256", key).update(ip, "utf8").digest());
|
|
1249
|
+
inner = Buffer.concat([Buffer.from([1, ips.length]), ...hashes, Buffer.from(value, "utf8")]);
|
|
1250
|
+
} else {
|
|
1251
|
+
inner = Buffer.concat([Buffer.from([0, 0]), Buffer.from(value, "utf8")]);
|
|
1252
|
+
}
|
|
1253
|
+
const ciph = (0, crypto_1.createCipheriv)(_ALG_V1, key, nonce, { authTagLength: _TL });
|
|
1254
|
+
const body = Buffer.concat([ciph.update(inner), ciph.final()]);
|
|
1255
|
+
const tag = ciph.getAuthTag();
|
|
1256
|
+
const pfx = ips.length > 0 ? compact ? _CPX_SEI : _PFX_SEI : compact ? _CPX_SE : _PFX_SE;
|
|
1257
|
+
return pfx + Buffer.concat([salt, nonce, tag, body]).toString("base64url");
|
|
1258
|
+
}
|
|
1259
|
+
async function open(token, masterKey, cb, opts = {}) {
|
|
1260
|
+
const pfx = token.startsWith(_PFX_SEI) ? _PFX_SEI : token.startsWith(_CPX_SEI) ? _CPX_SEI : token.startsWith(_PFX_SE) ? _PFX_SE : token.startsWith(_CPX_SE) ? _CPX_SE : null;
|
|
1261
|
+
if (!pfx)
|
|
1262
|
+
throw Object.assign(new Error("invalid seal-enc token"), { code: "ERR_FORMAT" });
|
|
1263
|
+
const compact = pfx === _CPX_SE || pfx === _CPX_SEI;
|
|
1264
|
+
const sl = compact ? _SL_C : _SL;
|
|
1265
|
+
const payload = Buffer.from(token.slice(pfx.length), "base64url");
|
|
1266
|
+
const salt = payload.subarray(0, sl);
|
|
1267
|
+
const nonce = payload.subarray(sl, sl + _NL);
|
|
1268
|
+
const tag = payload.subarray(sl + _NL, sl + _NL + _TL);
|
|
1269
|
+
const body = payload.subarray(sl + _NL + _TL);
|
|
1270
|
+
const key = _kdf(masterKey, salt);
|
|
1271
|
+
let inner;
|
|
1272
|
+
try {
|
|
1273
|
+
const dc = (0, crypto_1.createDecipheriv)(_ALG_V1, key, nonce, { authTagLength: _TL });
|
|
1274
|
+
dc.setAuthTag(tag);
|
|
1275
|
+
inner = Buffer.concat([dc.update(body), dc.final()]);
|
|
1276
|
+
} catch {
|
|
1277
|
+
throw Object.assign(new Error("wrong master key or corrupted token"), { code: "ERR_AUTH" });
|
|
1278
|
+
}
|
|
1279
|
+
const hasIp = inner[0] === 1;
|
|
1280
|
+
if (hasIp) {
|
|
1281
|
+
if (!opts.ip)
|
|
1282
|
+
throw Object.assign(new Error("this token requires an ip"), { code: "ERR_IP_REQUIRED" });
|
|
1283
|
+
const count = inner[1];
|
|
1284
|
+
const hashes = [];
|
|
1285
|
+
for (let i = 0; i < count; i++)
|
|
1286
|
+
hashes.push(inner.subarray(2 + i * 32, 2 + (i + 1) * 32));
|
|
1287
|
+
const given = (0, crypto_1.createHmac)("sha256", key).update(opts.ip, "utf8").digest();
|
|
1288
|
+
const matched = hashes.some((h) => h.length === given.length && require("crypto").timingSafeEqual(h, given));
|
|
1289
|
+
if (!matched)
|
|
1290
|
+
throw Object.assign(new Error("ip mismatch"), { code: "ERR_IP_MISMATCH" });
|
|
1291
|
+
const value2 = inner.subarray(2 + count * 32).toString("utf8");
|
|
1292
|
+
const sealed2 = _makeSeal(value2);
|
|
1293
|
+
const result = await cb(sealed2);
|
|
1294
|
+
sealed2[_SYM_VAL];
|
|
1295
|
+
return result;
|
|
1296
|
+
}
|
|
1297
|
+
const value = inner.subarray(2).toString("utf8");
|
|
1298
|
+
const sealed = _makeSeal(value);
|
|
1299
|
+
return await cb(sealed);
|
|
1300
|
+
}
|
|
1193
1301
|
var _PFX_S1 = "secry:s1:";
|
|
1194
1302
|
var _PFX_S2 = "secry:s2:";
|
|
1303
|
+
var _CPX_S1 = "sec:s1:";
|
|
1304
|
+
var _CPX_S2 = "sec:s2:";
|
|
1195
1305
|
var _PEPPER_S2 = "enclove.secry.s2.pepper.v1";
|
|
1196
|
-
function seal(input, secret) {
|
|
1197
|
-
const
|
|
1306
|
+
function seal(input, secret, compact = false) {
|
|
1307
|
+
const sl = compact ? _SL_C : 16;
|
|
1308
|
+
const pfx = compact ? _CPX_S1 : _PFX_S1;
|
|
1309
|
+
const salt = (0, crypto_1.randomBytes)(sl);
|
|
1198
1310
|
const key = (0, crypto_1.scryptSync)(Buffer.from(secret, "utf8"), salt, 32, _SCRYPT);
|
|
1199
1311
|
const mac = (0, crypto_1.createHmac)("sha256", key).update(input, "utf8").digest();
|
|
1200
|
-
return
|
|
1312
|
+
return pfx + Buffer.concat([salt, mac]).toString("base64url");
|
|
1201
1313
|
}
|
|
1202
1314
|
function sealVerify(input, secret, token) {
|
|
1203
|
-
|
|
1315
|
+
const isCompact = token.startsWith(_CPX_S1);
|
|
1316
|
+
const pfx = isCompact ? _CPX_S1 : _PFX_S1;
|
|
1317
|
+
if (!token.startsWith(pfx) && !token.startsWith(_PFX_S1))
|
|
1204
1318
|
return false;
|
|
1205
1319
|
try {
|
|
1206
|
-
const
|
|
1207
|
-
|
|
1320
|
+
const sl = isCompact ? _SL_C : 16;
|
|
1321
|
+
const raw = Buffer.from(token.slice(pfx.length), "base64url");
|
|
1322
|
+
if (raw.length < sl + 32)
|
|
1208
1323
|
return false;
|
|
1209
|
-
const salt = raw.subarray(0,
|
|
1210
|
-
const mac = raw.subarray(
|
|
1324
|
+
const salt = raw.subarray(0, sl);
|
|
1325
|
+
const mac = raw.subarray(sl);
|
|
1211
1326
|
const key = (0, crypto_1.scryptSync)(Buffer.from(secret, "utf8"), salt, 32, _SCRYPT);
|
|
1212
1327
|
const exp = (0, crypto_1.createHmac)("sha256", key).update(input, "utf8").digest();
|
|
1213
1328
|
return exp.length === mac.length && require("crypto").timingSafeEqual(exp, mac);
|
|
@@ -1215,23 +1330,28 @@ var require_crypto = __commonJS({
|
|
|
1215
1330
|
return false;
|
|
1216
1331
|
}
|
|
1217
1332
|
}
|
|
1218
|
-
async function sealS2(input, secret) {
|
|
1219
|
-
const
|
|
1333
|
+
async function sealS2(input, secret, compact = false) {
|
|
1334
|
+
const sl = compact ? _SL_C : 32;
|
|
1335
|
+
const pfx = compact ? _CPX_S2 : _PFX_S2;
|
|
1336
|
+
const salt = (0, crypto_1.randomBytes)(sl);
|
|
1220
1337
|
const peppered = Buffer.from(_PEPPER_S2 + secret, "utf8");
|
|
1221
1338
|
const key = (0, crypto_1.scryptSync)(peppered, salt, 32, _SCRYPT_S2);
|
|
1222
1339
|
const { blake3: blake32 } = await Promise.resolve().then(() => __importStar((init_blake3(), __toCommonJS(blake3_exports))));
|
|
1223
1340
|
const out = blake32(new TextEncoder().encode(input), { key, dkLen: 64 });
|
|
1224
|
-
return
|
|
1341
|
+
return pfx + Buffer.concat([salt, Buffer.from(out)]).toString("base64url");
|
|
1225
1342
|
}
|
|
1226
1343
|
async function sealVerifyS2(input, secret, token) {
|
|
1227
|
-
|
|
1344
|
+
const isCompact = token.startsWith(_CPX_S2);
|
|
1345
|
+
const pfx = isCompact ? _CPX_S2 : _PFX_S2;
|
|
1346
|
+
if (!token.startsWith(pfx) && !token.startsWith(_PFX_S2))
|
|
1228
1347
|
return false;
|
|
1229
1348
|
try {
|
|
1230
|
-
const
|
|
1231
|
-
|
|
1349
|
+
const sl = isCompact ? _SL_C : 32;
|
|
1350
|
+
const raw = Buffer.from(token.slice(pfx.length), "base64url");
|
|
1351
|
+
if (raw.length < sl + 64)
|
|
1232
1352
|
return false;
|
|
1233
|
-
const salt = raw.subarray(0,
|
|
1234
|
-
const mac = raw.subarray(
|
|
1353
|
+
const salt = raw.subarray(0, sl);
|
|
1354
|
+
const mac = raw.subarray(sl);
|
|
1235
1355
|
const peppered = Buffer.from(_PEPPER_S2 + secret, "utf8");
|
|
1236
1356
|
const key = (0, crypto_1.scryptSync)(peppered, salt, 32, _SCRYPT_S2);
|
|
1237
1357
|
const { blake3: blake32 } = await Promise.resolve().then(() => __importStar((init_blake3(), __toCommonJS(blake3_exports))));
|
|
@@ -2110,8 +2230,48 @@ ${_c.gray}${"\u2500".repeat(48)}${_c.r}
|
|
|
2110
2230
|
var require_seal = __commonJS({
|
|
2111
2231
|
"dist/cmd/seal.js"(exports2) {
|
|
2112
2232
|
"use strict";
|
|
2233
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
2234
|
+
if (k2 === void 0) k2 = k;
|
|
2235
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
2236
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
2237
|
+
desc = { enumerable: true, get: function() {
|
|
2238
|
+
return m[k];
|
|
2239
|
+
} };
|
|
2240
|
+
}
|
|
2241
|
+
Object.defineProperty(o, k2, desc);
|
|
2242
|
+
}) : (function(o, m, k, k2) {
|
|
2243
|
+
if (k2 === void 0) k2 = k;
|
|
2244
|
+
o[k2] = m[k];
|
|
2245
|
+
}));
|
|
2246
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
2247
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
2248
|
+
}) : function(o, v) {
|
|
2249
|
+
o["default"] = v;
|
|
2250
|
+
});
|
|
2251
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
2252
|
+
var ownKeys = function(o) {
|
|
2253
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
2254
|
+
var ar = [];
|
|
2255
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
2256
|
+
return ar;
|
|
2257
|
+
};
|
|
2258
|
+
return ownKeys(o);
|
|
2259
|
+
};
|
|
2260
|
+
return function(mod) {
|
|
2261
|
+
if (mod && mod.__esModule) return mod;
|
|
2262
|
+
var result = {};
|
|
2263
|
+
if (mod != null) {
|
|
2264
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
2265
|
+
}
|
|
2266
|
+
__setModuleDefault(result, mod);
|
|
2267
|
+
return result;
|
|
2268
|
+
};
|
|
2269
|
+
})();
|
|
2113
2270
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2114
2271
|
exports2.cmdSeal = cmdSeal;
|
|
2272
|
+
exports2.cmdSei = cmdSei;
|
|
2273
|
+
exports2.cmdSeiOpen = cmdSeiOpen;
|
|
2274
|
+
exports2.cmdSealOpen = cmdSealOpen;
|
|
2115
2275
|
exports2.cmdSealVerify = cmdSealVerify;
|
|
2116
2276
|
var crypto_1 = require_crypto();
|
|
2117
2277
|
var password_1 = require_password();
|
|
@@ -2119,6 +2279,17 @@ var require_seal = __commonJS({
|
|
|
2119
2279
|
var clip_1 = require_clip();
|
|
2120
2280
|
var rc_1 = require_rc();
|
|
2121
2281
|
var args_12 = require_args();
|
|
2282
|
+
var os = __importStar(require("os"));
|
|
2283
|
+
function _localIp() {
|
|
2284
|
+
const ifaces = os.networkInterfaces();
|
|
2285
|
+
for (const name of Object.keys(ifaces)) {
|
|
2286
|
+
for (const iface of ifaces[name] ?? []) {
|
|
2287
|
+
if (iface.family === "IPv4" && !iface.internal)
|
|
2288
|
+
return iface.address;
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
return "127.0.0.1";
|
|
2292
|
+
}
|
|
2122
2293
|
async function cmdSeal(parsed2) {
|
|
2123
2294
|
const rc = (0, rc_1.loadRC)();
|
|
2124
2295
|
const text = parsed2.positional[0];
|
|
@@ -2129,8 +2300,49 @@ var require_seal = __commonJS({
|
|
|
2129
2300
|
const useClip = (0, args_12.hasFlag)(parsed2.flags, "clip") || !!rc.clip;
|
|
2130
2301
|
const quiet = (0, args_12.hasFlag)(parsed2.flags, "quiet") || (0, args_12.hasFlag)(parsed2.flags, "q");
|
|
2131
2302
|
const useS2 = (0, args_12.hasFlag)(parsed2.flags, "s2");
|
|
2303
|
+
const useEnc = (0, args_12.hasFlag)(parsed2.flags, "enc");
|
|
2304
|
+
const useIp = (0, args_12.hasFlag)(parsed2.flags, "ip");
|
|
2305
|
+
const ipForce = (0, args_12.hasFlag)(parsed2.flags, "ipf");
|
|
2306
|
+
const compact = (0, args_12.hasFlag)(parsed2.flags, "compact");
|
|
2132
2307
|
const t0 = Date.now();
|
|
2133
|
-
|
|
2308
|
+
if (useEnc) {
|
|
2309
|
+
let ips;
|
|
2310
|
+
if (useIp) {
|
|
2311
|
+
const extras = (0, args_12.getFlags)(parsed2.multi, "ip");
|
|
2312
|
+
ips = extras.length > 0 ? [_localIp(), ...extras] : [_localIp()];
|
|
2313
|
+
} else if (ipForce) {
|
|
2314
|
+
const extras = (0, args_12.getFlags)(parsed2.multi, "ipf");
|
|
2315
|
+
ips = extras.length > 0 ? [_localIp(), ...extras] : [_localIp()];
|
|
2316
|
+
}
|
|
2317
|
+
if (ips && !ipForce && ips.length > 5)
|
|
2318
|
+
(0, ui_12.err)("max 5 IPs allowed \u2014 use --ipf to override");
|
|
2319
|
+
const token2 = (0, crypto_1.sealEnc)(text, secret, { ip: ips, ipForce, compact });
|
|
2320
|
+
const elapsed2 = Date.now() - t0;
|
|
2321
|
+
if (!quiet) {
|
|
2322
|
+
(0, ui_12.section)("seal");
|
|
2323
|
+
(0, ui_12.box)([
|
|
2324
|
+
{ label: "input", value: text.length > 52 ? text.slice(0, 52) + "\u2026" : text },
|
|
2325
|
+
{ label: "algo", value: "AES-256-GCM / scrypt" },
|
|
2326
|
+
{ label: "mode", value: `reversible${ips ? ` \xB7 ip-bound (${ips.length})` : ""}${compact ? " \xB7 compact" : ""}` },
|
|
2327
|
+
...ips ? ips.map((ip, i) => ({ label: `ip[${i}]`, value: ip })) : [],
|
|
2328
|
+
{ label: "note", value: ips ? "use seal:open \u2014 any of the bound IPs are accepted" : "use seal:open to retrieve" },
|
|
2329
|
+
{ label: "token", value: token2 }
|
|
2330
|
+
]);
|
|
2331
|
+
(0, ui_12.ms)(elapsed2);
|
|
2332
|
+
}
|
|
2333
|
+
if (useClip) {
|
|
2334
|
+
const copied = (0, clip_1.copyToClipboard)(token2);
|
|
2335
|
+
if (copied) {
|
|
2336
|
+
const { info } = require_ui();
|
|
2337
|
+
if (!quiet)
|
|
2338
|
+
info("copied to clipboard");
|
|
2339
|
+
} else if (!quiet)
|
|
2340
|
+
(0, ui_12.warn)("--clip: no clipboard tool found");
|
|
2341
|
+
}
|
|
2342
|
+
(0, ui_12.data)(token2);
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
const token = useS2 ? await (0, crypto_1.sealS2)(text, secret, compact) : (0, crypto_1.seal)(text, secret, compact);
|
|
2134
2346
|
const elapsed = Date.now() - t0;
|
|
2135
2347
|
if (!quiet) {
|
|
2136
2348
|
(0, ui_12.section)("seal");
|
|
@@ -2138,7 +2350,8 @@ var require_seal = __commonJS({
|
|
|
2138
2350
|
{ label: "input", value: text.length > 52 ? text.slice(0, 52) + "\u2026" : text },
|
|
2139
2351
|
{ label: "algo", value: useS2 ? "BLAKE3 / scrypt N=2^16" : "HMAC-SHA256 / scrypt" },
|
|
2140
2352
|
{ label: "version", value: useS2 ? "s2" : "s1" },
|
|
2141
|
-
{ label: "
|
|
2353
|
+
{ label: "mode", value: "one-way" },
|
|
2354
|
+
{ label: "note", value: "cannot be reversed" },
|
|
2142
2355
|
{ label: "token", value: token }
|
|
2143
2356
|
]);
|
|
2144
2357
|
(0, ui_12.ms)(elapsed);
|
|
@@ -2156,6 +2369,104 @@ var require_seal = __commonJS({
|
|
|
2156
2369
|
}
|
|
2157
2370
|
(0, ui_12.data)(token);
|
|
2158
2371
|
}
|
|
2372
|
+
async function cmdSei(parsed2) {
|
|
2373
|
+
const rc = (0, rc_1.loadRC)();
|
|
2374
|
+
const text = parsed2.positional[0];
|
|
2375
|
+
if (!text)
|
|
2376
|
+
(0, ui_12.err)("missing <value> argument");
|
|
2377
|
+
const rawPw = (0, args_12.getFlag)(parsed2.flags, "sw") ?? rc.password;
|
|
2378
|
+
const secret = (0, password_1.resolvePassword)(rawPw ?? "");
|
|
2379
|
+
const ipForce = (0, args_12.hasFlag)(parsed2.flags, "ipf");
|
|
2380
|
+
const compact = (0, args_12.hasFlag)(parsed2.flags, "compact");
|
|
2381
|
+
const useClip = (0, args_12.hasFlag)(parsed2.flags, "clip") || !!rc.clip;
|
|
2382
|
+
const quiet = (0, args_12.hasFlag)(parsed2.flags, "quiet") || (0, args_12.hasFlag)(parsed2.flags, "q");
|
|
2383
|
+
const t0 = Date.now();
|
|
2384
|
+
const extraIp = (0, args_12.getFlags)(parsed2.multi, "ip");
|
|
2385
|
+
const extraIpf = (0, args_12.getFlags)(parsed2.multi, "ipf");
|
|
2386
|
+
const extras = ipForce ? extraIpf : extraIp;
|
|
2387
|
+
const ips = [_localIp(), ...extras];
|
|
2388
|
+
if (!ipForce && ips.length > 5)
|
|
2389
|
+
(0, ui_12.err)("max 5 IPs allowed \u2014 use --ipf to override");
|
|
2390
|
+
const token = (0, crypto_1.sealEnc)(text, secret, { ip: ips, ipForce, compact });
|
|
2391
|
+
const elapsed = Date.now() - t0;
|
|
2392
|
+
if (!quiet) {
|
|
2393
|
+
(0, ui_12.section)("sei");
|
|
2394
|
+
(0, ui_12.box)([
|
|
2395
|
+
{ label: "input", value: text.length > 52 ? text.slice(0, 52) + "\u2026" : text },
|
|
2396
|
+
{ label: "algo", value: "AES-256-GCM / scrypt" },
|
|
2397
|
+
{ label: "mode", value: `${compact ? "compact (sec:sei:)" : "full (secry:sei:)"} \xB7 ip-bound (${ips.length})` },
|
|
2398
|
+
...ips.map((ip, i) => ({ label: `ip[${i}]`, value: ip })),
|
|
2399
|
+
{ label: "note", value: "reversible \u2014 use sei:open to retrieve" },
|
|
2400
|
+
{ label: "token", value: token }
|
|
2401
|
+
]);
|
|
2402
|
+
(0, ui_12.ms)(elapsed);
|
|
2403
|
+
}
|
|
2404
|
+
if (useClip) {
|
|
2405
|
+
const copied = (0, clip_1.copyToClipboard)(token);
|
|
2406
|
+
if (copied) {
|
|
2407
|
+
const { info } = require_ui();
|
|
2408
|
+
if (!quiet)
|
|
2409
|
+
info("copied to clipboard");
|
|
2410
|
+
} else if (!quiet)
|
|
2411
|
+
(0, ui_12.warn)("--clip: no clipboard tool found");
|
|
2412
|
+
}
|
|
2413
|
+
(0, ui_12.data)(token);
|
|
2414
|
+
}
|
|
2415
|
+
async function cmdSeiOpen(parsed2) {
|
|
2416
|
+
const rc = (0, rc_1.loadRC)();
|
|
2417
|
+
const token = parsed2.positional[0];
|
|
2418
|
+
if (!token)
|
|
2419
|
+
(0, ui_12.err)("missing <token> argument");
|
|
2420
|
+
const rawPw = (0, args_12.getFlag)(parsed2.flags, "sw") ?? rc.password;
|
|
2421
|
+
if (!rawPw)
|
|
2422
|
+
(0, ui_12.err)("-sw <secret> is required");
|
|
2423
|
+
const secret = (0, password_1.resolvePassword)(rawPw);
|
|
2424
|
+
const quiet = (0, args_12.hasFlag)(parsed2.flags, "quiet") || (0, args_12.hasFlag)(parsed2.flags, "q");
|
|
2425
|
+
const t0 = Date.now();
|
|
2426
|
+
const detectedIp = _localIp();
|
|
2427
|
+
await (0, crypto_1.open)(token, secret, (sealed) => {
|
|
2428
|
+
const elapsed = Date.now() - t0;
|
|
2429
|
+
const value = (0, crypto_1._unseal)(sealed);
|
|
2430
|
+
if (!quiet) {
|
|
2431
|
+
(0, ui_12.section)("sei open");
|
|
2432
|
+
(0, ui_12.box)([
|
|
2433
|
+
{ label: "token", value: token.length > 52 ? token.slice(0, 52) + "\u2026" : token },
|
|
2434
|
+
{ label: "ip", value: detectedIp },
|
|
2435
|
+
{ label: "result", value }
|
|
2436
|
+
]);
|
|
2437
|
+
(0, ui_12.ms)(elapsed);
|
|
2438
|
+
}
|
|
2439
|
+
(0, ui_12.data)(value);
|
|
2440
|
+
}, { ip: detectedIp });
|
|
2441
|
+
}
|
|
2442
|
+
async function cmdSealOpen(parsed2) {
|
|
2443
|
+
const rc = (0, rc_1.loadRC)();
|
|
2444
|
+
const token = parsed2.positional[0];
|
|
2445
|
+
if (!token)
|
|
2446
|
+
(0, ui_12.err)("missing <token> argument");
|
|
2447
|
+
const rawPw = (0, args_12.getFlag)(parsed2.flags, "sw") ?? rc.password;
|
|
2448
|
+
if (!rawPw)
|
|
2449
|
+
(0, ui_12.err)("-sw <secret> is required");
|
|
2450
|
+
const secret = (0, password_1.resolvePassword)(rawPw);
|
|
2451
|
+
const quiet = (0, args_12.hasFlag)(parsed2.flags, "quiet") || (0, args_12.hasFlag)(parsed2.flags, "q");
|
|
2452
|
+
const t0 = Date.now();
|
|
2453
|
+
const needsIp = token.startsWith("secry:sei:") || token.startsWith("sec:sei:");
|
|
2454
|
+
const detectedIp = needsIp ? _localIp() : void 0;
|
|
2455
|
+
await (0, crypto_1.open)(token, secret, (sealed) => {
|
|
2456
|
+
const elapsed = Date.now() - t0;
|
|
2457
|
+
const value = (0, crypto_1._unseal)(sealed);
|
|
2458
|
+
if (!quiet) {
|
|
2459
|
+
(0, ui_12.section)("seal open");
|
|
2460
|
+
(0, ui_12.box)([
|
|
2461
|
+
{ label: "token", value: token.length > 52 ? token.slice(0, 52) + "\u2026" : token },
|
|
2462
|
+
...detectedIp ? [{ label: "ip", value: detectedIp }] : [],
|
|
2463
|
+
{ label: "result", value }
|
|
2464
|
+
]);
|
|
2465
|
+
(0, ui_12.ms)(elapsed);
|
|
2466
|
+
}
|
|
2467
|
+
(0, ui_12.data)(value);
|
|
2468
|
+
}, detectedIp ? { ip: detectedIp } : {});
|
|
2469
|
+
}
|
|
2159
2470
|
async function cmdSealVerify(parsed2) {
|
|
2160
2471
|
const rc = (0, rc_1.loadRC)();
|
|
2161
2472
|
const text = parsed2.positional[0];
|
|
@@ -7153,9 +7464,18 @@ async function main() {
|
|
|
7153
7464
|
case "seal":
|
|
7154
7465
|
await (0, seal_1.cmdSeal)(parsed);
|
|
7155
7466
|
break;
|
|
7467
|
+
case "seal:open":
|
|
7468
|
+
await (0, seal_1.cmdSealOpen)(parsed);
|
|
7469
|
+
break;
|
|
7156
7470
|
case "seal:verify":
|
|
7157
7471
|
await (0, seal_1.cmdSealVerify)(parsed);
|
|
7158
7472
|
break;
|
|
7473
|
+
case "sei":
|
|
7474
|
+
await (0, seal_1.cmdSei)(parsed);
|
|
7475
|
+
break;
|
|
7476
|
+
case "sei:open":
|
|
7477
|
+
await (0, seal_1.cmdSeiOpen)(parsed);
|
|
7478
|
+
break;
|
|
7159
7479
|
case "changelog":
|
|
7160
7480
|
case "changes":
|
|
7161
7481
|
await (0, changelog_1.cmdChangelog)(parsed);
|