-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathElGamal.ts
122 lines (111 loc) · 4.03 KB
/
ElGamal.ts
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import chalk from "chalk";
import {
babyStepGiantStep,
fastModularExponentiation,
naorReingo,
} from "../entry-point";
import { EActors } from "../common/constants";
import { log, inquire, wrap } from "../common/utilities";
export async function prompt() {
try {
console.log("There are three people in this ElGamal encryption process:");
console.log(
`\t${EActors.Alice} - Receiver\n\t${EActors.Bob} - Sender\n\t${EActors.Eve} - Eavesdropper`
);
const [p, g, r, x, y] = await inquire.continue(
`${EActors.Alice} is going to pick prime number P, generator g, and random numbers r and x:`,
() => {
const [p] = wrap.randomize(16, 5, 1);
const [g, r, x] = naorReingo(3, 2);
log.list([
{ name: "P", value: p },
{ name: "g", value: g },
{ name: "r", value: r },
{ name: "x", value: x },
]);
console.log(`\n\t${EActors.Alice} generates y:`);
const y = fastModularExponentiation(BigInt(g), BigInt(x), p);
console.log(`\ty: ${chalk.gray(y)}`);
console.log(
`\n\t${EActors.Alice} sends ${chalk.bold.bgCyan(
"(g, r, p, y)"
)} as the public key to ${EActors.Bob} and ${EActors.Eve}.`
);
return [p, g, r, x, y];
}
);
const message = "This is a hardcoded secret message.";
const [keyEncrypted, arrayOfEncryptedCode] = await inquire.continue(
`${EActors.Bob} encrypts the message and sends it back to ${EActors.Alice} (while ${EActors.Eve} is eavesdropping).`,
() => {
const keyEncrypted = fastModularExponentiation(BigInt(g), BigInt(r), p);
const arrayOfEncryptedCode = wrap.encrypt(message, (code) => {
return BigInt(code) * fastModularExponentiation(y, BigInt(r), p);
});
console.log(`\tEncrypted key: ${chalk.gray(keyEncrypted)}`);
console.log(`\tEncrypted message: ${chalk.gray(arrayOfEncryptedCode)}`);
const messageDecrypted =
message ||
wrap.decrypt(arrayOfEncryptedCode, (codeEncrypted) => {
return (
fastModularExponentiation(
keyEncrypted,
BigInt(Number(p) - 1 - x),
p
) * codeEncrypted
);
});
console.log(
`\n\t${
EActors.Alice
} can decrypt the message since she has the random number ${chalk.bold.bgCyan(
"(x)"
)}.\n\tDecrypted message: ${chalk.gray(messageDecrypted)}\n\t${
EActors.Alice
} verifies the message with ${EActors.Bob} privately.`
);
return [keyEncrypted, arrayOfEncryptedCode];
}
);
await inquire.continue(
`${EActors.Eve} is going to decrypt the secret message.`,
() => {
console.log(`\tNow ${EActors.Eve} has the following stuff:`);
log.list([
{ name: "g", value: g },
{ name: "r", value: r },
{ name: "p", value: p },
{ name: "y", value: y },
{ name: "secret key", value: keyEncrypted },
{ name: "secret message", value: arrayOfEncryptedCode },
]);
console.log(
`\n\t${EActors.Eve} is going to figure out what the random number x is using Discrete Log with the information she has.`
);
const xEavesdropped =
x || babyStepGiantStep(BigInt(g), BigInt(r), BigInt(p));
console.log(
`\tRandom number ${chalk.bold.bgCyan("(x)")}: ${chalk.gray(
`(${xEavesdropped})`
)}`
);
const messageEavesdropped =
message ||
wrap.decrypt(arrayOfEncryptedCode, (codeEncrypted) => {
return fastModularExponentiation(
codeEncrypted,
BigInt(xEavesdropped),
p
);
});
console.log(
`\tDecrypted message: ${chalk.gray(messageEavesdropped)}\n\t${
EActors.Eve
} verifies the message with ${EActors.Bob}.`
);
}
);
} catch (error) {
throw error;
}
}