1 | /******************************************************************************
|
---|
2 | *
|
---|
3 | * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
|
---|
4 | * www.mindbright.se, [email protected]
|
---|
5 | *
|
---|
6 | * This program is free software; you can redistribute it and/or modify
|
---|
7 | * it under the terms of the GNU General Public License as published by
|
---|
8 | * the Free Software Foundation; either version 2 of the License, or
|
---|
9 | * (at your option) any later version.
|
---|
10 | *
|
---|
11 | * This program is distributed in the hope that it will be useful,
|
---|
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | * GNU General Public License for more details.
|
---|
15 | *
|
---|
16 | *****************************************************************************
|
---|
17 | * $Author: mats $
|
---|
18 | * $Date: 1999/01/13 09:42:07 $
|
---|
19 | * $Name: rel1-2-1 $
|
---|
20 | *****************************************************************************/
|
---|
21 | /*
|
---|
22 | * !!! Author's comment: The contents of this file is heavily based
|
---|
23 | * upon Tatu Ylonen's c-code in the ssh1.2.26 package, which in turn
|
---|
24 | * is a standard implementation of the RSA algorithm, the code is
|
---|
25 | * rather trivial (though the math behind it is not :-). I don't know
|
---|
26 | * whom are responsible for the original optimization using the
|
---|
27 | * Chinese remainder theorem which I guess is the only non-trivial
|
---|
28 | * part of this implementation. Please note that RSA can't be used
|
---|
29 | * without proper licensing in the United States.
|
---|
30 | *
|
---|
31 | * Below is some references to useful information about RSA:
|
---|
32 | *
|
---|
33 | * Bruce Schneier: Applied Cryptography 2nd ed., John Wiley & Sons, 1996
|
---|
34 | * Arto Salomaa: Public-Key Cryptography 2nd ed., Springer-Verlag, 1996
|
---|
35 | * Man Young Rhee: Cryptography and Secure Data Comm., McGraw-Hill, 1994
|
---|
36 | * R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
|
---|
37 | * System and Method. US Patent 4,405,829, 1983.
|
---|
38 | * Hans Riesel: Prime Numbers and Computer Methods for Factorization.
|
---|
39 | * Birkhauser, 1994.
|
---|
40 | */
|
---|
41 | package mindbright.security;
|
---|
42 |
|
---|
43 | import java.math.BigInteger;
|
---|
44 | import java.io.IOException;
|
---|
45 |
|
---|
46 | public class RSACipher {
|
---|
47 |
|
---|
48 | public KeyPair keys;
|
---|
49 |
|
---|
50 | public RSACipher(KeyPair keys) {
|
---|
51 | this.keys = keys;
|
---|
52 | }
|
---|
53 |
|
---|
54 | public BigInteger doPublic(BigInteger input) {
|
---|
55 | RSAPublicKey pubKey = (RSAPublicKey)keys.getPublic();
|
---|
56 | BigInteger result;
|
---|
57 |
|
---|
58 | result = input.modPow(pubKey.getE(), pubKey.getN());
|
---|
59 |
|
---|
60 | return result;
|
---|
61 | }
|
---|
62 |
|
---|
63 | public BigInteger doPrivate(BigInteger input) {
|
---|
64 | BigInteger dp;
|
---|
65 | BigInteger dq;
|
---|
66 | BigInteger p2;
|
---|
67 | BigInteger q2;
|
---|
68 | BigInteger k;
|
---|
69 | BigInteger result;
|
---|
70 | BigInteger one = BigInteger.valueOf(1L);
|
---|
71 | RSAPrivateKey privKey = (RSAPrivateKey)keys.getPrivate();
|
---|
72 |
|
---|
73 | dp = privKey.getP().subtract(one);
|
---|
74 | dp = privKey.getD().mod(dp);
|
---|
75 |
|
---|
76 | dq = privKey.getQ().subtract(one);
|
---|
77 | dq = privKey.getD().mod(dq);
|
---|
78 |
|
---|
79 | p2 = input.mod(privKey.getP());
|
---|
80 | p2 = p2.modPow(dp, privKey.getP());
|
---|
81 |
|
---|
82 | q2 = input.mod(privKey.getQ());
|
---|
83 | q2 = q2.modPow(dq, privKey.getQ());
|
---|
84 |
|
---|
85 | if(p2.compareTo(q2) == 0)
|
---|
86 | return p2;
|
---|
87 |
|
---|
88 | k = q2.subtract(p2).mod(privKey.getQ());
|
---|
89 | k = k.multiply(privKey.getU());
|
---|
90 | k = k.mod(privKey.getQ());
|
---|
91 |
|
---|
92 | result = k.multiply(privKey.getP());
|
---|
93 | result = result.add(p2);
|
---|
94 |
|
---|
95 | return result;
|
---|
96 | }
|
---|
97 |
|
---|
98 | public static BigInteger stripPad(BigInteger input) throws IOException {
|
---|
99 | byte[] strip = input.toByteArray();
|
---|
100 | byte[] val;
|
---|
101 | int i;
|
---|
102 |
|
---|
103 | if(strip[0] != 0x02)
|
---|
104 | throw new IOException("Invalid strip-data");
|
---|
105 | for(i = 0; i < strip.length; i++)
|
---|
106 | if(strip[i] == 0)
|
---|
107 | break;
|
---|
108 | if(i == strip.length)
|
---|
109 | throw new IOException("Invalid strip-data");
|
---|
110 | val = new byte[strip.length - i];
|
---|
111 | System.arraycopy(strip, i, val, 0, val.length);
|
---|
112 | return new BigInteger(val);
|
---|
113 | }
|
---|
114 |
|
---|
115 | public static BigInteger doPad(BigInteger input, int padLen, SecureRandom rand) throws IOException {
|
---|
116 | BigInteger result;
|
---|
117 | BigInteger rndInt;
|
---|
118 | int inByteLen = (input.bitLength() + 7) / 8;
|
---|
119 | int padByteLen = (padLen + 7) / 8;
|
---|
120 |
|
---|
121 | if(inByteLen > padByteLen - 3)
|
---|
122 | throw new IOException("rsaPad: Input too long to pad");
|
---|
123 |
|
---|
124 | // !!! byte[] ranBytes = new byte[(padByteLen - inByteLen - 3) + 1];
|
---|
125 | byte[] ranBytes = new byte[(padByteLen - inByteLen - 3) + 1];
|
---|
126 | rand.nextBytes(ranBytes);
|
---|
127 | ranBytes[0] = 0;
|
---|
128 | for(int i = 1; i < (padByteLen - inByteLen - 3 + 1); i++)
|
---|
129 | if(ranBytes[i] == 0)
|
---|
130 | ranBytes[i] = 0x17;
|
---|
131 |
|
---|
132 | rndInt = new BigInteger(ranBytes);
|
---|
133 | rndInt = rndInt.shiftLeft((inByteLen + 1) * 8);
|
---|
134 | result = new BigInteger("2");
|
---|
135 | result = result.shiftLeft((padByteLen - 2) * 8);
|
---|
136 | result = result.or(rndInt);
|
---|
137 | result = result.or(input);
|
---|
138 |
|
---|
139 | return result;
|
---|
140 | }
|
---|
141 |
|
---|
142 |
|
---|
143 | /* !!! DEBUG !!!
|
---|
144 | public static void main(String[] argv) {
|
---|
145 | KeyPair kp;
|
---|
146 | RSACipher cipher;
|
---|
147 | BigInteger p;
|
---|
148 | BigInteger q;
|
---|
149 | BigInteger t;
|
---|
150 | BigInteger p_1;
|
---|
151 | BigInteger q_1;
|
---|
152 | BigInteger phi;
|
---|
153 | BigInteger G;
|
---|
154 | BigInteger F;
|
---|
155 | BigInteger e;
|
---|
156 | BigInteger d;
|
---|
157 | BigInteger u;
|
---|
158 | BigInteger n;
|
---|
159 | BigInteger one = new BigInteger("1");
|
---|
160 |
|
---|
161 | System.out.println("Generating primes...");
|
---|
162 |
|
---|
163 | // p = new BigInteger(128, 64, new SecureRandom());
|
---|
164 | p = new BigInteger("3336670033");
|
---|
165 | // q = new BigInteger(128, 64, new SecureRandom());
|
---|
166 | q = new BigInteger("9876543211");
|
---|
167 |
|
---|
168 | if(p.compareTo(q) == 0) {
|
---|
169 | System.out.println("Same prime, impossible!!!");
|
---|
170 | System.exit(0);
|
---|
171 | } else if(q.compareTo(p) < 0) {
|
---|
172 | t = q;
|
---|
173 | q = p;
|
---|
174 | p = t;
|
---|
175 | }
|
---|
176 |
|
---|
177 | t = p.gcd(q);
|
---|
178 | if(t.compareTo(one) != 0) {
|
---|
179 | System.out.println("Same prime, impossible!!!");
|
---|
180 | System.exit(0);
|
---|
181 | }
|
---|
182 |
|
---|
183 | p_1 = p.subtract(one);
|
---|
184 | q_1 = q.subtract(one);
|
---|
185 | phi = p_1.multiply(q_1);
|
---|
186 | G = p_1.gcd(q_1);
|
---|
187 | F = phi.divide(G);
|
---|
188 |
|
---|
189 | e = one.shiftLeft(5);
|
---|
190 | e = e.subtract(one);
|
---|
191 | do {
|
---|
192 | e = e.add(one.add(one));
|
---|
193 | t = e.gcd(phi);
|
---|
194 | } while(t.compareTo(one) != 0);
|
---|
195 |
|
---|
196 | // d = e.modInverse(F);
|
---|
197 | d = e.modInverse(phi);
|
---|
198 | n = p.multiply(q);
|
---|
199 | u = p.modInverse(q);
|
---|
200 |
|
---|
201 | kp = new KeyPair(new RSAPublicKey(e, n),
|
---|
202 | new RSAPrivateKey(e, n, d, u, p, q));
|
---|
203 | cipher = new RSACipher(kp);
|
---|
204 |
|
---|
205 | System.out.println("..p = " + p.toString());
|
---|
206 | System.out.println("..q = " + q.toString());
|
---|
207 | System.out.println("..phi = " + phi.toString());
|
---|
208 | System.out.println("..e = " + e.toString());
|
---|
209 | System.out.println("..n = " + n.toString());
|
---|
210 | System.out.println("..d = " + d.toString());
|
---|
211 | System.out.println("..u = " + u.toString());
|
---|
212 |
|
---|
213 |
|
---|
214 | // one = new BigInteger(256, new SecureRandom());
|
---|
215 | one = new BigInteger("1901211401001920");
|
---|
216 |
|
---|
217 | System.out.println("..val = " + one.toString());
|
---|
218 | one = cipher.doPublic(one);
|
---|
219 | System.out.println("..val = " + one.toString());
|
---|
220 | one = cipher.doPrivate(one);
|
---|
221 | System.out.println("..val = " + one.toString());
|
---|
222 |
|
---|
223 | }
|
---|
224 | */
|
---|
225 |
|
---|
226 | }
|
---|