TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
elliptic_curve_key_exchange.cpp
Go to the documentation of this file.
1
24#include <cassert>
25#include <iostream>
26
27#include "uint256_t.hpp"
28
33namespace ciphers {
40namespace elliptic_curve_key_exchange {
41
46typedef struct Point {
47 uint256_t x, y;
48
55 inline bool operator==(const Point &p) { return x == p.x && y == p.y; }
56
63 friend std::ostream &operator<<(std::ostream &op, const Point &p) {
64 op << p.x << " " << p.y;
65 return op;
66 }
68
79 if (!power) {
80 return uint256_t(1);
81 }
82 uint256_t ans(1);
83 number = number % mod;
84 while (power) {
85 if ((power & 1)) {
86 ans = (ans * number) % mod;
87 }
88 power >>= 1;
89 if (power) {
90 number = (number * number) % mod;
91 }
92 }
93 return ans;
94}
95
110Point addition(Point a, Point b, const uint256_t &curve_a_coeff,
111 uint256_t mod) {
112 uint256_t lambda(0);
113 uint256_t zero(0);
114 lambda = zero = 0;
115 uint256_t inf = ~zero;
116 if (a.x != b.x || a.y != b.y) {
117 // Slope being infinite.
118 if (b.x == a.x) {
119 return {inf, inf};
120 }
121 uint256_t num = (b.y - a.y + mod), den = (b.x - a.x + mod);
122 lambda = (num * (exp(den, mod - 2, mod))) % mod;
123 } else {
134 if (!a.y) {
135 return {inf, inf};
136 }
137 uint256_t axsq = ((a.x * a.x)) % mod;
138 // Mulitply by 3 adjustment
139 axsq += (axsq << 1);
140 axsq %= mod;
141 // Mulitply by 2 adjustment
142 uint256_t a_2 = (a.y << 1);
143 lambda =
144 (((axsq + curve_a_coeff) % mod) * exp(a_2, mod - 2, mod)) % mod;
145 }
146 Point c;
147 // new point: x = ((lambda^2) - x1 - x2)
148 // y = (lambda * (x1 - x)) - y1
149 c.x = ((lambda * lambda) % mod + (mod << 1) - a.x - b.x) % mod;
150 c.y = (((lambda * (a.x + mod - c.x)) % mod) + mod - a.y) % mod;
151 return c;
152}
153
165Point multiply(const Point &a, const uint256_t &curve_a_coeff, uint256_t p,
166 const uint256_t &mod) {
167 Point N = a;
168 N.x %= mod;
169 N.y %= mod;
170 uint256_t inf{};
171 inf = ~uint256_t(0);
172 Point Q = {inf, inf};
173 while (p) {
174 if ((p & 1)) {
175 if (Q.x == inf && Q.y == inf) {
176 Q.x = N.x;
177 Q.y = N.y;
178 } else {
179 Q = addition(Q, N, curve_a_coeff, mod);
180 }
181 }
182 p >>= 1;
183 if (p) {
184 N = addition(N, N, curve_a_coeff, mod);
185 }
186 }
187 return Q;
188}
189} // namespace elliptic_curve_key_exchange
190} // namespace ciphers
191
197static void uint128_t_tests() {
198 // 1st test: Operations test
199 uint128_t a("122"), b("2312");
200 assert(a + b == 2434);
201 assert(b - a == 2190);
202 assert(a * b == 282064);
203 assert(b / a == 18);
204 assert(b % a == 116);
205 assert((a & b) == 8);
206 assert((a | b) == 2426);
207 assert((a ^ b) == 2418);
208 assert((a << 64) == uint128_t("2250502776992565297152"));
209 assert((b >> 7) == 18);
210
211 // 2nd test: Operations test
212 a = uint128_t("12321421424232142122");
213 b = uint128_t("23123212");
214 assert(a + b == uint128_t("12321421424255265334"));
215 assert(a - b == uint128_t("12321421424209018910"));
216 assert(a * b == uint128_t("284910839733861759501135864"));
217 assert(a / b == 532859423865LL);
218 assert(a % b == 3887742);
219 assert((a & b) == 18912520);
220 assert((a | b) == uint128_t("12321421424236352814"));
221 assert((a ^ b) == uint128_t("12321421424217440294"));
222 assert((a << 64) == uint128_t("227290107637132170748078080907806769152"));
223}
224
230static void uint256_t_tests() {
231 // 1st test: Operations test
232 uint256_t a("122"), b("2312");
233 assert(a + b == 2434);
234 assert(b - a == 2190);
235 assert(a * b == 282064);
236 assert(b / a == 18);
237 assert(b % a == 116);
238 assert((a & b) == 8);
239 assert((a | b) == 2426);
240 assert((a ^ b) == 2418);
241 assert((a << 64) == uint256_t("2250502776992565297152"));
242 assert((b >> 7) == 18);
243
244 // 2nd test: Operations test
245 a = uint256_t("12321423124513251424232142122");
246 b = uint256_t("23124312431243243215354315132413213212");
247 assert(a + b == uint256_t("23124312443564666339867566556645355334"));
248 // Since a < b, the value is greater
249 assert(a - b == uint256_t("115792089237316195423570985008687907853246860353"
250 "221642219366742944204948568846"));
251 assert(a * b == uint256_t("284924437928789743312147393953938013677909398222"
252 "169728183872115864"));
253 assert(b / a == uint256_t("1876756621"));
254 assert(b % a == uint256_t("2170491202688962563936723450"));
255 assert((a & b) == uint256_t("3553901085693256462344"));
256 assert((a | b) == uint256_t("23124312443564662785966480863388892990"));
257 assert((a ^ b) == uint256_t("23124312443564659232065395170132430646"));
258 assert((a << 128) == uint256_t("4192763024643754272961909047609369343091683"
259 "376561852756163540549632"));
260}
261
267static void test() {
268 // demonstration of key exchange using curve secp112r1
269
270 // Equation of the form y^2 = (x^3 + ax + b) % P (here p is mod)
271 uint256_t a("4451685225093714772084598273548424"),
272 b("2061118396808653202902996166388514"),
273 mod("4451685225093714772084598273548427");
274
275 // Generator value: is pre-defined for the given curve
277 uint256_t("188281465057972534892223778713752"),
278 uint256_t("3419875491033170827167861896082688")};
279
280 // Shared key generation.
281 // For alice
282 std::cout << "For alice:\n";
283 // Alice's private key (can be generated randomly)
284 uint256_t alice_private_key("164330438812053169644452143505618");
286 multiply(ptr, a, alice_private_key, mod);
287 std::cout << "\tPrivate key: " << alice_private_key << "\n";
288 std::cout << "\tPublic Key: " << alice_public_key << std::endl;
289
290 // For Bob
291 std::cout << "For Bob:\n";
292 // Bob's private key (can be generated randomly)
293 uint256_t bob_private_key("1959473333748537081510525763478373");
295 multiply(ptr, a, bob_private_key, mod);
296 std::cout << "\tPrivate key: " << bob_private_key << "\n";
297 std::cout << "\tPublic Key: " << bob_public_key << std::endl;
298
299 // After public key exchange, create a shared key for communication.
300 // create shared key:
302 bob_public_key, a,
303 alice_private_key, mod),
304 bob_shared_key = multiply(
305 alice_public_key, a,
306 bob_private_key, mod);
307
308 std::cout << "Shared keys:\n";
309 std::cout << alice_shared_key << std::endl;
310 std::cout << bob_shared_key << std::endl;
311
312 // Check whether shared keys are equal
313 assert(alice_shared_key == bob_shared_key);
314}
315
320int main() {
321 uint128_t_tests(); // running predefined 128-bit unsigned integer tests
322 uint256_t_tests(); // running predefined 256-bit unsigned integer tests
323 test(); // running self-test implementations
324 return 0;
325}
class for 128-bit unsigned integer
Definition uint128_t.hpp:60
class for 256-bit unsigned integer
Definition uint256_t.hpp:33
static void uint256_t_tests()
Function to test the uint256_t header.
static void uint128_t_tests()
Function to test the uint128_t header.
static void test()
Function to test the provided algorithm above.
int main()
Main function.
Point multiply(const Point &a, const uint256_t &curve_a_coeff, uint256_t p, const uint256_t &mod)
multiply Point and integer
uint256_t exp(uint256_t number, uint256_t power, const uint256_t &mod)
This function calculates number raised to exponent power under modulo mod using Modular Exponentiatio...
Point addition(Point a, Point b, const uint256_t &curve_a_coeff, uint256_t mod)
Addition of points.
struct ciphers::elliptic_curve_key_exchange::Point Point
Definition of struct Point.
Algorithms for encryption and decryption.
int multiply(int x, int res[], int res_size)
void power(int x, int n)
bool operator==(const Point &p)
x and y co-ordinates
friend std::ostream & operator<<(std::ostream &op, const Point &p)
ostream operator for printing Point