forked from gadial/ECC
-
Notifications
You must be signed in to change notification settings - Fork 1
/
elgamal.cpp
121 lines (107 loc) · 3.24 KB
/
elgamal.cpp
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
/*
* elgamal.cpp
*
* Created on: Jan 27, 2010
* Author: bhess
*/
#include "elgamal.h"
ECC_ElGamal::ECC_ElGamal(Ellipticcurve* E) { ell = E;}
ECC_ElGamal_Ciphertext ECC_ElGamal::encrypt_element(ECC_ElGamal_Plaintext m) {
//ECC_ElGamal_Ciphertext eco;
Coordinate C1, C2;
Coordinate M = m.P;
Coordinate P = ell->point;
mpz_class n = ell->getOrder();
mpz_class k = rand.rand(n - 1);
C1 = ell->pointMultiplication(P, k);
Coordinate kQ = ell->pointMultiplication(Q, k);
C2 = ell->addition(M, kQ);
return ECC_ElGamal_Ciphertext(C1, C2);
}
/*
ECC_ElGamal_Ciphertext ECC_ElGamal::encrypt_element(string m) {
return encrypt_element(ECC_ElGamal_Plaintext(to_point(m)));
}
*/
ECC_ElGamal_Plaintext ECC_ElGamal::decrypt_element (ECC_ElGamal_Ciphertext ciphertext) {
Coordinate dC1 = ell->pointMultiplication(ciphertext.C1, d);
return ECC_ElGamal_Plaintext(ell->subtraction(ciphertext.C2, dC1));
}
string ECC_ElGamal::encrypt(string m) {
return encrypt_element(ECC_ElGamal_Plaintext(to_point(m))).to_string(ell);
}
string ECC_ElGamal::decrypt(string c) {
ECC_ElGamal_Ciphertext ct = ECC_ElGamal_Ciphertext::from_string(c, ell);
ECC_ElGamal_Plaintext ep = decrypt_element(ct);
return remove_padding(ep);
}
string ECC_ElGamal::remove_padding(ECC_ElGamal_Plaintext& ep) {
string st = to_string(ep.P.X >> 8);
string res = "";
for (int i = 0; i < (int)st.size(); ++i) {
res += st[st.size() - 1 - i];
}
return res;
}
/*
vector<ECC_ElGamal_Plaintext> ECC_ElGamal::split_msg(string msg) {
int str_length_bits = msg.length();
int max_point_length_effective = get_max_point_length();
//cout << max_point_length_effective << endl;
int vec_el = (str_length_bits % max_point_length_effective == 0 ?
str_length_bits / max_point_length_effective : (str_length_bits / max_point_length_effective) + 1);
vector<ECC_ElGamal_Plaintext> res(vec_el);
for (int i = 0; i < vec_el; ++i) {
string s = msg.substr(i * max_point_length_effective, max_point_length_effective);
//ECC_ElGamal_Plaintext ep;
//cout << "Part " << i << ":" << s << endl;
//ep.P = to_point(s);
res[i] = ECC_ElGamal_Plaintext(to_point(s));
}
return res;
}
*/
int ECC_ElGamal::get_max_point_length() {
return (ell->get_bits() / 8) - 1;
}
Coordinate ECC_ElGamal::to_point(string str) {
mpz_class res = 0;
// 8 bit encoding of a character, as in ASCII...
//res.set_str(str, 256);
for (int i = 0; i < (int)str.size(); ++i) {
res |= (int)str[i];
if (i < (int)str.size() - 1) {
res <<= 8;
}
}
return get_point_with_padding(res, 1);
}
Coordinate ECC_ElGamal::get_point_with_padding(mpz_class str, int padding_length) {
mpz_class str_copy;
Coordinate c;
do {
// setting random padding until there exists a point
str_copy = str;
mpz_class pad = rand.rand(255);
str_copy <<= 8;
str_copy |= pad;
c = ell->getPoint_interface(str_copy, false);
} while(c.isInfinite());
return c;
}
void ECC_ElGamal::generate_random_keypair() {
d = rand.rand(ell->getOrder() - 1);
Q = ell->pointMultiplication(ell->point, d);
}
string ECC_ElGamal::to_string(mpz_class mpz) {
string res;
while (mpz != 0) {
res += (char)(mpz.get_ui() & 0xFF);
mpz >>= 8;
}
return res;
}
bool ECC_ElGamal::validate_curve() {
Coordinate m = ell->pointMultiplication(ell->point, ell->getOrder());
return m.isInfinite();
}