-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEnd2End.java
More file actions
378 lines (342 loc) · 13.8 KB
/
End2End.java
File metadata and controls
378 lines (342 loc) · 13.8 KB
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
package com.abhaytr.jmulticrypt;
/*
Welcome To JMULTICRYPT
Java module for the new and the secure
MULTICRYPT encryption algorithm made by me which is
a hybrid encryption system (consists of
both symmetric and asymmetric encryption)
and is designed specially for End-2-End encryption
(for more details on the algorithm,
read the readme.md on https://github.com/AbhayTr/JMultiCrypt).
Usage:
Constructor: End2End()
@params for Constructor
public_key (Optional): Public Key to be used if you want to use existing key (Default: "").
private_key (Optional): Private Key to be used if you want to use existing key (Default: "").
save (Optional): Should be true/false. Specifies whether the keys have to be stored in a file or not (Default: true).
key_path (Optional): Specifies the path and name of the file where the keys have to be stored, if save = true (Default: root of your java projct)(NOTE: Default value won't work in Android Project).
new (Optional): Should be true/false. Specifies whether it should ignore any existing key pairs and generate new key pair or not (Default: false).
Methods:
1. keys(): Returns Private Key and Public Key in the form of Map of the format {"public": %YOUR_PUBLIC_KEY%, "private": %YOUR_PRIVATE_KEY%}.
2. encrypt(): Encrypts the message using MULTICRYPT algorithm.
@params
message (Required): Message to encrypt.
public_key (Required): Public Key of the recipient of the message (for the asymmetric encryption part).
3. decrypt(): Decrypts the encrypted message using MULTICRYPT algorithm.
@params
message (Required): Encrypted Message to decryt.
private_key (Optional): Your Private Key required to decrypt any message which is encrypted with Public Key
linked to that private key (Default: Key which was either passed in the paramters
map or generated by the program for you).
Useful for transmitting data securely between 2 devices on a network.
© Abhay Tripathi
*/
import java.io.*;
import java.math.*;
import java.nio.charset.*;
import java.security.*;
import java.util.*;
public class End2End
{
private final char char_glyph[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
public int[] primes_list =
{
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131,
137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197,
199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271,
277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349
};
public static Map schema;
static
{
schema = new HashMap();
schema.put("1", "a");
schema.put("2", "b");
schema.put("3", "c");
schema.put("4", "d");
schema.put("5", "e");
schema.put("6", "f");
schema.put("7", "g");
schema.put("8", "h");
schema.put("9", "i");
schema.put("0", "j");
}
public static Map reverse_schema;
static
{
reverse_schema = new HashMap();
reverse_schema.put("a", "1");
reverse_schema.put("b", "2");
reverse_schema.put("c", "3");
reverse_schema.put("d", "4");
reverse_schema.put("e", "5");
reverse_schema.put("f", "6");
reverse_schema.put("g", "7");
reverse_schema.put("h", "8");
reverse_schema.put("i", "9");
reverse_schema.put("j", "0");
}
public String public_key = "";
public String private_key = "";
public boolean save = true;
public String key_path = "key_pair.key";
public boolean new_keys = false;
public End2End(Map parameters)
{
if (parameters != null)
{
if (parameters.containsKey("public_key") && parameters.containsKey("private_key"))
{
this.public_key = parameters.get("public_key").toString();
this.private_key = parameters.get("private_key").toString();
}
if (parameters.containsKey("save"))
{
this.save = (boolean) parameters.get("save");
}
if (parameters.containsKey("key_path"))
{
this.key_path = parameters.get("key_path").toString();
}
if (parameters.containsKey("new_keys"))
{
this.new_keys = (boolean) parameters.get("new");
}
}
if (this.public_key.equals("") || this.private_key.equals(""))
{
try
{
if (this.new_keys)
{
throw new Exception("Generate New Key Pair.");
}
ArrayList<String> lines = new ArrayList<String>();
File keys = new File(this.key_path);
Scanner key_reader = new Scanner(keys);
while (key_reader.hasNextLine())
{
String line = key_reader.nextLine();
lines.add(line);
}
key_reader.close();
this.private_key = lines.get(0);
this.public_key = lines.get(1);
}
catch (Exception generate_new)
{
try
{
Map fresh_keys = get_keys();
this.private_key = fresh_keys.get("private").toString();
this.public_key = fresh_keys.get("public").toString();
if (this.save)
{
FileWriter save_keys = new FileWriter(this.key_path);
save_keys.write(this.private_key + "\n" + this.public_key);
save_keys.close();
}
}
catch (Exception io)
{
throw new RuntimeException("Failed to save keys due to the following error:\n\n" + io.getMessage());
}
}
}
else
{
try
{
if (this.save)
{
FileWriter save_keys = new FileWriter(this.key_path);
save_keys.write(this.private_key + "\n" + this.public_key);
save_keys.close();
}
}
catch (Exception io)
{
throw new RuntimeException("Failed to save keys due to the following error:\n\n" + io.getMessage());
}
}
}
public boolean is_coprime(BigInteger number1, BigInteger number2)
{
while (!number2.equals(BigInteger.ZERO))
{
BigInteger prev_number_1 = number1;
number1 = number2;
number2 = prev_number_1.mod(number2);
}
return (number1.equals(BigInteger.ONE));
}
public String hexlify(byte[] bytes)
{
StringBuilder hex_ascii = new StringBuilder(bytes.length * 2);
for (int i = 0; i < bytes.length; ++i)
{
byte b = bytes[i];
hex_ascii.append(char_glyph[(int)(b & 0xf0) >> 4]);
hex_ascii.append(char_glyph[(int)(b & 0x0f)]);
}
return hex_ascii.toString();
}
public byte[] unhexlify(byte[] ascii_hex)
{
if((ascii_hex.length % 2) != 0)
{
throw new RuntimeException("Only even-length number allowed");
}
int ascii_len = ascii_hex.length;
byte[] original_data = new byte[ascii_len / 2];
for (int i = 0; i < ascii_len; i += 2)
{
original_data[i / 2] = (byte)((Character.digit(ascii_hex[i], 16) << 4) + Character.digit(ascii_hex[i + 1], 16));
}
return original_data;
}
public BigInteger compress_string(String string)
{
return new BigInteger(hexlify(string.getBytes(Charset.forName("ISO-8859-1"))), 16);
}
public String deflate_string(BigInteger number)
{
String number_string = String.format("%x", number);
byte[] encoded_bytes = number_string.getBytes(Charset.forName("ISO-8859-1"));
return new String(unhexlify(encoded_bytes), Charset.forName("ISO-8859-1"));
}
public String compress_number(String number)
{
String compressed_number_string = "";
for (int digit_number = 0; digit_number < number.length(); digit_number++)
{
try
{
String formatted_digit = this.schema.get(Character.toString(number.charAt(digit_number))).toString();
if (formatted_digit != null)
{
compressed_number_string += formatted_digit;
}
else
{
throw new Exception("Directly add charecter");
}
}
catch (Exception direct_add)
{
compressed_number_string += number.charAt(digit_number);
}
}
return compressed_number_string;
}
public String deflate_number(String number_string)
{
String deflated_number = "";
for (int charecter_number = 0; charecter_number < number_string.length(); charecter_number++)
{
try
{
String original_digit = this.reverse_schema.get(Character.toString(number_string.charAt(charecter_number))).toString();
if (original_digit != null)
{
deflated_number += original_digit;
}
else
{
throw new Exception("Directly add charecter");
}
}
catch (Exception direct_add)
{
deflated_number += number_string.charAt(charecter_number);
}
}
return deflated_number;
}
public Map get_keys()
{
BigInteger prime_key_1 = BigInteger.probablePrime(1024, new SecureRandom());
BigInteger prime_key_2 = BigInteger.probablePrime(1024, new SecureRandom());
BigInteger public_key_number = prime_key_1.multiply(prime_key_2);
BigInteger phi_n = (prime_key_1.add(new BigInteger("-1"))).multiply(prime_key_2.add(new BigInteger("-1")));
BigInteger e = BigInteger.ZERO;
for (BigInteger number = new BigInteger("2"); number.compareTo(phi_n) == -1; number = number.add(BigInteger.ONE))
{
if (is_coprime(phi_n, number))
{
e = number;
break;
}
}
String public_key = public_key_number.toString() + "X" + e.toString();
String private_key = (e.modInverse(phi_n)).toString() + "X" + public_key_number.toString();
public_key = compress_number(public_key);
private_key = compress_number(private_key);
Map keys = new HashMap();
keys.put("public", public_key);
keys.put("private", private_key);
return keys;
}
public Map keys()
{
Map keys = new HashMap();
keys.put("public", this.public_key);
keys.put("private", this.private_key);
return keys;
}
public String rsa_encrypt(String message, String public_key)
{
public_key = deflate_number(public_key);
int seperator_position = public_key.indexOf("X");
BigInteger e = new BigInteger(public_key.substring((seperator_position + 1), (public_key.length())));
BigInteger public_key_number = new BigInteger(public_key.substring(0, seperator_position));
String encrypted_message = "";
byte[] charecters = message.getBytes();
for (int charecter_index = 0; charecter_index < charecters.length; charecter_index++)
{
encrypted_message += Integer.toString((int) charecters[charecter_index]);
if (charecter_index != (charecters.length - 1))
{
encrypted_message += "300";
}
}
encrypted_message = (new BigInteger(encrypted_message).modPow(e, public_key_number)).toString();
return encrypted_message;
}
public String rsa_decrypt(String message, String private_key)
{
private_key = deflate_number(private_key);
int seperator_position = private_key.indexOf("X");
BigInteger public_key_number = new BigInteger(private_key.substring((seperator_position + 1), (private_key.length())));
BigInteger private_key_number = new BigInteger(private_key.substring(0, seperator_position));
String[] charecters = (new BigInteger(message).modPow(private_key_number, public_key_number)).toString().split("300");
String actual_message = "";
for (String charecter : charecters)
{
actual_message += (char) Integer.parseInt(charecter);
}
return actual_message;
}
public String encrypt(String message, String public_key)
{
BigInteger key = BigInteger.probablePrime(256, new Random());
BigInteger encrypted_message = compress_string(message).add(key);
return (compress_number(encrypted_message.toString()) + "K" + compress_number(rsa_encrypt(key.toString(), public_key)));
}
public String decrypt(String message, String private_key)
{
if (private_key.isEmpty())
{
private_key = this.private_key;
}
int seperator_position = message.indexOf("K");
String encrypted_message = message.substring(0, seperator_position);
String encrypted_key = deflate_number(message.substring((seperator_position + 1), (message.length())));
encrypted_message = deflate_number(encrypted_message);
String key = rsa_decrypt(encrypted_key, private_key);
BigInteger actual_message_number = new BigInteger(encrypted_message).add(new BigInteger(key).multiply(new BigInteger("-1")));
String actual_message = deflate_string(actual_message_number);
return actual_message;
}
}