crystals-kyber-ts
Version:
KYBER is an IND-CCA2-secure key encapsulation mechanism (KEM).
118 lines • 3.87 kB
JavaScript
import { Buffer } from "buffer";
import { Utilities } from "./utilities";
import { KyberService } from "../services/kyber.service";
/**
* Utility class for byte operations
*/
export class ByteOps {
constructor(paramsK) {
this.paramsK = paramsK;
}
/**
* Generate a polynomial with coefficients distributed according to a
* centered binomial distribution with parameter eta, given an array of
* uniformly random bytes.
*
* @param buff
* @param paramsK
* @return
*/
generateCBDPoly(buff, paramsK) {
const buf = Buffer.from(buff);
let t, d;
let a, b;
let r = new Array(KyberService.paramsPolyBytes).fill(0);
switch (paramsK) {
case 2:
for (let i = 0; i < KyberService.paramsN / 4; i++) {
t = this.convertByteTo24BitUnsignedInt(buf.slice(3 * i, buf.length));
d = t & 0x00249249;
d = d + ((t >> 1) & 0x00249249);
d = d + ((t >> 2) & 0x00249249);
for (let j = 0; j < 4; j++) {
a = Utilities.int16((d >> (6 * j + 0)) & 0x7);
b = Utilities.int16((d >> (6 * j + KyberService.paramsETAK512)) & 0x7);
r[4 * i + j] = a - b;
}
}
break;
default:
for (let i = 0; i < KyberService.paramsN / 8; i++) {
t = (this.convertByteTo32BitUnsignedInt(buf.slice(4 * i, buf.length)));
d = (t & 0x55555555);
d = d + (((t >> 1) & 0x55555555) >>> 0);
for (let j = 0; j < 8; j++) {
a = Utilities.int16((((d >> (4 * j + 0))) & 0x3));
b = Utilities.int16((((d >> (4 * j + KyberService.paramsETAK768K1024))) & 0x3));
r[8 * i + j] = a - b;
}
}
}
return r;
}
/**
* Returns a 24-bit unsigned integer as a long from byte x
*
* @param x
* @return
*/
convertByteTo24BitUnsignedInt(x) {
let r;
r = Utilities.int32(x[0] & 0xFF);
r = r | (Utilities.int32(x[1] & 0xFF) << 8);
r = r | (Utilities.int32(x[2] & 0xFF) << 16);
return r;
}
/**
* Returns a 24-bit unsigned integer as a long from byte x
*
* @param x
* @return
*/
convertByteTo32BitUnsignedInt(x) {
let r;
r = Utilities.int32(x[0] & 0xFF);
r = (((r | (Utilities.int32(x[1] & 0xFF) << 8))));
r = (((r | (Utilities.int32(x[2] & 0xFF) << 16))));
r = (((r | Utilities.int32(Utilities.int32(x[3] & 0xFF) << 24))));
// last one won't print the same as java
return r;
}
/**
* Computes a Barrett reduction given a 16 Bit Integer
*
* @param a
* @return
*/
barrettReduce(a) {
let shift = Utilities.int32(1 << 26);
let v = +Utilities.int16((shift + (KyberService.paramsQ / 2)) / KyberService.paramsQ).toFixed(0);
let t = Utilities.int16((v * a) >> 26);
t = Utilities.int16(t * KyberService.paramsQ);
return a - t;
}
/**
* Multiply the given shorts and then run a Montgomery reduce
*
* @param a
* @param b
* @return
*/
modQMulMont(a, b) {
return this.byteopsMontgomeryReduce(a * b);
}
/**
* Computes a Montgomery reduction given a 32 Bit Integer
*
* @param a
* @return
*/
byteopsMontgomeryReduce(a) {
let u = Utilities.int16(Utilities.uint16(a) * KyberService.paramsQinv);
let t = u * KyberService.paramsQ;
t = a - t;
t >>= 16;
return Utilities.int16(t);
}
}
//# sourceMappingURL=byte-ops.js.map