@hazae41/kdbx
Version:
Rust-like KeePass (KDBX 4) file format for TypeScript
552 lines (548 loc) • 22.5 kB
JavaScript
'use strict';
var tslib_es6 = require('../../../../../node_modules/tslib/tslib.es6.cjs');
var index = require('./cipher/index.cjs');
var index$1 = require('./compression/index.cjs');
var argon2 = require('@hazae41/argon2');
var binary = require('@hazae41/binary');
var index$3 = require('../../../../libs/bytes/index.cjs');
var index$7 = require('../../../../libs/uuid/index.cjs');
var index$5 = require('../../dictionary/index.cjs');
var index$2 = require('../../hmac/index.cjs');
var index$6 = require('../../index.cjs');
var index$4 = require('../../vector/index.cjs');
class Version {
major;
minor;
constructor(major, minor) {
this.major = major;
this.minor = minor;
}
sizeOrThrow() {
return 2 + 2;
}
writeOrThrow(cursor) {
cursor.writeUint16OrThrow(this.minor, true);
cursor.writeUint16OrThrow(this.major, true);
}
cloneOrThrow() {
return this;
}
}
class MagicAndVersionAndHeadersWithBytesWithHashAndHmacWithKeys {
data;
keys;
constructor(data, keys) {
this.data = data;
this.keys = keys;
}
sizeOrThrow() {
return this.data.sizeOrThrow();
}
writeOrThrow(cursor) {
this.data.writeOrThrow(cursor);
}
async rotateOrThrow(composite) {
const data = this.data.data.rotateOrThrow();
const keys = await data.deriveOrThrow(composite);
const hash = await MagicAndVersionAndHeadersWithBytesWithHashAndHmac.computeOrThrow(data, keys);
return new MagicAndVersionAndHeadersWithBytesWithHashAndHmacWithKeys(hash, keys);
}
}
class MagicAndVersionAndHeadersWithBytesWithHashAndHmac {
data;
hash;
hmac;
constructor(data, hash, hmac) {
this.data = data;
this.hash = hash;
this.hmac = hmac;
}
static async computeOrThrow(data, keys) {
const index = 0xffffffffffffffffn;
const major = keys.authifier.bytes;
const key = await new index$2.PreHmacKey(index, major).digestOrThrow();
const hash = new Uint8Array(await crypto.subtle.digest("SHA-256", data.bytes.bytes));
const hmac = new Uint8Array(await key.signOrThrow(data.bytes.bytes));
return new MagicAndVersionAndHeadersWithBytesWithHashAndHmac(data, new binary.Opaque(hash), new binary.Opaque(hmac));
}
async verifyOrThrow(keys) {
const hash = new Uint8Array(await crypto.subtle.digest("SHA-256", this.data.bytes.bytes));
if (!index$3.Bytes.equals(hash, this.hash.bytes))
throw new Error();
const index = 0xffffffffffffffffn;
const major = keys.authifier.bytes;
const key = await new index$2.PreHmacKey(index, major).digestOrThrow();
await key.verifyOrThrow(this.data.bytes.bytes, this.hmac.bytes);
}
sizeOrThrow() {
return this.data.sizeOrThrow() + 32 + 32;
}
writeOrThrow(cursor) {
this.data.writeOrThrow(cursor);
cursor.writeOrThrow(this.hash.bytes);
cursor.writeOrThrow(this.hmac.bytes);
}
cloneOrThrow() {
const data = this.data.cloneOrThrow();
const hash = this.hash.cloneOrThrow();
const hmac = this.hmac.cloneOrThrow();
return new MagicAndVersionAndHeadersWithBytesWithHashAndHmac(data, hash, hmac);
}
async deriveOrThrow(composite) {
return await this.data.deriveOrThrow(composite);
}
}
(function (MagicAndVersionAndHeadersWithBytesWithHashAndHmac) {
function readOrThrow(cursor) {
const data = MagicAndVersionAndHeadersWithBytes.readOrThrow(cursor);
const hash = new binary.Opaque(cursor.readOrThrow(32));
const hmac = new binary.Opaque(cursor.readOrThrow(32));
return new MagicAndVersionAndHeadersWithBytesWithHashAndHmac(data, hash, hmac);
}
MagicAndVersionAndHeadersWithBytesWithHashAndHmac.readOrThrow = readOrThrow;
})(MagicAndVersionAndHeadersWithBytesWithHashAndHmac || (MagicAndVersionAndHeadersWithBytesWithHashAndHmac = {}));
class MagicAndVersionAndHeadersWithBytes {
value;
bytes;
constructor(value, bytes) {
this.value = value;
this.bytes = bytes;
}
static computeOrThrow(value) {
const bytes = new binary.Opaque(binary.Writable.writeToBytesOrThrow(value));
return new MagicAndVersionAndHeadersWithBytes(value, bytes);
}
rotateOrThrow() {
return MagicAndVersionAndHeadersWithBytes.computeOrThrow(this.value.rotateOrThrow());
}
sizeOrThrow() {
return this.bytes.bytes.length;
}
writeOrThrow(cursor) {
cursor.writeOrThrow(this.bytes.bytes);
}
cloneOrThrow() {
const value = this.value.cloneOrThrow();
const bytes = this.bytes.cloneOrThrow();
return new MagicAndVersionAndHeadersWithBytes(value, bytes);
}
async deriveOrThrow(composite) {
return await this.value.deriveOrThrow(composite);
}
}
(function (MagicAndVersionAndHeadersWithBytes) {
function readOrThrow(cursor) {
const start = cursor.offset;
const value = MagicAndVersionAndHeaders.readOrThrow(cursor);
const bytes = new binary.Opaque(cursor.bytes.subarray(start, cursor.offset));
return new MagicAndVersionAndHeadersWithBytes(value, bytes);
}
MagicAndVersionAndHeadersWithBytes.readOrThrow = readOrThrow;
})(MagicAndVersionAndHeadersWithBytes || (MagicAndVersionAndHeadersWithBytes = {}));
class MagicAndVersionAndHeaders {
version;
headers;
constructor(version, headers) {
this.version = version;
this.headers = headers;
}
rotateOrThrow() {
const { version } = this;
const headers = this.headers.rotateOrThrow();
return new MagicAndVersionAndHeaders(version, headers);
}
sizeOrThrow() {
return 4 + 4 + this.version.sizeOrThrow() + this.headers.sizeOrThrow();
}
writeOrThrow(cursor) {
cursor.writeUint32OrThrow(0x9AA2D903, true);
cursor.writeUint32OrThrow(0xB54BFB67, true);
this.version.writeOrThrow(cursor);
this.headers.writeOrThrow(cursor);
}
cloneOrThrow() {
const version = this.version.cloneOrThrow();
const headers = this.headers.cloneOrThrow();
return new MagicAndVersionAndHeaders(version, headers);
}
async deriveOrThrow(composite) {
return await this.headers.deriveOrThrow(composite);
}
}
(function (MagicAndVersionAndHeaders) {
function readOrThrow(cursor) {
const alpha = cursor.readUint32OrThrow(true);
if (alpha !== 0x9AA2D903)
throw new Error();
const beta = cursor.readUint32OrThrow(true);
if (beta !== 0xB54BFB67)
throw new Error();
const minor = cursor.readUint16OrThrow(true);
const major = cursor.readUint16OrThrow(true);
const version = new Version(major, minor);
if (major !== 4)
throw new Error();
const headers = Headers.readOrThrow(cursor);
return new MagicAndVersionAndHeaders(version, headers);
}
MagicAndVersionAndHeaders.readOrThrow = readOrThrow;
})(MagicAndVersionAndHeaders || (MagicAndVersionAndHeaders = {}));
class Headers {
value;
constructor(value) {
this.value = value;
}
get cipher() {
return this.value.value[2][0];
}
get compression() {
return this.value.value[3][0];
}
get seed() {
return this.value.value[4][0];
}
get iv() {
return this.value.value[7][0];
}
get kdf() {
return this.value.value[11][0];
}
get custom() {
return this.value.value[12]?.[0];
}
rotateOrThrow() {
const { cipher, compression, custom } = this;
const seed = new binary.Opaque(crypto.getRandomValues(new Uint8Array(32)));
const iv = new binary.Opaque(crypto.getRandomValues(new Uint8Array(cipher.IV.length)));
const kdf = this.kdf.rotateOrThrow();
return Headers.initOrThrow({ cipher, compression, seed, iv, kdf, custom });
}
sizeOrThrow() {
return this.value.sizeOrThrow();
}
writeOrThrow(cursor) {
this.value.writeOrThrow(cursor);
}
cloneOrThrow() {
return binary.Readable.readFromBytesOrThrow(Headers, binary.Writable.writeToBytesOrThrow(this));
}
async deriveOrThrow(composite) {
const { seed } = this;
const derived = this.kdf.deriveOrThrow(composite);
const encrypter = await new index$6.PreMasterKey(seed, derived).digestOrThrow();
const authifier = await new index$6.PreHmacMasterKey(seed, derived).digestOrThrow();
return new index$6.MasterKeys(encrypter, authifier);
}
}
(function (Headers) {
function initOrThrow(init) {
const { cipher, compression, seed, iv, kdf, custom } = init;
if (iv.bytes.length !== cipher.IV.length)
throw new Error();
const indexed = {
2: [cipher],
3: [compression],
4: [new binary.Opaque(seed.bytes)],
7: [new binary.Opaque(iv.bytes)],
11: [kdf],
12: custom != null ? [custom] : undefined
};
return new Headers(index$4.Vector.initOrThrow(indexed));
}
Headers.initOrThrow = initOrThrow;
function readOrThrow(cursor) {
const vector = index$4.Vector.readOrThrow(cursor);
if (vector.value[2].length !== 1)
throw new Error();
if (vector.value[3].length !== 1)
throw new Error();
if (vector.value[4].length !== 1)
throw new Error();
if (vector.value[4][0].bytes.length !== 32)
throw new Error();
if (vector.value[7].length !== 1)
throw new Error();
if (vector.value[11].length !== 1)
throw new Error();
if (vector.value[12] != null && vector.value[12].length !== 1)
throw new Error();
const indexed = {
2: [vector.value[2][0].readIntoOrThrow(index.Cipher)],
3: [vector.value[3][0].readIntoOrThrow(index$1.Compression)],
4: [vector.value[4][0]],
7: [vector.value[7][0]],
11: [vector.value[11][0].readIntoOrThrow(exports.KdfParameters)],
12: vector.value[12] != null ? [vector.value[12][0].readIntoOrThrow(index$5.Dictionary)] : undefined
};
return new Headers(new index$4.Vector(vector.bytes, indexed));
}
Headers.readOrThrow = readOrThrow;
})(Headers || (Headers = {}));
class Seed {
bytes;
constructor(bytes) {
this.bytes = bytes;
}
static readOrThrow(cursor) {
return new Seed(new binary.Opaque(cursor.readOrThrow(32)));
}
}
exports.KdfParameters = void 0;
(function (KdfParameters) {
class AesKdf {
value;
constructor(value) {
this.value = value;
}
get seed() {
return this.value.entries.value["S"].value;
}
get rounds() {
return this.value.entries.value["R"].value;
}
rotateOrThrow() {
const { version } = this.value;
const $UUID = this.value.entries.value["$UUID"];
const R = this.value.entries.value["R"];
const S = new index$5.Value.Bytes(new binary.Opaque(crypto.getRandomValues(new Uint8Array(32))));
const value = index$5.Dictionary.initOrThrow(version, { $UUID, R, S });
return new AesKdf(value);
}
deriveOrThrow(key) {
throw new Error();
}
sizeOrThrow() {
return this.value.sizeOrThrow();
}
writeOrThrow(cursor) {
this.value.writeOrThrow(cursor);
}
cloneOrThrow() {
return new AesKdf(this.value.cloneOrThrow());
}
}
KdfParameters.AesKdf = AesKdf;
(function (AesKdf) {
AesKdf.$UUID = "c9d9f39a-628a-4460-bf74-0d08c18a4fea";
function parseOrThrow(dictionary) {
const { version, entries } = dictionary;
if (entries.value["$UUID"] instanceof index$5.Value.Bytes === false)
throw new Error();
const $UUID = entries.value["$UUID"];
if (entries.value.R instanceof index$5.Value.UInt32 === false)
throw new Error();
const R = entries.value.R;
if (entries.value.S instanceof index$5.Value.Bytes === false)
throw new Error();
const S = entries.value.S;
return new KdfParameters.AesKdf(new index$5.Dictionary(version, new index$5.Entries(entries.bytes, { $UUID, R, S })));
}
AesKdf.parseOrThrow = parseOrThrow;
})(AesKdf = KdfParameters.AesKdf || (KdfParameters.AesKdf = {}));
class Argon2d {
value;
constructor(value) {
this.value = value;
}
get salt() {
return this.value.entries.value["S"].value;
}
get parallelism() {
return this.value.entries.value["P"].value;
}
get memory() {
return this.value.entries.value["M"].value;
}
get iterations() {
return this.value.entries.value["I"].value;
}
get version() {
return this.value.entries.value["V"].value;
}
rotateOrThrow() {
const { version } = this.value;
const $UUID = this.value.entries.value["$UUID"];
const S = new index$5.Value.Bytes(new binary.Opaque(crypto.getRandomValues(new Uint8Array(32))));
const P = this.value.entries.value.P;
const M = this.value.entries.value.M;
const I = this.value.entries.value.I;
const V = this.value.entries.value.V;
const value = index$5.Dictionary.initOrThrow(version, { $UUID, S, P, M, I, V });
return new Argon2d(value);
}
deriveOrThrow(key) {
const env_1 = { stack: [], error: void 0, hasError: false };
try {
const { version, iterations, parallelism, memory, salt } = this;
const { Memory, Argon2Deriver } = argon2.Argon2.get().getOrThrow();
const mkey = tslib_es6.__addDisposableResource(env_1, Memory.importOrThrow(key.value.bytes), false);
const msalt = tslib_es6.__addDisposableResource(env_1, Memory.importOrThrow(salt.bytes), false);
const deriver = tslib_es6.__addDisposableResource(env_1, Argon2Deriver.createOrThrow("argon2d", version, Number(memory) / 1024, Number(iterations), parallelism), false);
const derived = tslib_es6.__addDisposableResource(env_1, deriver.deriveOrThrow(mkey, msalt), false);
return new index$6.DerivedKey(new binary.Opaque(new Uint8Array(derived.bytes)));
}
catch (e_1) {
env_1.error = e_1;
env_1.hasError = true;
}
finally {
tslib_es6.__disposeResources(env_1);
}
}
sizeOrThrow() {
return this.value.sizeOrThrow();
}
writeOrThrow(cursor) {
this.value.writeOrThrow(cursor);
}
cloneOrThrow() {
return new Argon2d(this.value.cloneOrThrow());
}
}
KdfParameters.Argon2d = Argon2d;
(function (Argon2d) {
Argon2d.$UUID = "ef636ddf-8c29-444b-91f7-a9a403e30a0c";
function parseOrThrow(dictionary) {
const { version, entries } = dictionary;
if (dictionary.entries.value["$UUID"] instanceof index$5.Value.Bytes === false)
throw new Error();
const $UUID = dictionary.entries.value["$UUID"];
if (dictionary.entries.value.S instanceof index$5.Value.Bytes === false)
throw new Error();
const S = dictionary.entries.value.S;
if (dictionary.entries.value.P instanceof index$5.Value.UInt32 === false)
throw new Error();
const P = dictionary.entries.value.P;
if (dictionary.entries.value.M instanceof index$5.Value.UInt64 === false)
throw new Error();
const M = dictionary.entries.value.M;
if (dictionary.entries.value.I instanceof index$5.Value.UInt64 === false)
throw new Error();
const I = dictionary.entries.value.I;
if (dictionary.entries.value.V instanceof index$5.Value.UInt32 === false)
throw new Error();
const V = dictionary.entries.value.V;
return new KdfParameters.Argon2d(new index$5.Dictionary(version, new index$5.Entries(entries.bytes, { $UUID, S, P, M, I, V })));
}
Argon2d.parseOrThrow = parseOrThrow;
})(Argon2d = KdfParameters.Argon2d || (KdfParameters.Argon2d = {}));
class Argon2id {
value;
constructor(value) {
this.value = value;
}
get salt() {
return this.value.entries.value["S"].value;
}
get parallelism() {
return this.value.entries.value["P"].value;
}
get memory() {
return this.value.entries.value["M"].value;
}
get iterations() {
return this.value.entries.value["I"].value;
}
get version() {
return this.value.entries.value["V"].value;
}
rotateOrThrow() {
const { version } = this.value;
const $UUID = this.value.entries.value["$UUID"];
const S = new index$5.Value.Bytes(new binary.Opaque(crypto.getRandomValues(new Uint8Array(32))));
const P = this.value.entries.value.P;
const M = this.value.entries.value.M;
const I = this.value.entries.value.I;
const V = this.value.entries.value.V;
const value = index$5.Dictionary.initOrThrow(version, { $UUID, S, P, M, I, V });
return new Argon2d(value);
}
deriveOrThrow(key) {
const env_2 = { stack: [], error: void 0, hasError: false };
try {
const { version, iterations, parallelism, memory, salt } = this;
const { Memory, Argon2Deriver } = argon2.Argon2.get().getOrThrow();
const mkey = tslib_es6.__addDisposableResource(env_2, Memory.importOrThrow(key.value.bytes), false);
const msalt = tslib_es6.__addDisposableResource(env_2, Memory.importOrThrow(salt.bytes), false);
const deriver = tslib_es6.__addDisposableResource(env_2, Argon2Deriver.createOrThrow("argon2id", version, Number(memory) / 1024, Number(iterations), parallelism), false);
const derived = tslib_es6.__addDisposableResource(env_2, deriver.deriveOrThrow(mkey, msalt), false);
return new index$6.DerivedKey(new binary.Opaque(new Uint8Array(derived.bytes)));
}
catch (e_2) {
env_2.error = e_2;
env_2.hasError = true;
}
finally {
tslib_es6.__disposeResources(env_2);
}
}
sizeOrThrow() {
return this.value.sizeOrThrow();
}
writeOrThrow(cursor) {
this.value.writeOrThrow(cursor);
}
cloneOrThrow() {
return new Argon2id(this.value.cloneOrThrow());
}
}
KdfParameters.Argon2id = Argon2id;
(function (Argon2id) {
Argon2id.$UUID = "9e298b19-56db-4773-b23d-fc3ec6f0a1e6";
function parseOrThrow(dictionary) {
const { version, entries } = dictionary;
if (entries.value["$UUID"] instanceof index$5.Value.Bytes === false)
throw new Error();
const $UUID = entries.value["$UUID"];
if (entries.value.S instanceof index$5.Value.Bytes === false)
throw new Error();
const S = entries.value.S;
if (entries.value.P instanceof index$5.Value.UInt32 === false)
throw new Error();
const P = entries.value.P;
if (entries.value.M instanceof index$5.Value.UInt64 === false)
throw new Error();
const M = entries.value.M;
if (entries.value.I instanceof index$5.Value.UInt64 === false)
throw new Error();
const I = entries.value.I;
if (entries.value.V instanceof index$5.Value.UInt32 === false)
throw new Error();
const V = entries.value.V;
return new KdfParameters.Argon2id(new index$5.Dictionary(version, new index$5.Entries(entries.bytes, { $UUID, S, P, M, I, V })));
}
Argon2id.parseOrThrow = parseOrThrow;
})(Argon2id = KdfParameters.Argon2id || (KdfParameters.Argon2id = {}));
function readOrThrow(cursor) {
const dictionary = index$5.Dictionary.readOrThrow(cursor);
if (dictionary.entries.value["$UUID"] instanceof index$5.Value.Bytes === false)
throw new Error();
const $UUID = index$7.StringAsUuid.from(dictionary.entries.value["$UUID"].value.bytes);
if (![KdfParameters.AesKdf.$UUID, KdfParameters.Argon2d.$UUID, KdfParameters.Argon2id.$UUID].includes($UUID))
throw new Error();
if ($UUID === KdfParameters.AesKdf.$UUID)
return KdfParameters.AesKdf.parseOrThrow(dictionary);
if ($UUID === KdfParameters.Argon2d.$UUID)
return KdfParameters.Argon2d.parseOrThrow(dictionary);
if ($UUID === KdfParameters.Argon2id.$UUID)
return KdfParameters.Argon2id.parseOrThrow(dictionary);
throw new Error();
}
KdfParameters.readOrThrow = readOrThrow;
})(exports.KdfParameters || (exports.KdfParameters = {}));
Object.defineProperty(exports, "Cipher", {
enumerable: true,
get: function () { return index.Cipher; }
});
Object.defineProperty(exports, "Compression", {
enumerable: true,
get: function () { return index$1.Compression; }
});
exports.Headers = Headers;
exports.MagicAndVersionAndHeaders = MagicAndVersionAndHeaders;
exports.MagicAndVersionAndHeadersWithBytes = MagicAndVersionAndHeadersWithBytes;
exports.MagicAndVersionAndHeadersWithBytesWithHashAndHmac = MagicAndVersionAndHeadersWithBytesWithHashAndHmac;
exports.MagicAndVersionAndHeadersWithBytesWithHashAndHmacWithKeys = MagicAndVersionAndHeadersWithBytesWithHashAndHmacWithKeys;
exports.Seed = Seed;
exports.Version = Version;
//# sourceMappingURL=index.cjs.map