Changeset - d27d9e2dd943
[Not reviewed]
default
0 3 0
Laman - 6 years ago 2018-07-07 13:16:57

chacha finished, tests refactored into functions
3 files changed with 76 insertions and 32 deletions:
0 comments (0 inline, 0 general)
blake.js
Show inline comments
 
// https://tools.ietf.org/html/rfc7693
 

	
 
const MASK=0xffffffff;
 
const BLOCK_LEN=64;
 

	
 
const IV=[0x6A09E667,0xBB67AE85,0x3C6EF372,0xA54FF53A,0x510E527F,0x9B05688C,0x1F83D9AB,0x5BE0CD19];
 

	
 
function padEnd(arr,length,val=0){
 
	return arr.concat((new Array(length-arr.length)).fill(0));
 
}
 

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

	
 
@@ -83,26 +82,28 @@ BLAKE2S.prototype._mix=function(arr,ia,i
 
	c=(c+d)&MASK; b=rrot(b^c,12);
 
	a=(a+b+y)&MASK; d=rrot(d^a,8);
 
	c=(c+d)&MASK; b=rrot(b^c,7);
 
	arr[ia]=a; arr[ib]=b; arr[ic]=c; arr[id]=d;
 
};
 

	
 
function blake2s(data,outputLen=32,key=[]){
 
	let h=new BLAKE2S(outputLen,key);
 
	for(let i=0;i<data.length;i+=BLOCK_LEN){h.update(data.slice(i,i+BLOCK_LEN));}
 
	return h.digest();
 
}
 

	
 
function testBlake(){
 
let msg=str2utf8("abc");
 
let longMsg=str2utf8("0123456789.10.456789.20.456789.30.456789.40.456789.50.456789.60.456789.70.456789.80.456789.90.456789");
 
let key=str2utf8("zoqpiz");
 
let longKey=str2utf8("zoqpizjutyclcmkamzhhmhvchxjtefjy");
 
console.log(bytes2hex(blake2s(msg,16))=="aa4938119b1dc7b87cbad0ffd200d0ae");
 
console.log(bytes2hex(blake2s(msg,20))=="5ae3b99be29b01834c3b508521ede60438f8de17");
 
console.log(bytes2hex(blake2s(msg,28))=="0b033fc226df7abde29f67a05d3dc62cf271ef3dfea4d387407fbd55");
 
console.log(bytes2hex(blake2s(msg))=="508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982");
 
console.log(bytes2hex(blake2s(longMsg))=="59a44e5e417d07fb382505ee7e67c23e0d476d354abc81899960bcab677beee1");
 
console.log(bytes2hex(blake2s(msg,32,key))=="0da0b6a54e8f294b60bb25c572700166ddb9d124257ff36f9f43f18b844adf9f");
 
console.log(bytes2hex(blake2s(msg,32,longKey))=="09ef85c9942bebdeb866c6ade769220fd9b851aead642017f6d59bf7e2a32037");
 
console.log(bytes2hex(blake2s([]))=="69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9");
 
console.log(bytes2hex(blake2s(longMsg.slice(0,64)))=="70484f89974551454d596350dda8af2aa6f0811b527549b9ecfe7adede063753");
 
console.log(bytes2hex(blake2s(longMsg.slice(0,65)))=="af14d4f74947bbde734d0e3015c667cc80676efe4349be235be8046e9e45e0ae");
 
}
chacha.js
Show inline comments
 
MASK=0xffffffff;
 

	
 
function int2bytes(x){
 
	var res=new Array(4);
 
	for(var i=0;i<4;i++){
 
		res[i]=x&0xff;
 
		x>>>=8;
 
	}
 
	return res;
 
}
 
// https://tools.ietf.org/html/rfc7539
 

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

	
 
function quarterRound(arr,ia,ib,ic,id){
 
	var a=arr[ia], b=arr[ib], c=arr[ic], d=arr[id];
 
function createNonce(){
 
	let nonce=new Uint8Array(12);
 
	window.crypto.getRandomValues(nonce);
 
	return nonce;
 
}
 

	
 
function Chacha20(key,nonce){
 
	if(nonce===undefined){
 
		let nonce=createNonce();
 
	}
 
	nonce=bytes2int32s(nonce);
 
	key=bytes2int32s(key);
 
	
 
	this._state=[
 
		0x61707865,0x3320646e,0x79622d32,0x6b206574,
 
		key[0],key[1],key[2],key[3],
 
		key[4],key[5],key[6],key[7],
 
		0,nonce[0],nonce[1],nonce[2]
 
	];
 
	this._buffer=[];
 
}
 

	
 
Chacha20.prototype.setPos=function(pos){
 
	this._state[12]=pos;
 
	this._buffer=[];
 
}
 

	
 
Chacha20.prototype.getByte=function(){
 
	if(this._buffer.length==0){
 
		this._buffer=int32s2bytes(this._computeBlock());
 
	}
 
	return this._buffer.shift();
 
};
 

	
 
Chacha20.prototype._quarterRound=function(arr,ia,ib,ic,id){
 
	let a=arr[ia], b=arr[ib], c=arr[ic], d=arr[id];
 
	a=(a+b)&MASK; d=lrot(d^a,16);
 
	c=(c+d)&MASK; b=lrot(b^c,12);
 
	a=(a+b)&MASK; d=lrot(d^a,8);
 
	c=(c+d)&MASK; b=lrot(b^c,7);
 
	arr[ia]=a; arr[ib]=b; arr[ic]=c; arr[id]=d;
 
};
 

	
 
Chacha20.prototype._computeBlock=function(){
 
	let state=this._state.slice();
 

	
 
	for(let i=0;i<10;i++){ // 10 double rounds
 
		// column round
 
		this._quarterRound(state,0,4,8,12);
 
		this._quarterRound(state,1,5,9,13);
 
		this._quarterRound(state,2,6,10,14);
 
		this._quarterRound(state,3,7,11,15);
 
		// diagonal round
 
		this._quarterRound(state,0,5,10,15);
 
		this._quarterRound(state,1,6,11,12);
 
		this._quarterRound(state,2,7,8,13);
 
		this._quarterRound(state,3,4,9,14);
 
}
 

	
 
function chacha(key,nonce,position){
 
	var x=input.slice();
 
	return state.map((xi,i)=>(xi+this._state[i])&MASK);
 
};
 

	
 
	for(var i=0;i<10;i++){
 
		// column round
 
		quarterRound(x,0,4,8,12);
 
		quarterRound(x,1,5,9,13);
 
		quarterRound(x,2,6,10,14);
 
		quarterRound(x,3,7,11,15);
 
		// diagonal round
 
		quarterRound(x,0,5,10,15);
 
		quarterRound(x,1,6,11,12);
 
		quarterRound(x,2,7,8,13);
 
		quarterRound(x,3,4,9,14);
 
Chacha20.prototype._incrementPos=function(){
 
	this._state[12]=(this._state[12]+1)&MASK;
 
};
 

	
 
function encrypt(message,key){
 
	let nonce=Date.now();
 
	let nonce0=nonce;
 
	let hashedKey=blake2s(str2bytes(key));
 
	message=str2bytes(message);
 
	}
 

	
 
	return x.map((xi,i)=>(xi+input[i])&MASK);
 
function testChacha(){
 
	let key=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31];
 
	let nonce=[0,0,0,9,0,0,0,74,0,0,0,0];
 
	let cipher=new Chacha20(key,nonce);
 
	cipher.setPos(1);
 
	let output=cipher._computeBlock().map(x=>(x>>>0).toString(16).padStart(8,"0"));
 
	let example=["e4e7f110","15593bd1","1fdd0f50","c47120a3","c7f4d1c7","0368c033","9aaa2204","4e6cd4c3","466482d2","09aa9f07","05d7c214","a2028bd9","d19c12b5","b94e16de","e883d0cb","4e3c50a2"];
 
	console.log(output.every((x,i)=>x==example[i]));
 
}
 

	
 
function encrypt(message,key){
 
	var nonce=Date.now();
 
	var nonce0=nonce;
 
}
util.js
Show inline comments
 
const MASK=0xffffffff;
 

	
 
function bytes2int32(arr){
 
	return arr.reduce((acc,b,i)=>acc|b<<(i*8));
 
}
 

	
 
function bytes2int32s(arr){
 
	let res=[];
 
	for(let i=0;i<arr.length;i+=4){
 
		res.push(bytes2int32(arr.slice(i,i+4)));
 
	}
 
	return res;
 
}
 

	
0 comments (0 inline, 0 general)