@hazae41/kdbx
Version:
Rust-like KeePass (KDBX 4) file format for TypeScript
387 lines (383 loc) • 13.5 kB
JavaScript
'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