Changeset - 12f10d9d5948
[Not reviewed]
default
0 4 0
Laman - 5 years ago 2019-07-05 15:42:03

refactored Chacha20.encrypt, .decrypt
4 files changed with 22 insertions and 22 deletions:
0 comments (0 inline, 0 general)
spec/test/chachaSpec.js
Show inline comments
 
@@ -34,7 +34,7 @@ describe("Chacha",function(){
 
	describe("encrypt",function(){
 
		it("should correctly encrypt an example text",function(){
 
			let ciphertext=[110,46,53,154,37,104,249,128,65,186,7,40,221,13,105,129,233,126,122,236,29, 67,96,194,10,39,175,204,253,159,174,11,249,27,101,197,82,71,51,171,143,89,61,171,205,98,179,87,22, 57,214,36,230,81,82,171,143,83,12,53,159,8,97,216,7,202,13,191,80,13,106,97,86,163,142,8,138,34, 182,94,82,188,81,77,22,204,248,6,129,140,233,26,183,121,55,54,90,249,11,191,116,163,91,230,180,11, 142,237,242,120,94,66,135,77];
 
			expect(encrypt(str2utf8(plaintext),key,nonce2)).toEqual(nonce2.concat(ciphertext));
 
			expect(encrypt(str2utf8(plaintext),key,nonce2)).toEqual([nonce2,ciphertext]);
 
		});
 
	});
 
	
 
@@ -45,7 +45,8 @@ describe("Chacha",function(){
 
			for(let i=0;i<16;i++){key.push(Math.floor(Math.random()*256));}
 
			let nonce=[];
 
			for(let i=0;i<8;i++){nonce.push(Math.floor(Math.random()*256));}
 
			expect(decrypt(encrypt(text,key,nonce),key)).toEqual(text);
 
			let [_,ciphertext]=encrypt(text,key,nonce);
 
			expect(decrypt(ciphertext,key,nonce)).toEqual(text);
 
		});
 
	});
 
	
src/chacha.js
Show inline comments
 
// https://tools.ietf.org/html/rfc7539
 
import {MASK,int32s2bytes,bytes2int32s,zeroPad} from "./util.js";
 
import {MASK,int32s2bytes,bytes2int32s,zeroPad,createRandomNonce} from "./util.js";
 

	
 
function lrot(x,shift){
 
	return (x<<shift|x>>>(32-shift))&MASK;
 
}
 

	
 
export function createNonce(){
 
	let nonce=new Uint8Array(12);
 
	window.crypto.getRandomValues(nonce);
 
	return Array.from(nonce);
 
}
 

	
 
/**
 
 * A Chacha20 cipher class.
 
 * @param {Array} key Array of bytes (integers: 0<=x<256). Short keys are padded to 32B, long keys are silently truncated.
 
 * @param {Array} nonce optional. If present, it must be an Array of bytes (integers: 0<=x<256). Short nonces are padded to 12B, long nonces are silently truncated.
 
 */
 
export function Chacha20(key,nonce){
 
	const NONCE_LEN=12;
 
	if(nonce===undefined){
 
		nonce=createNonce();
 
		nonce=createRandomNonce(NONCE_LEN);
 
	}
 
	this._nonce=zeroPad(nonce,12);
 
	this._nonce=zeroPad(nonce,NONCE_LEN);
 
	nonce=bytes2int32s(this._nonce);
 
	key=bytes2int32s(zeroPad(key,32));
 
	
 
@@ -85,12 +80,10 @@ Chacha20.prototype._incrementPos=functio
 
export function encrypt(data,key,nonce){
 
	let cipher=new Chacha20(key,nonce);
 
	nonce=cipher.getNonce();
 
	return nonce.concat(data.map(b=>b^cipher.getByte()));
 
	return [nonce,data.map(b=>b^cipher.getByte())];
 
}
 

	
 
export function decrypt(data,key){
 
	let nonce=data.slice(0,12);
 
	let ciphertext=data.slice(12);
 
export function decrypt(ciphertext,key,nonce){
 
	let cipher=new Chacha20(key,nonce);
 
	return ciphertext.map(b=>b^cipher.getByte());
 
}
src/main.js
Show inline comments
 
import * as util from "./util.js";
 
import {blake2s} from "./blake.js";
 
import {pbkdf2} from "./pbkdf2.js";
 
import {createNonce,Chacha20,encrypt as _encrypt,decrypt as _decrypt} from "./chacha.js";
 
import {Chacha20,encrypt as _encrypt,decrypt as _decrypt} from "./chacha.js";
 

	
 
const VERSION=1;
 

	
 
function encrypt(s,password){
 
	let bs=util.str2utf8(s);
 
	let pass=util.str2utf8(password);
 
	let salt=createNonce();
 
	let salt=util.createRandomNonce(12);
 
	let [iters,key]=stretchKey(pass,salt);
 
	let noncedCiphertext=_encrypt(bs,key,salt);
 
	let payload=[iters].concat(noncedCiphertext);
 
	let [_,ciphertext]=_encrypt(bs,key,salt);
 
	let payload=[iters].concat(salt,ciphertext);
 
	let signature=blake2s([VERSION].concat(payload),16,pass);
 
	let arr=[VERSION].concat(signature,payload);
 
	return util.bytes2base64(arr);
 
@@ -24,12 +24,12 @@ function decrypt(s,password){
 
	let signature=arr.slice(1,17);
 
	let iters=arr[17];
 
	let salt=arr.slice(18,30);
 
	let noncedCiphertext=arr.slice(18);
 
	let check=blake2s([version].concat([iters],noncedCiphertext),16,pass);
 
	let ciphertext=arr.slice(30);
 
	let check=blake2s([version,iters].concat(salt,ciphertext),16,pass);
 
	if(!signature.every((b,i)=>b===check[i])){return false;}
 
	if(version>VERSION){return false;}
 
	let key=pbkdf2(pass,salt,1<<iters,32);
 
	let plainbytes=_decrypt(noncedCiphertext,key);
 
	let plainbytes=_decrypt(ciphertext,key,salt);
 
	return util.utf82str(plainbytes);
 
}
 

	
src/util.js
Show inline comments
 
@@ -138,3 +138,9 @@ export function base642bytes(str){
 

	
 
	return out;
 
}
 

	
 
export function createRandomNonce(n){
 
	let nonce=new Uint8Array(n);
 
	window.crypto.getRandomValues(nonce);
 
	return Array.from(nonce);
 
}
0 comments (0 inline, 0 general)