90 lines
2.5 KiB
TypeScript
90 lines
2.5 KiB
TypeScript
import {createSHA256, pbkdf2} from "hash-wasm";
|
|
import aes from 'js-crypto-aes';
|
|
import {decode, encode} from "uint8-to-b64";
|
|
|
|
export class Encryption {
|
|
private _key: Uint8Array | null = null;
|
|
private _salt: Uint8Array | null = null;
|
|
private _iv: Uint8Array | null = null;
|
|
private _encrypted: Uint8Array | null = null;
|
|
|
|
constructor() {
|
|
|
|
}
|
|
|
|
private _ready: boolean = false;
|
|
|
|
public get ready() {
|
|
return this._ready;
|
|
}
|
|
|
|
public async setPassword(password: string, saltString?: string) {
|
|
if (saltString) {
|
|
this._salt = decode(saltString);
|
|
} else {
|
|
const salt = new Uint8Array(16);
|
|
window.crypto.getRandomValues(salt);
|
|
this._salt = salt;
|
|
}
|
|
this._key = await pbkdf2({
|
|
password: password,
|
|
salt: this._salt,
|
|
iterations: 10000,
|
|
hashLength: 32,
|
|
hashFunction: createSHA256(),
|
|
outputType: "binary"
|
|
});
|
|
this._ready = true;
|
|
}
|
|
|
|
public async encryptObject(obj: any) {
|
|
return await this.encrypt(JSON.stringify(obj));
|
|
}
|
|
|
|
public async decryptToObject(msg: string, iv: string) {
|
|
return JSON.parse(await this.decrypt(msg, iv));
|
|
}
|
|
|
|
public async encrypt(msg: string) {
|
|
if (!this._key) {
|
|
throw new Error('No password key set');
|
|
}
|
|
|
|
const iv = new Uint8Array(12);
|
|
window.crypto.getRandomValues(iv);
|
|
this._iv = iv;
|
|
|
|
const arr: Uint8Array = await aes.encrypt(
|
|
new TextEncoder().encode(msg), this._key, {name: 'AES-GCM', iv: this._iv, tagLength: 16});
|
|
this._encrypted = arr;
|
|
return this._encrypted;
|
|
}
|
|
|
|
public async decrypt(msg: string, iv: string) {
|
|
if (!this._key) {
|
|
throw new Error('No key set');
|
|
}
|
|
this._iv = decode(iv);
|
|
const msgArray = decode(msg);
|
|
//Uint8Array.from(atob(decode(msg)), c => c.charCodeAt(0));
|
|
const output = await aes.decrypt(msgArray, this._key, {name: 'AES-GCM', iv: this._iv, tagLength: 16});
|
|
return new TextDecoder().decode(output);
|
|
}
|
|
|
|
public getEncrypted() {
|
|
if (
|
|
!this._encrypted ||
|
|
!this._iv ||
|
|
!this._salt
|
|
) {
|
|
return null;
|
|
} else {
|
|
return {
|
|
encrypted: encode(this._encrypted),
|
|
salt: encode(this._salt),
|
|
iv: encode(this._iv)
|
|
}
|
|
}
|
|
|
|
}
|
|
} |