UNPKG

@hazae41/kdbx

Version:

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

387 lines (383 loc) 13.5 kB
'use strict'; var tslib_es6 = require('../../../node_modules/tslib/tslib.es6.cjs'); var index = require('./dictionary/index.cjs'); var index$1 = require('./headers/inner/index.cjs'); var index$2 = require('./headers/outer/index.cjs'); var base64 = require('@hazae41/base64'); var binary = require('@hazae41/binary'); var cursor = require('@hazae41/cursor'); var index$4 = require('../../libs/gzip/index.cjs'); var index$5 = require('./hmac/index.cjs'); var index$3 = require('./headers/outer/compression/index.cjs'); var _a, _b, _c, _d, _e, _f, _g, _h; class PasswordKey { value; #class = _a; constructor(value) { this.value = value; } static async digestOrThrow(password) { const array = await crypto.subtle.digest("SHA-256", password); const bytes = new Uint8Array(array); return new _a(new binary.Opaque(bytes)); } } _a = PasswordKey; class CompositeKey { value; #class = _b; constructor(value) { this.value = value; } static async digestOrThrow(password) { const array = await crypto.subtle.digest("SHA-256", password.value.bytes); const bytes = new Uint8Array(array); return new _b(new binary.Opaque(bytes)); } } _b = CompositeKey; class DerivedKey { value; #class = _c; constructor(value) { this.value = value; } } _c = DerivedKey; class PreMasterKey { seed; hash; #class = _d; constructor(seed, hash) { this.seed = seed; this.hash = hash; } sizeOrThrow() { return 32 + 32; } writeOrThrow(cursor) { cursor.writeOrThrow(this.seed.bytes); cursor.writeOrThrow(this.hash.value.bytes); } async digestOrThrow() { const input = binary.Writable.writeToBytesOrThrow(this); const digest = await crypto.subtle.digest("SHA-256", input); const output = new Uint8Array(digest); return new MasterKey(new binary.Opaque(output)); } } _d = PreMasterKey; class MasterKey { value; #class = _e; constructor(value) { this.value = value; } } _e = MasterKey; class PreHmacMasterKey { seed; hash; #class = _f; constructor(seed, hash) { this.seed = seed; this.hash = hash; } sizeOrThrow() { return 32 + 32 + 1; } writeOrThrow(cursor) { cursor.writeOrThrow(this.seed.bytes); cursor.writeOrThrow(this.hash.value.bytes); cursor.writeUint8OrThrow(1); } async digestOrThrow() { const input = binary.Writable.writeToBytesOrThrow(this); const digest = await crypto.subtle.digest("SHA-512", input); const output = new Uint8Array(digest); return new HmacMasterKey(new binary.Opaque(output)); } } _f = PreHmacMasterKey; class HmacMasterKey { bytes; #class = _g; constructor(bytes) { this.bytes = bytes; } } _g = HmacMasterKey; class MasterKeys { encrypter; authifier; #class = _h; constructor(encrypter, authifier) { this.encrypter = encrypter; this.authifier = authifier; } } _h = MasterKeys; exports.Database = void 0; (function (Database) { class Decrypted { outer; inner; constructor(outer, inner) { this.outer = outer; this.inner = inner; } async rotateOrThrow(composite) { return new Decrypted(await this.outer.rotateOrThrow(composite), await this.inner.rotateOrThrow()); } async encryptOrThrow() { const cipher = await this.inner.headers.getCipherOrThrow(); const $$values = this.inner.content.value.document.querySelectorAll("Value[Protected='True']"); for (let i = 0; i < $$values.length; i++) { const env_1 = { stack: [], error: void 0, hasError: false }; try { const $value = $$values[i]; const decrypted = new TextEncoder().encode($value.innerHTML); const encrypted = tslib_es6.__addDisposableResource(env_1, cipher.applyOrThrow(decrypted), false); $value.innerHTML = base64.Base64.encodePaddedOrThrow(encrypted.bytes); } catch (e_1) { env_1.error = e_1; env_1.hasError = true; } finally { tslib_es6.__disposeResources(env_1); } } { const { cipher, iv, compression } = this.outer.data.data.value.headers; const degzipped = binary.Writable.writeToBytesOrThrow(this.inner.recomputeOrThrow()); const engzipped = compression === index$3.Compression.Gzip ? new Uint8Array(await index$4.gzip(degzipped)) : degzipped; const encrypted = await cipher.encryptOrThrow(this.outer.keys.encrypter.value.bytes, iv.bytes, engzipped); const blocks = new Array(); const cursor$1 = new cursor.Cursor(encrypted); const splits = cursor$1.splitOrThrow(1048576); let index = 0n; for (let x = splits.next(); true; index++, x = splits.next()) { if (x.done) break; blocks.push(await BlockWithIndex.fromOrThrow(this.outer.keys, index, x.value)); continue; } blocks.push(await BlockWithIndex.fromOrThrow(this.outer.keys, index, new Uint8Array(0))); return new Encrypted(this.outer.data, new Blocks(blocks)); } } } Database.Decrypted = Decrypted; class Encrypted { outer; inner; constructor(outer, inner) { this.outer = outer; this.inner = inner; } sizeOrThrow() { return this.outer.sizeOrThrow() + this.inner.sizeOrThrow(); } writeOrThrow(cursor) { this.outer.writeOrThrow(cursor); this.inner.writeOrThrow(cursor); } cloneOrThrow() { return new Encrypted(this.outer.cloneOrThrow(), this.inner.cloneOrThrow()); } async decryptOrThrow(composite) { const { cipher, iv, compression } = this.outer.data.value.headers; const keys = await this.outer.deriveOrThrow(composite); await this.outer.verifyOrThrow(keys); const length = this.inner.blocks.reduce((a, b) => a + b.block.data.bytes.length, 0); const cursor$1 = new cursor.Cursor(new Uint8Array(length)); for (const block of this.inner.blocks) { await block.verifyOrThrow(keys); cursor$1.writeOrThrow(block.block.data.bytes); continue; } const decrypted = await cipher.decryptOrThrow(keys.encrypter.value.bytes, iv.bytes, cursor$1.bytes); const degzipped = compression === index$3.Compression.Gzip ? await index$4.gunzip(decrypted) : decrypted; const inner = binary.Readable.readFromBytesOrThrow(index$1.HeadersAndContentWithBytes, degzipped); { const cipher = await inner.headers.getCipherOrThrow(); const $$values = inner.content.value.document.querySelectorAll("Value[Protected='True']"); for (let i = 0; i < $$values.length; i++) { const env_2 = { stack: [], error: void 0, hasError: false }; try { const $value = $$values[i]; const encrypted = base64.Base64.decodePaddedOrThrow($value.innerHTML); const decrypted = tslib_es6.__addDisposableResource(env_2, cipher.applyOrThrow(encrypted), false); $value.innerHTML = new TextDecoder().decode(decrypted.bytes); } catch (e_2) { env_2.error = e_2; env_2.hasError = true; } finally { tslib_es6.__disposeResources(env_2); } } const outer = new index$2.MagicAndVersionAndHeadersWithBytesWithHashAndHmacWithKeys(this.outer, keys); return new Decrypted(outer, inner); } } } Database.Encrypted = Encrypted; (function (Encrypted) { function readOrThrow(cursor) { const head = index$2.MagicAndVersionAndHeadersWithBytesWithHashAndHmac.readOrThrow(cursor); const body = Blocks.readOrThrow(cursor); return new Encrypted(head, body); } Encrypted.readOrThrow = readOrThrow; })(Encrypted = Database.Encrypted || (Database.Encrypted = {})); })(exports.Database || (exports.Database = {})); class Blocks { blocks; constructor(blocks) { this.blocks = blocks; } sizeOrThrow() { return this.blocks.reduce((a, b) => a + b.sizeOrThrow(), 0); } writeOrThrow(cursor) { for (const block of this.blocks) block.writeOrThrow(cursor); return; } cloneOrThrow() { return new Blocks(this.blocks.map(block => block.cloneOrThrow())); } } (function (Blocks) { function readOrThrow(cursor) { const blocks = new Array(); for (let index = 0n; true; index++) { const block = Block.readOrThrow(cursor); blocks.push(new BlockWithIndex(index, block)); if (block.data.bytes.length === 0) break; continue; } return new Blocks(blocks); } Blocks.readOrThrow = readOrThrow; })(Blocks || (Blocks = {})); class BlockWithIndexPreHmacData { index; block; constructor(index, block) { this.index = index; this.block = block; } sizeOrThrow() { return 8 + 4 + this.block.bytes.length; } writeOrThrow(cursor) { cursor.writeUint64OrThrow(this.index, true); cursor.writeUint32OrThrow(this.block.bytes.length, true); cursor.writeOrThrow(this.block.bytes); } } class BlockWithIndex { index; block; constructor(index, block) { this.index = index; this.block = block; } sizeOrThrow() { return this.block.sizeOrThrow(); } writeOrThrow(cursor) { this.block.writeOrThrow(cursor); } cloneOrThrow() { return new BlockWithIndex(this.index, this.block.cloneOrThrow()); } async verifyOrThrow(keys) { const { index } = this; const major = keys.authifier.bytes; const key = await new index$5.PreHmacKey(index, major).digestOrThrow(); const preimage = new BlockWithIndexPreHmacData(this.index, this.block.data); const prebytes = binary.Writable.writeToBytesOrThrow(preimage); await key.verifyOrThrow(prebytes, this.block.hmac.bytes); } } (function (BlockWithIndex) { async function fromOrThrow(keys, index, data) { const major = keys.authifier.bytes; const key = await new index$5.PreHmacKey(index, major).digestOrThrow(); const preimage = new BlockWithIndexPreHmacData(index, new binary.Opaque(data)); const prebytes = binary.Writable.writeToBytesOrThrow(preimage); const hmac = new binary.Opaque(await key.signOrThrow(prebytes)); const block = new Block(hmac, new binary.Opaque(data)); return new BlockWithIndex(index, block); } BlockWithIndex.fromOrThrow = fromOrThrow; })(BlockWithIndex || (BlockWithIndex = {})); class Block { hmac; data; constructor(hmac, data) { this.hmac = hmac; this.data = data; } sizeOrThrow() { return 32 + 4 + this.data.bytes.length; } writeOrThrow(cursor) { cursor.writeOrThrow(this.hmac.bytes); cursor.writeUint32OrThrow(this.data.bytes.length, true); cursor.writeOrThrow(this.data.bytes); } cloneOrThrow() { return new Block(this.hmac.cloneOrThrow(), this.data.cloneOrThrow()); } } (function (Block) { function readOrThrow(cursor) { const hmac = new binary.Opaque(cursor.readOrThrow(32)); const size = cursor.readUint32OrThrow(true); const data = new binary.Opaque(cursor.readOrThrow(size)); return new Block(hmac, data); } Block.readOrThrow = readOrThrow; })(Block || (Block = {})); Object.defineProperty(exports, "Dictionary", { enumerable: true, get: function () { return index.Dictionary; } }); Object.defineProperty(exports, "Entries", { enumerable: true, get: function () { return index.Entries; } }); Object.defineProperty(exports, "Entry", { enumerable: true, get: function () { return index.Entry; } }); Object.defineProperty(exports, "Key", { enumerable: true, get: function () { return index.Key; } }); Object.defineProperty(exports, "Value", { enumerable: true, get: function () { return index.Value; } }); exports.Inner = index$1; exports.Outer = index$2; exports.Block = Block; exports.BlockWithIndex = BlockWithIndex; exports.BlockWithIndexPreHmacData = BlockWithIndexPreHmacData; exports.Blocks = Blocks; exports.CompositeKey = CompositeKey; exports.DerivedKey = DerivedKey; exports.HmacMasterKey = HmacMasterKey; exports.MasterKey = MasterKey; exports.MasterKeys = MasterKeys; exports.PasswordKey = PasswordKey; exports.PreHmacMasterKey = PreHmacMasterKey; exports.PreMasterKey = PreMasterKey; //# sourceMappingURL=index.cjs.map