removed cryptojs from requirements

This commit is contained in:
2023-05-02 14:19:15 +01:00
parent 6ffdadb0b5
commit b59ced8fa6
7 changed files with 72 additions and 53 deletions

View File

@ -49,7 +49,10 @@ document.addEventListener("DOMContentLoaded", () => {
let sig = BigInt(packet.sig);
// decrypt and compare signature
let dehash = sender.rsaPubKey.encrypt(sig);
let hash = BigInt("0x" + CryptoJS.SHA3(JSON.stringify(data)).toString());
let hasher = new jsSHA("SHA3-256", "TEXT");
hasher.update(JSON.stringify(data));
let hash = BigInt("0x" + hasher.getHash("HEX"));
if (dehash !== hash) {
window.console.error(`Signature invalid! Ignoring packet ${data.id}.`);
return;

View File

@ -12,16 +12,12 @@ export class Packet {
static _sign(data) {
// compute hash of data
let hash = CryptoJS.SHA3(JSON.stringify(data));
let res = 0n;
for (let word32 of hash.words) {
// remove any sign
let bi = BigInt.asUintN(32, BigInt(word32));
res = (res << 32n) | bi;
}
let hasher = new jsSHA("SHA3-256", "TEXT");
hasher.update(JSON.stringify(data));
let hash = BigInt("0x" + hasher.getHash("HEX"));
// sign hash
let sig = window.rsa.privKey.decrypt(res);
let sig = window.rsa.privKey.decrypt(hash);
// return new packet
return {
@ -54,22 +50,23 @@ export class Packet {
});
}
static createRandomCyphertext(sessionId, range, cipherText) {
static createRandomHMAC(sessionId, range, hmac, key) {
return this._sign({
...this._createBase("RANDOM"),
session: sessionId,
range: range,
stage: "CIPHERTEXT",
cipherText: cipherText,
stage: "COMMIT",
hmac: hmac,
key: key,
});
}
static createRandomKey(sessionId, key) {
static createRandomNoise(sessionId, noise) {
return this._sign({
...this._createBase("RANDOM"),
session: sessionId,
stage: "DECRYPT",
cipherKey: key,
stage: "REVEAL",
noise: noise,
});
}

View File

@ -1,19 +1,24 @@
import { socket, game } from "./main.js";
import { Packet } from "./packet.js";
import { cryptoRandom } from "../crypto/random_primes.js";
class RandomSession {
constructor(range) {
this.range = range;
this.cipherTexts = {};
this.cipherKeys = {};
this.ourKey = CryptoJS.lib.WordArray.random(32).toString();
this.ourNoise = CryptoJS.lib.WordArray.random(8);
this.hmacs = {};
this.keys = {};
this.noises = {};
this.ourKey = cryptoRandom(1024).toString(16);
this.ourNoise = cryptoRandom(64);
this.finalValue = null;
this.resolvers = [];
}
cipherText() {
return CryptoJS.AES.encrypt(this.ourNoise, this.ourKey).toString();
hmac() {
let hasher = new jsSHA("SHA3-256", "HEX");
hasher.update(this.ourKey);
hasher.update(this.ourNoise.toString(16));
return hasher.getHash("HEX");
}
}
@ -58,7 +63,7 @@ export class Random {
socket.emit(
"message",
Packet.createRandomCyphertext(sessionId, n, session.cipherText())
Packet.createRandomHMAC(sessionId, n, session.hmac(), session.ourKey)
);
return session;
@ -78,41 +83,49 @@ export class Random {
session = this.initialiseSession(data.range, data.session);
}
if (stage === "CIPHERTEXT") {
session.cipherTexts[data.author] = data.cipherText;
if (stage === "COMMIT") {
session.hmacs[data.author] = data.hmac;
session.keys[data.author] = data.key;
if (
Object.keys(session.cipherTexts).length ===
Object.keys(session.hmacs).length ===
Object.keys(game.players).length - 1
) {
// Step 3: release our key once all players have sent a ciphertext
socket.emit(
"message",
Packet.createRandomKey(data.session, session.ourKey)
Packet.createRandomNoise(
data.session,
"0x" + session.ourNoise.toString(16)
)
);
}
} else if (stage === "DECRYPT") {
session.cipherKeys[data.author] = data.cipherKey;
} else if (stage === "REVEAL") {
// Check HMAC
let noise = BigInt(data.noise) % 2n ** 64n;
let hasher = new jsSHA("SHA3-256", "HEX");
hasher.update(session.keys[data.author]);
hasher.update(noise.toString(16));
let hash = hasher.getHash("HEX");
if (hash === session.hmacs[data.author]) {
session.noises[data.author] = noise;
}
// Step 4: get final random value
if (
Object.keys(session.cipherKeys).length ===
Object.keys(session.noises).length ===
Object.keys(game.players).length - 1
) {
// Lock out wait calls as they may resolve to never-ending promises.
await navigator.locks.request(`random-${data.session}`, () => {
let total = BigInt("0x" + session.ourNoise.toString());
let total = session.ourNoise;
for (let participant of Object.keys(session.cipherKeys)) {
let decrypted = CryptoJS.AES.decrypt(
session.cipherTexts[participant],
session.cipherKeys[participant]
).toString();
total += BigInt("0x" + decrypted);
for (let noise of Object.values(session.noises)) {
total += noise;
}
// Find first good block of bits to avoid modular bias
// Find first good block of bits
let blockSize = BigInt(Math.ceil(Math.log2(session.range)));
let blockMask = 2n ** blockSize - 1n;