@hazae41/kdbx
Version:
Rust-like KeePass (KDBX 4) file format for TypeScript
120 lines (119 loc) • 3.8 kB
JavaScript
// deno-lint-ignore-file no-namespace
export * from "./cipher/mod.js";
export * from "./markup/mod.js";
import { Vector } from "../../vector/mod.js";
import { Readable, Unknown, Writable } from "@hazae41/binary";
import { Cipher } from "./cipher/mod.js";
import { KeePassFile } from "./markup/mod.js";
export class HeadersAndContentWithBytes {
headers;
content;
constructor(headers, content) {
this.headers = headers;
this.content = content;
}
sizeOrThrow() {
return this.headers.sizeOrThrow() + this.content.sizeOrThrow();
}
writeOrThrow(cursor) {
this.headers.writeOrThrow(cursor);
this.content.writeOrThrow(cursor);
}
}
export class ContentWithBytes {
bytes;
value;
constructor(bytes, value) {
this.bytes = bytes;
this.value = value;
}
static computeOrThrow(value) {
return new ContentWithBytes(new Unknown(value.encodeOrThrow()), value);
}
sizeOrThrow() {
return this.bytes.sizeOrThrow();
}
writeOrThrow(cursor) {
this.bytes.writeOrThrow(cursor);
}
}
(function (ContentWithBytes) {
function readOrThrow(cursor) {
const bytes = new Unknown(cursor.readOrThrow(cursor.remaining));
const value = KeePassFile.decodeOrThrow(bytes.bytes);
return new ContentWithBytes(bytes, value);
}
ContentWithBytes.readOrThrow = readOrThrow;
})(ContentWithBytes || (ContentWithBytes = {}));
(function (HeadersAndContentWithBytes) {
function readOrThrow(cursor) {
const headers = Headers.readOrThrow(cursor);
const content = ContentWithBytes.readOrThrow(cursor);
return new HeadersAndContentWithBytes(headers, content);
}
HeadersAndContentWithBytes.readOrThrow = readOrThrow;
})(HeadersAndContentWithBytes || (HeadersAndContentWithBytes = {}));
export class Headers {
value;
constructor(value) {
this.value = value;
}
get cipher() {
return this.value.value[1][0];
}
get key() {
return this.value.value[2][0];
}
get binary() {
return this.value.value[3];
}
sizeOrThrow() {
return this.value.sizeOrThrow();
}
writeOrThrow(cursor) {
this.value.writeOrThrow(cursor);
}
cloneOrThrow() {
return Readable.readFromBytesOrThrow(Headers, Writable.writeToBytesOrThrow(this));
}
rotateOrThrow() {
const { cipher, binary } = this;
const key = new Unknown(crypto.getRandomValues(new Uint8Array(32)));
return Headers.initOrThrow({ cipher, key, binary });
}
async getCipherOrThrow() {
return await this.cipher.initOrThrow(this.key.bytes);
}
}
(function (Headers) {
function createOrThrow(cipher) {
const binary = new Array();
const key = new Unknown(crypto.getRandomValues(new Uint8Array(32)));
return Headers.initOrThrow({ cipher, key, binary });
}
Headers.createOrThrow = createOrThrow;
function initOrThrow(init) {
const { cipher, key, binary } = init;
const indexed = {
1: [cipher],
2: [key],
3: binary
};
return new Headers(Vector.initOrThrow(indexed));
}
Headers.initOrThrow = initOrThrow;
function readOrThrow(cursor) {
const vector = Vector.readOrThrow(cursor);
if (vector.value[1].length !== 1)
throw new Error();
if (vector.value[2].length !== 1)
throw new Error();
const indexed = {
1: [vector.value[1][0].readIntoOrThrow(Cipher)],
2: [vector.value[2][0]],
3: vector.value[3]
};
return new Headers(new Vector(vector.bytes, indexed));
}
Headers.readOrThrow = readOrThrow;
})(Headers || (Headers = {}));