Files @ 07d399b4c31c
Branch filter:

Location: CryptoJS/src/main.js - annotation

Laman
updated .hgignore
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;
}