UNPKG

@hazae41/kdbx

Version:

Rust-like KeePass (KDBX 4) file format for TypeScript

552 lines (548 loc) 22.5 kB
'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