-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathelgamal-digital-signature.js
109 lines (98 loc) · 3.01 KB
/
elgamal-digital-signature.js
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
const main = () => {
//signature generation
let p = 113;
let g = 5;
let x = 7;
let G_x = p.toString(2);
let y = Math.pow(g, x) % p;
let plainText = prompt("Введите сообщение, которое хотите подписать: ");
let M = getM(plainText);
let h = parseInt(findCRC(M, G_x), 2);
let k = getRandomInt(p-1);
let r = Number((BigInt(g) ** BigInt(k)) % BigInt(p));
let u = (h-(x*r)) % (p-1);
while(u<0) u = u + (p-1);
let s = ((extendedEeuclid(k, p-1)[1]) * u) % (p-1);
while(s<0) s += p-1;
console.log("Подписанная тройка (M, r, s): (" + M + ", " + r + ", " + s + ")");
//signature verification
let leftSide = Number((BigInt(y) ** BigInt(r)) * (BigInt(r) ** BigInt(s)) % BigInt(p));
console.log("(y^r)*(r^s) mod p = (" + y + "^" + r + ")*(" + r + "^" + s + ") mod " + p + " = " + leftSide);
let rightSide = Number((BigInt(g) ** BigInt(h)) % BigInt(p));
console.log("(g^h) mod p = (" + g + "^" + h + ") mod " + p + " = " + rightSide);
if (leftSide === rightSide) console.log("Цифровая подпись прошла проверку");
else console.log("Цифровая подпись не прошла проверку");
}
const extendedEeuclid = (a, b) => {
a = +a;
b = +b;
if (a !== a || b !== b) {
return [NaN, NaN, NaN];
}
if (a === Infinity || a === -Infinity || b === Infinity || b === -Infinity) {
return [Infinity, Infinity, Infinity];
}
if ((a % 1 !== 0) || (b % 1 !== 0)) {
return false;
}
var signX = (a < 0) ? -1 : 1,
signY = (b < 0) ? -1 : 1,
x = 0,
y = 1,
u = 1,
v = 0,
q, r, m, n;
a = Math.abs(a);
b = Math.abs(b);
while (a !== 0) {
q = Math.floor(b / a);
r = b % a;
m = x - u * q;
n = y - v * q;
b = a;
a = r;
x = u;
y = v;
u = m;
v = n;
}
return [b, signX * x, signY * y];
}
const NOD = (x, y) => {
if (y > x) return NOD(y, x);
if (!y) return x;
return NOD(y, x % y);
}
const isPrime = num => {
for(let i = 2, s = Math.sqrt(num); i <= s; i++)
if(num % i === 0) return false;
return num > 1;
}
const getRandomInt = max => {
let randomNumber = -1;
while (randomNumber<0 || NOD(randomNumber, max) !== 1 || !isPrime(randomNumber)){
randomNumber = Math.floor(Math.random() * Math.floor(max));
}
return randomNumber;
}
const findCRC = (number, g_x) => {
let size;
let substr = "";
let str = number.toString(2);
str += '0'.repeat(g_x.length);
while(str !== ""){
do {
size = g_x.length - substr.length;
substr += str.slice(0, size);
substr = parseInt(substr, 2).toString(2);
str = str.replace(str.slice(0,size), "");
} while (substr.length !== g_x.length && str !== "");
if (substr.length === g_x.length) {
substr = (parseInt(substr, 2) ^ parseInt(g_x, 2)).toString(2);
if (str === "") return substr;
} else return(substr);
}
}
const getM = plainText => {
return parseInt(plainText.split('').map((a) => {return a.charCodeAt(0).toString(2).padStart(8, "0")}).join(''), 2);
}