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;
}