import * as util from "./util.js";
import {blake2s} from "./blake.js";
import {pbkdf2} from "./pbkdf2.js";
import {Chacha20, encrypt as _encrypt, decrypt as _decrypt} from "./chacha.js";
const VERSION = 1;
const MAX_ITERS = 24;
function encrypt(s, password) {
let bs = util.str2utf8(s);
let pass = util.str2utf8(password);
let salt = util.createRandomNonce(12);
let [iters, key] = stretchKey(pass, salt);
let [_, ciphertext] = _encrypt(bs, key, salt);
let signature = blake2s([VERSION, iters].concat(salt, ciphertext), 16, key);
let arr = [VERSION, iters].concat(signature, salt, ciphertext);
return util.bytes2base64(arr);
}
function decrypt(s, password) {
let pass = util.str2utf8(password);
let arr = util.base642bytes(s);
let version = arr[0];
let iters = arr[1];
let signature = arr.slice(2, 18);
let salt = arr.slice(18, 30);
let ciphertext = arr.slice(30);
if (ciphertext.length == 0) {return 4;}
if (version > VERSION) {return 2;}
if (iters > MAX_ITERS) {return 3;}
let key = pbkdf2(pass, salt, 1 << iters, 32);
let check = blake2s([version, iters].concat(salt, ciphertext), 16, key);
if (!signature.every((b, i) => b === check[i])) {return 1;}
let plainbytes = _decrypt(ciphertext, key, salt);
return util.utf82str(plainbytes);
}
function stretchKey(password, salt) {
let start = Date.now(); // ms
let i, key;
for (i = 0; i <= MAX_ITERS; i++) {
key = pbkdf2(password, salt, 1<<i, 32);
if (Date.now()-start >= 500) {break;}
}
return [i, key];
}
export default {util, blake2s, pbkdf2, Chacha20, encrypt, decrypt};
// export for tests running on Node
if (typeof module !== 'undefined' && module.hasOwnProperty('exports')) {
module.exports.util = util;
module.exports.blake2s = blake2s;
module.exports.pbkdf2 = pbkdf2;
module.exports.Chacha20 = Chacha20;
module.exports.encrypt = _encrypt;
module.exports.decrypt = _decrypt;
}