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