-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimple_rsa.c
171 lines (159 loc) · 5.25 KB
/
simple_rsa.c
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
====================================================================================================
simple_rsa is a very simple implementation of the basic RSA encryption algorithm
===== IMPORTANT NOTE =====
This program does NOT fulfil any safety standards! It should NOT be used for real
encryption, because it does not provide any safety! This program is only written
for teaching purposes.
simple_rsa is distributed without any warranty!
======== LICENSE ========
simple_rsa is free software; you can modify it or redistribute it
under the terms of the GNU General Public License as published by
the Free Software Foundation <http://www.fsf.org>, either version 3,
or (at your option) any later version.
See <http://www.gnu.org/licenses> for the license, if you
haven't received a copy of it (GNU_GPL.txt).
====================================================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
//generaing a random number between RANDMIN and RANDMAX
unsigned long get_rand(unsigned long RANDMAX, unsigned long RANDMIN) {
unsigned long r;
r = (rand() % (RANDMAX - RANDMIN + 1)) + RANDMIN;
return r;
}
//get a random prime between MIN and MAX
unsigned long get_prime(unsigned long MAX, unsigned long MIN) {
unsigned long rand_num;
unsigned int i;
unsigned short prime = 1;
while (prime != 0) {
prime = 0;
rand_num = get_rand(MAX, MIN);
for(i = 2; i < rand_num / 2 && !prime; i++) {
if(rand_num % i == 0) {
prime = 1;
}
}
}
return rand_num;
}
//get grearesult common divisor of numbers a and b using Euclidean algorithm
unsigned long gcd(unsigned long a, unsigned long b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
//get modular inverse of numbers a b
double modular_inverse(unsigned long a, unsigned long b) {
long b0 = b, t, q;
long x0 = 0, x1 = 1;
if (b == 1) return 1;
while (a > 1) {
q = a / b;
t = b, b = a % b, a = t;
t = x0, x0 = x1 - q * x0, x1 = t;
}
if (x1 < 0) x1 += b0;
return x1;
}
long n;
unsigned long e;
long d;
//function for generating key pair
void generate_keys(unsigned long PRIMEMIN, unsigned long PRIMEMAX, unsigned long EMIN, unsigned long EMAX) {
printf("\nStarting RSA key generation...\n");
unsigned long p, q, phi_n;
//generating two random prime numbers
p = get_prime(PRIMEMAX, PRIMEMIN);
q = get_prime(PRIMEMAX, PRIMEMIN);
n = p * q;
phi_n = (p - 1) * (q - 1);
unsigned long coprime = 0;
while (coprime != 1) {
e = get_rand(EMAX, EMIN);
coprime = gcd(phi_n,e);
}
d = modular_inverse(e, phi_n);
printf("p: %ld\nq: %ld\nn: %ld\ne: %ld\n",p,q,n,e);
printf("d: %ld\n====================================================\n",d);
}
unsigned long modular_power(unsigned long num, unsigned long pow, unsigned long mod)
{
//using modular exponentation is faster; this algorithm can deal with much greater numbers than just using remainder()
unsigned long long result;
unsigned long long n = num;
for(result = 1; pow; pow >>= 1) {
if (pow & 1)
result = ((result % mod) * (n % mod)) % mod;
n = ((n % mod) * (n % mod)) % mod;
}
return result;
}
//main function
int main(void) {
unsigned long PRIMEMIN = 10000;
unsigned long PRIMEMAX = 100000;
unsigned long EMIN = 2000;
unsigned long EMAX = 5000;
char message[50];
unsigned long char_num;
unsigned long long enc_text[50];
unsigned long long dec_text[50];
unsigned long long encrypted, decrypted;
unsigned int correct = 0;
unsigned int i = 0;
system("clear");
srand(time(NULL));
while (correct != 1) {
system("clear");
generate_keys(PRIMEMIN, PRIMEMAX, EMIN, EMAX);
encrypted = modular_power(123, e, n);
decrypted = modular_power(encrypted, d, n);
if (decrypted == 123)
correct = 1;
}
printf("=> Public key: (%ld , %ld)\n=> Private key: (%ld , %ld)\n", n, e, n, d);
printf("====================================================\nEnter text to encrypt: ");
fgets(message, 50, stdin);
printf("Clear text message: %s\n", message);
printf("====================================================\n");
printf("Encrypting...\n");
for (i = 0; i < strlen(message)-1; i++) {
printf("%d ",message[i]);
char_num = message[i];
encrypted = modular_power(char_num, e, n);
enc_text[i] = encrypted;
}
printf("\nEncrypted message:\n");
for (i = 0; i < strlen(message)-1; i++) {
printf("%lld ", enc_text[i]);
}
printf("\n====================================================\n");
printf("Decrypting...\n");
for (i = 0; i < strlen(message)-1; i++) {
decrypted = modular_power(enc_text[i], d, n);
dec_text[i] = decrypted;
}
printf("\nDecrypted message:\n");
for (i = 0; i < strlen(message)-1; i++) {
printf("%lld ", dec_text[i]);
}
correct = 1;
for (i = 0; i < strlen(message)-1; i++) {
if (message[i] != dec_text[i]) {
correct = 0;
}
}
printf("\n====================================================\n");
if (correct == 1) printf("Decrypted message same as original message!\n");
if (correct == 0) printf("Decrypted message not same as original message!\n");
printf("====================================================\n");
return EXIT_SUCCESS;
}