· 9 years ago · Nov 10, 2016, 09:22 PM
1/*
2* Author: Zubin Kadva
3* CSE 5673 Cryptology Fall 2016
4* An implementation of the RSA algorithm
5*/
6
7package com.company;
8
9import java.io.*;
10import java.math.BigInteger;
11import java.security.SecureRandom;
12import java.util.Arrays;
13import java.util.List;
14
15public class RSA {
16
17 private final String KEYS = "-K", PUBLIC_KEY = "-p", SECRET_KEY = "-s",
18 BITS = "-b", CERTAINTY = "-y", ENCRYPT = "-e", DECRYPT = "-d",
19 PLAIN = "-m", CIPHER = "-c";
20 private BigInteger p, q, n, e, dp, dq, qinv, plain, cipher;
21 private String[] temp;
22
23 public static void main(String[] args) {
24
25 List options = Arrays.asList(args);
26 RSA rsa = new RSA();
27 rsa.start(options);
28
29 /*
30 Scanner scanner = new Scanner(System.in);
31 SecureRandom secureRandom = new SecureRandom();
32 String n, e, message;
33 int k, mlen;
34
35 System.out.print("Enter n, e: ");
36 n = scanner.next();
37 e = scanner.next();
38 System.out.print("Enter message: ");
39 message = scanner.next();
40
41 k = n.getBytes().length;
42 mlen = message.getBytes().length;
43
44 if (message.getBytes().length > (k - 11)) return;
45
46 secureRandom.nextBytes(new byte[k - mlen - 11]);
47*/
48
49 }
50
51 // RSA OPS BEGIN
52
53 private void start(List options) {
54 String publicKeyFile, secretKeyFile, plainFile, cipherFile;
55 try {
56 if (options.contains(KEYS)) {
57 if (generateKeysCheck(options)) {
58 int bits = Integer.parseInt(options.get(options.indexOf(BITS) + 1).toString());
59 int certainty = Integer.parseInt(options.get(options.indexOf(CERTAINTY) + 1).toString());
60 publicKeyFile = options.get(options.indexOf(PUBLIC_KEY) + 1).toString();
61 secretKeyFile = options.get(options.indexOf(SECRET_KEY) + 1).toString();
62 generateKeys(bits, certainty, publicKeyFile, secretKeyFile);
63 return;
64 }
65 } else if (options.contains(ENCRYPT)) {
66 if (encryptCheck(options)) {
67 publicKeyFile = options.get(options.indexOf(PUBLIC_KEY) + 1).toString();
68 plainFile = options.get(options.indexOf(PLAIN) + 1).toString();
69 cipherFile = options.get(options.indexOf(CIPHER) + 1).toString();
70 encrypt(publicKeyFile, plainFile, cipherFile);
71 return;
72 }
73 } else if (options.contains(DECRYPT)) {
74 if (decryptCheck(options)) {
75 secretKeyFile = options.get(options.indexOf(SECRET_KEY) + 1).toString();
76 plainFile = options.get(options.indexOf(PLAIN) + 1).toString();
77 cipherFile = options.get(options.indexOf(CIPHER) + 1).toString();
78 decrypt(secretKeyFile, plainFile, cipherFile);
79 return;
80 }
81 }
82 showHelp();
83 } catch (Exception e) {
84 System.out.println(e.getMessage());
85 }
86 }
87
88 private void encrypt(String publicKeyFile, String plainFile, String cipherFile) {
89 try {
90 temp = read(publicKeyFile).split(" ");
91 plain = new BigInteger(read(plainFile).trim().getBytes());
92 n = new BigInteger(temp[0], 16);
93 if (n.bitCount() < plain.bitCount()) {
94 System.out.println("Cannot encrypt message. Key bit length too small!!");
95 return;
96 }
97 e = new BigInteger(temp[1], 16);
98 cipher = plain.modPow(e, n); // c = m^e mod n
99 write(cipherFile, toHex(cipher));
100 System.out.println("Cipher text: " + toHex(cipher));
101 } catch (Exception e) {
102 System.out.println("Error: File Not Found!!");
103 }
104 }
105
106 private void decrypt(String secretKeyFile, String plainFile, String cipherFile) {
107 try {
108 temp = read(secretKeyFile).split(" ");
109 cipher = new BigInteger(read(cipherFile).trim(), 16);
110 p = new BigInteger(temp[3], 16);
111 q = new BigInteger(temp[4], 16);
112 dp = new BigInteger(temp[5], 16);
113 dq = new BigInteger(temp[6], 16);
114 qinv = new BigInteger(temp[7], 16);
115 BigInteger m1 = cipher.modPow(dp, p); // m1 = c^dp mod p
116 BigInteger m2 = cipher.modPow(dq, q); // m2 = c^dq mod q
117 BigInteger h = (m1.subtract(m2)).multiply(qinv).mod(p); // h = ((m1 - m2) * qinv) mod p
118 plain = m2.add(q.multiply(h)); // m = m2 + q * h
119 System.out.println("m1 = " + toHex(m1));
120 System.out.println("m2 = " + toHex(m2));
121 System.out.println("h = " + toHex(h));
122 System.out.println("Plain text: " + new String(plain.toByteArray()));
123 write(plainFile, new String(plain.toByteArray()));
124 } catch (Exception e) {
125 System.out.println(e.getMessage());
126 }
127 }
128
129 private void generateKeys(int bits, int certainty,
130 String publicKeyFile, String secretKeyFile) throws IOException {
131 p = new BigInteger(bits, certainty, new SecureRandom());
132
133 do
134 q = new BigInteger(bits, certainty, new SecureRandom());
135 while (!p.gcd(q).equals(BigInteger.valueOf(1)));
136
137 n = p.multiply(q);
138 BigInteger phiN = p.subtract(BigInteger.valueOf(1)).
139 multiply(q.subtract(BigInteger.valueOf(1)));
140
141 do
142 e = new BigInteger(bits, new SecureRandom());
143 while (!e.gcd(phiN).equals(new BigInteger("1")));
144
145 BigInteger d = e.modInverse(phiN);
146 dp = d.mod((p.subtract(BigInteger.valueOf(1))));
147 dq = d.mod((q.subtract(BigInteger.valueOf(1))));
148 qinv = q.modInverse(p);
149
150 write(secretKeyFile, toHex(n) + "\n" + toHex(e) + "\n" + toHex(d) + "\n" +
151 toHex(p) + "\n" + toHex(q) + "\n" + toHex(dp) + "\n" +
152 toHex(dq) + "\n" + toHex(qinv));
153
154 write(publicKeyFile, toHex(n) + "\n" + toHex(e));
155
156 System.out.println("n = " + toHex(n));
157 System.out.println("e = " + toHex(e));
158 System.out.println("d = " + toHex(d));
159 System.out.println("p = " + toHex(p));
160 System.out.println("q = " + toHex(q));
161 System.out.println("dp = " + toHex(dp));
162 System.out.println("dq = " + toHex(dq));
163 System.out.println("qinv = " + toHex(qinv));
164 }
165
166 // RSA OPS END
167
168 // FILE I/O FUNCTIONS BEGIN
169
170 private String read(String name) throws IOException {
171 FileReader fileReader = new FileReader(new File(name));
172 BufferedReader bufferedReader = new BufferedReader(fileReader);
173 String s, r = "";
174 while ((s = bufferedReader.readLine()) != null)
175 r += s + " ";
176 bufferedReader.close();
177 fileReader.close();
178 return r;
179 }
180
181 private void write(String name, String data) throws IOException {
182 FileWriter fileWriter = new FileWriter(new File(name));
183 fileWriter.write(data);
184 fileWriter.close();
185 }
186
187 // FILE I/O FUNCTIONS END
188
189 private void showHelp() {
190 String help = "Usage:\njava " + RSA.class.getName() + " " + KEYS + " " + PUBLIC_KEY +
191 " <public_key_file> " + SECRET_KEY + " <secret_key_file> " +
192 BITS + " <bits> " + CERTAINTY + " <Miller_Rabin_certainty>\n" +
193 "java " + RSA.class.getName() + " -h\n" +
194 "java " + RSA.class.getName() + " " + ENCRYPT + " " + PLAIN + " " + " <plaintext_file> " +
195 PUBLIC_KEY + " <public_key_file> " + CIPHER + " <ciphertext_file>\n" +
196 "java " + RSA.class.getName() + " " + DECRYPT + " " + CIPHER + " " + " <ciphertext_file> " +
197 SECRET_KEY + " <secret_key_file> " + PLAIN + " <plaintext_file>";
198 System.out.println(help);
199 }
200
201 // VALIDATION FUNCTIONS BEGIN
202
203 private boolean generateKeysCheck(List options) {
204 return options.contains(PUBLIC_KEY) && options.contains(SECRET_KEY) &&
205 options.contains(BITS) && options.contains(CERTAINTY);
206 }
207
208 private boolean decryptCheck(List options) {
209 return options.contains(CIPHER) && options.contains(SECRET_KEY) &&
210 options.contains(PLAIN);
211 }
212
213 private boolean encryptCheck(List options) {
214 return options.contains(PLAIN) && options.contains(PUBLIC_KEY) &&
215 options.contains(CIPHER);
216 }
217
218 // VALIDATION FUNCTIONS END
219
220 // UTILITY FUNCTIONS BEGIN
221
222 private String toHex(BigInteger bigInteger) {
223 return bigInteger.toString(16).toUpperCase();
224 }
225
226 // UTILITY FUNCTIONS END
227
228}