Ensure ciphertexts are cloned to avoid mutating actual object.
This commit is contained in:
@ -23,7 +23,6 @@ class Cyphertext {
|
||||
this.cyphertext += key.n2;
|
||||
}
|
||||
|
||||
console.log(performance.now());
|
||||
this.r = r;
|
||||
this.pubKey = key;
|
||||
this.plainText = plainText;
|
||||
@ -32,16 +31,13 @@ class Cyphertext {
|
||||
}
|
||||
|
||||
update(c) {
|
||||
this.cyphertext = (this.cyphertext * c.cyphertext) % this.pubKey.n ** 2n;
|
||||
this.r = (this.r * c.r) % this.pubKey.n ** 2n;
|
||||
this.cyphertext = (this.cyphertext * c.cyphertext) % this.pubKey.n2;
|
||||
this.r = (this.r * c.r) % this.pubKey.n2;
|
||||
this.plainText += c.plainText;
|
||||
|
||||
// Force into range
|
||||
while (this.cyphertext < 0n) {
|
||||
this.cyphertext += this.pubKey.n ** 2n;
|
||||
}
|
||||
while (this.r < 0n) {
|
||||
this.r += this.pubKey.n ** 2n;
|
||||
this.cyphertext += this.pubKey.n2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,11 +65,11 @@ class ProofSessionProver {
|
||||
}
|
||||
|
||||
get a() {
|
||||
return mod_exp(this.rp, this.cipherText.pubKey.n, this.cipherText.pubKey.n ** 2n);
|
||||
return mod_exp(this.rp, this.cipherText.pubKey.n, this.cipherText.pubKey.n2);
|
||||
}
|
||||
|
||||
noise() {
|
||||
return mod_exp(this.rp, this.cipherText.pubKey.n, this.cipherText.pubKey.n ** 2n);
|
||||
return mod_exp(this.rp, this.cipherText.pubKey.n, this.cipherText.pubKey.n2);
|
||||
}
|
||||
|
||||
prove(challenge) {
|
||||
@ -102,26 +98,33 @@ export class ReadOnlyCyphertext {
|
||||
}
|
||||
|
||||
update(c) {
|
||||
this.cyphertext = (this.cyphertext * c.cyphertext) % this.pubKey.n ** 2n;
|
||||
this.cyphertext = (this.cyphertext * c.cyphertext) % this.pubKey.n2;
|
||||
|
||||
// Force into range
|
||||
while (this.cyphertext < 0n) {
|
||||
this.cyphertext += this.pubKey.n ** 2n;
|
||||
this.cyphertext += this.pubKey.n2;
|
||||
}
|
||||
}
|
||||
|
||||
prove(plainText, a) {
|
||||
return new ProofSessionVerifier(this, plainText, a);
|
||||
}
|
||||
|
||||
clone() {
|
||||
return new ReadOnlyCyphertext(this.pubKey, this.cyphertext);
|
||||
}
|
||||
}
|
||||
|
||||
class ProofSessionVerifier {
|
||||
constructor(cipherText, plainText, a) {
|
||||
this.cipherText = cipherText;
|
||||
// Clone, otherwise the update below will mutate the original value
|
||||
this.cipherText = cipherText.clone();
|
||||
this.cipherText.update(this.cipherText.pubKey.encrypt(-1n * plainText, 1n));
|
||||
// Shift the challenge down by 1 to ensure it is smaller than either prime factor.
|
||||
this.challenge = cryptoRandom(2048) << 1n;
|
||||
this.a = a;
|
||||
|
||||
this.plainText = plainText;
|
||||
}
|
||||
|
||||
verify(proof) {
|
||||
@ -204,3 +207,5 @@ export function generate_keypair() {
|
||||
|
||||
return { pubKey, privKey };
|
||||
}
|
||||
|
||||
// p = a.prove(); v = p.asVerifier(); v.verify(p.prove(v.challenge));
|
||||
|
@ -34,7 +34,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
});
|
||||
|
||||
socket.on("message", async (packet) => {
|
||||
window.console.log(`Received size: ${JSON.stringify(packet).length}`);
|
||||
// window.console.log(`Received size: ${JSON.stringify(packet).length}`);
|
||||
|
||||
let data = packet.payload;
|
||||
if (data.type !== "KEEPALIVE") window.console.log(data);
|
||||
|
@ -11,9 +11,46 @@ class Continent {
|
||||
}
|
||||
|
||||
class Strength {
|
||||
constructor(cipherText) {
|
||||
constructor(cipherText, regionName) {
|
||||
this.cipherText = cipherText;
|
||||
this.assumedStrength = null;
|
||||
|
||||
this.prover = null;
|
||||
document.addEventListener("PROOF", (ev) => {
|
||||
const data = ev.detail;
|
||||
|
||||
if (
|
||||
data.region === regionName &&
|
||||
data.stage === "CHALLENGE" &&
|
||||
this.prover !== null
|
||||
) {
|
||||
let z = this.prover.prove(BigInt(data.challenge));
|
||||
|
||||
socket.emit(
|
||||
"message",
|
||||
Packet.createProof(regionName, "0x" + z.toString(16))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
this.verifier = null;
|
||||
document.addEventListener("PROOF", (ev) => {
|
||||
const data = ev.detail;
|
||||
|
||||
if (
|
||||
data.region === regionName &&
|
||||
data.stage === "PROOF" &&
|
||||
this.verifier !== null
|
||||
) {
|
||||
let result = this.verifier.verify(BigInt(data.z));
|
||||
if (result > 0) {
|
||||
this.assumedStrength = this.verifier.plainText;
|
||||
document.dispatchEvent(new CustomEvent("updateStrengths"));
|
||||
} else {
|
||||
console.warn(`Failed to verify ciphertext! ${result}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
update(cipherText) {
|
||||
@ -31,33 +68,14 @@ class Strength {
|
||||
return;
|
||||
}
|
||||
|
||||
const controller = new AbortController();
|
||||
let proofSessionProver = this.cipherText.prove();
|
||||
|
||||
document.addEventListener(
|
||||
"PROOF",
|
||||
(ev) => {
|
||||
const data = ev.detail;
|
||||
|
||||
if (data.region === region && data.stage === "CHALLENGE") {
|
||||
let z = proofSessionProver.prove(BigInt(data.challenge));
|
||||
|
||||
socket.emit(
|
||||
"message",
|
||||
Packet.createProof(region, "0x" + z.toString(16))
|
||||
);
|
||||
controller.abort();
|
||||
}
|
||||
},
|
||||
{ signal: controller.signal }
|
||||
);
|
||||
this.prover = this.cipherText.prove();
|
||||
|
||||
socket.emit(
|
||||
"message",
|
||||
Packet.createProofConjecture(
|
||||
region,
|
||||
"0x" + this.cipherText.plainText.toString(),
|
||||
"0x" + proofSessionProver.a.toString(16)
|
||||
"0x" + this.prover.a.toString(16)
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -67,33 +85,13 @@ class Strength {
|
||||
return;
|
||||
}
|
||||
|
||||
const controller = new AbortController();
|
||||
let proofSessionVerifier = this.cipherText.prove(plainText, a);
|
||||
|
||||
document.addEventListener(
|
||||
"PROOF",
|
||||
(ev) => {
|
||||
const data = ev.detail;
|
||||
|
||||
if (data.region === region && data.stage === "PROOF") {
|
||||
let result = proofSessionVerifier.verify(BigInt(data.z));
|
||||
if (result > 0) {
|
||||
this.assumedStrength = plainText;
|
||||
document.dispatchEvent(new CustomEvent("updateStrengths"));
|
||||
controller.abort();
|
||||
} else {
|
||||
console.warn(`Failed to verify ciphertext! ${result}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ signal: controller.signal }
|
||||
);
|
||||
this.verifier = this.cipherText.prove(plainText, a);
|
||||
|
||||
socket.emit(
|
||||
"message",
|
||||
Packet.createProofChallenge(
|
||||
region,
|
||||
"0x" + proofSessionVerifier.challenge.toString(16)
|
||||
"0x" + this.verifier.challenge.toString(16)
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -103,7 +101,7 @@ export class Region {
|
||||
constructor(name, continent) {
|
||||
this.name = name;
|
||||
this.owner = null;
|
||||
this.strength = new Strength(null);
|
||||
this.strength = new Strength(null, name);
|
||||
this.neighbours = new Set();
|
||||
this.continent = continent;
|
||||
|
||||
|
@ -156,7 +156,10 @@ export class Player {
|
||||
|
||||
// send proofs
|
||||
for (let region of this.getRegions()) {
|
||||
region.prove();
|
||||
// eh
|
||||
if ([...region.neighbours.values()].find((r) => r.owner !== this)) {
|
||||
region.prove();
|
||||
}
|
||||
}
|
||||
|
||||
this.endTurn();
|
||||
|
Reference in New Issue
Block a user