@kotevode/ffjavascript
Version:
Finite Field Library in Javascript
97 lines (76 loc) • 2.38 kB
JavaScript
import * as Scalar from "./scalar.js";
function quarterRound(st, a, b, c, d) {
st[a] = (st[a] + st[b]) >>> 0;
st[d] = (st[d] ^ st[a]) >>> 0;
st[d] = ((st[d] << 16) | ((st[d]>>>16) & 0xFFFF)) >>> 0;
st[c] = (st[c] + st[d]) >>> 0;
st[b] = (st[b] ^ st[c]) >>> 0;
st[b] = ((st[b] << 12) | ((st[b]>>>20) & 0xFFF)) >>> 0;
st[a] = (st[a] + st[b]) >>> 0;
st[d] = (st[d] ^ st[a]) >>> 0;
st[d] = ((st[d] << 8) | ((st[d]>>>24) & 0xFF)) >>> 0;
st[c] = (st[c] + st[d]) >>> 0;
st[b] = (st[b] ^ st[c]) >>> 0;
st[b] = ((st[b] << 7) | ((st[b]>>>25) & 0x7F)) >>> 0;
}
function doubleRound(st) {
quarterRound(st, 0, 4, 8,12);
quarterRound(st, 1, 5, 9,13);
quarterRound(st, 2, 6,10,14);
quarterRound(st, 3, 7,11,15);
quarterRound(st, 0, 5,10,15);
quarterRound(st, 1, 6,11,12);
quarterRound(st, 2, 7, 8,13);
quarterRound(st, 3, 4, 9,14);
}
export default class ChaCha {
constructor(seed) {
seed = seed || [0,0,0,0,0,0,0,0];
this.state = [
0x61707865,
0x3320646E,
0x79622D32,
0x6B206574,
seed[0],
seed[1],
seed[2],
seed[3],
seed[4],
seed[5],
seed[6],
seed[7],
0,
0,
0,
0
];
this.idx = 16;
this.buff = new Array(16);
}
nextU32() {
if (this.idx == 16) this.update();
return this.buff[this.idx++];
}
nextU64() {
return Scalar.add(Scalar.mul(this.nextU32(), 0x100000000), this.nextU32());
}
nextBool() {
return (this.nextU32() & 1) == 1;
}
update() {
// Copy the state
for (let i=0; i<16; i++) this.buff[i] = this.state[i];
// Apply the rounds
for (let i=0; i<10; i++) doubleRound(this.buff);
// Add to the initial
for (let i=0; i<16; i++) this.buff[i] = (this.buff[i] + this.state[i]) >>> 0;
this.idx = 0;
this.state[12] = (this.state[12] + 1) >>> 0;
if (this.state[12] != 0) return;
this.state[13] = (this.state[13] + 1) >>> 0;
if (this.state[13] != 0) return;
this.state[14] = (this.state[14] + 1) >>> 0;
if (this.state[14] != 0) return;
this.state[15] = (this.state[15] + 1) >>> 0;
}
}