1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44:
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57:
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64:
65: public class RSACipherImpl
66: extends CipherSpi
67: {
68: private static final Logger logger = SystemLogger.SYSTEM;
69: private static final byte[] EMPTY = new byte[0];
70: private int opmode = -1;
71: private RSAPrivateKey decipherKey = null;
72: private RSAPublicKey blindingKey = null;
73: private RSAPublicKey encipherKey = null;
74: private SecureRandom random = null;
75: private byte[] dataBuffer = null;
76: private int pos = 0;
77:
78: protected void engineSetMode(String mode) throws NoSuchAlgorithmException
79: {
80: throw new NoSuchAlgorithmException("only one mode available");
81: }
82:
83: protected void engineSetPadding(String pad) throws NoSuchPaddingException
84: {
85: throw new NoSuchPaddingException("only one padding available");
86: }
87:
88: protected int engineGetBlockSize()
89: {
90: return 1;
91: }
92:
93: protected int engineGetOutputSize(int inputLen)
94: {
95: int outputLen = 0;
96: if (decipherKey != null)
97: outputLen = (decipherKey.getModulus().bitLength() + 7) / 8;
98: else if (encipherKey != null)
99: outputLen = (encipherKey.getModulus().bitLength() + 7) / 8;
100: else
101: throw new IllegalStateException("not initialized");
102: if (inputLen > outputLen)
103: throw new IllegalArgumentException("not configured to encode " + inputLen
104: + "bytes; at most " + outputLen);
105: return outputLen;
106: }
107:
108: protected int engineGetKeySize(final Key key) throws InvalidKeyException
109: {
110: if (! (key instanceof RSAKey))
111: throw new InvalidKeyException("not an RSA key");
112: return ((RSAKey) key).getModulus().bitLength();
113: }
114:
115: protected byte[] engineGetIV()
116: {
117: return null;
118: }
119:
120: protected AlgorithmParameters engineGetParameters()
121: {
122: return null;
123: }
124:
125: protected void engineInit(int opmode, Key key, SecureRandom random)
126: throws InvalidKeyException
127: {
128: int outputLen = 0;
129: if (opmode == Cipher.ENCRYPT_MODE)
130: {
131: if (! (key instanceof RSAPublicKey))
132: throw new InvalidKeyException("expecting a RSAPublicKey");
133: encipherKey = (RSAPublicKey) key;
134: decipherKey = null;
135: blindingKey = null;
136: outputLen = (encipherKey.getModulus().bitLength() + 7) / 8;
137: }
138: else if (opmode == Cipher.DECRYPT_MODE)
139: {
140: if (key instanceof RSAPrivateKey)
141: {
142: decipherKey = (RSAPrivateKey) key;
143: encipherKey = null;
144: blindingKey = null;
145: outputLen = (decipherKey.getModulus().bitLength() + 7) / 8;
146: }
147: else if (key instanceof RSAPublicKey)
148: {
149: if (decipherKey == null)
150: throw new IllegalStateException("must configure decryption key first");
151: if (! decipherKey.getModulus().equals(((RSAPublicKey) key).getModulus()))
152: throw new InvalidKeyException("blinding key is not compatible");
153: blindingKey = (RSAPublicKey) key;
154: return;
155: }
156: else
157: throw new InvalidKeyException(
158: "expecting either an RSAPrivateKey or an RSAPublicKey (for blinding)");
159: }
160: else
161: throw new IllegalArgumentException("only encryption and decryption supported");
162: this.random = random;
163: this.opmode = opmode;
164: pos = 0;
165: dataBuffer = new byte[outputLen];
166: }
167:
168: protected void engineInit(int opmode, Key key, AlgorithmParameterSpec spec,
169: SecureRandom random) throws InvalidKeyException
170: {
171: engineInit(opmode, key, random);
172: }
173:
174: protected void engineInit(int opmode, Key key, AlgorithmParameters params,
175: SecureRandom random) throws InvalidKeyException
176: {
177: engineInit(opmode, key, random);
178: }
179:
180: protected byte[] engineUpdate(byte[] in, int offset, int length)
181: {
182: if (opmode != Cipher.ENCRYPT_MODE && opmode != Cipher.DECRYPT_MODE)
183: throw new IllegalStateException("not initialized");
184: System.arraycopy(in, offset, dataBuffer, pos, length);
185: pos += length;
186: return EMPTY;
187: }
188:
189: protected int engineUpdate(byte[] in, int offset, int length, byte[] out,
190: int outOffset)
191: {
192: engineUpdate(in, offset, length);
193: return 0;
194: }
195:
196: protected byte[] engineDoFinal(byte[] in, int offset, int length)
197: throws IllegalBlockSizeException, BadPaddingException
198: {
199: engineUpdate(in, offset, length);
200: if (opmode == Cipher.DECRYPT_MODE)
201: {
202: if (pos < dataBuffer.length)
203: throw new IllegalBlockSizeException("expecting exactly "
204: + dataBuffer.length + " bytes");
205: BigInteger enc = new BigInteger(1, dataBuffer);
206: byte[] dec = rsaDecrypt(enc);
207: logger.log(Component.CRYPTO, "RSA: decryption produced\n{0}",
208: new ByteArray(dec));
209: if (dec[0] != 0x02)
210: throw new BadPaddingException("expected padding type 2");
211: int i;
212: for (i = 1; i < dec.length && dec[i] != 0x00; i++)
213: ;
214: int len = dec.length - i - 1;
215: byte[] result = new byte[len];
216: System.arraycopy(dec, i + 1, result, 0, len);
217: pos = 0;
218: return result;
219: }
220: else
221: {
222: offset = dataBuffer.length - pos;
223: if (offset < 3)
224: throw new IllegalBlockSizeException("input is too large to encrypt");
225: byte[] dec = new byte[dataBuffer.length];
226: dec[0] = 0x02;
227: if (random == null)
228: random = new SecureRandom();
229: byte[] pad = new byte[offset - 2];
230: random.nextBytes(pad);
231: for (int i = 0; i < pad.length; i++)
232: if (pad[i] == 0)
233: pad[i] = 1;
234: System.arraycopy(pad, 0, dec, 1, pad.length);
235: dec[dec.length - pos] = 0x00;
236: System.arraycopy(dataBuffer, 0, dec, offset, pos);
237: logger.log(Component.CRYPTO, "RSA: produced padded plaintext\n{0}",
238: new ByteArray(dec));
239: BigInteger x = new BigInteger(1, dec);
240: BigInteger y = x.modPow(encipherKey.getPublicExponent(),
241: encipherKey.getModulus());
242: byte[] enc = y.toByteArray();
243: if (enc[0] == 0x00)
244: {
245: byte[] tmp = new byte[enc.length - 1];
246: System.arraycopy(enc, 1, tmp, 0, tmp.length);
247: enc = tmp;
248: }
249: pos = 0;
250: return enc;
251: }
252: }
253:
254: protected int engineDoFinal(byte[] out, int offset)
255: throws ShortBufferException, IllegalBlockSizeException,
256: BadPaddingException
257: {
258: byte[] result = engineDoFinal(EMPTY, 0, 0);
259: if (out.length - offset < result.length)
260: throw new ShortBufferException("need " + result.length + ", have "
261: + (out.length - offset));
262: System.arraycopy(result, 0, out, offset, result.length);
263: return result.length;
264: }
265:
266: protected int engineDoFinal(final byte[] input, final int offset,
267: final int length, final byte[] output,
268: final int outputOffset)
269: throws ShortBufferException, IllegalBlockSizeException,
270: BadPaddingException
271: {
272: byte[] result = engineDoFinal(input, offset, length);
273: if (output.length - outputOffset < result.length)
274: throw new ShortBufferException("need " + result.length + ", have "
275: + (output.length - outputOffset));
276: System.arraycopy(result, 0, output, outputOffset, result.length);
277: return result.length;
278: }
279:
280:
283: private byte[] rsaDecrypt(BigInteger enc)
284: {
285: if (random == null)
286: random = new SecureRandom();
287: BigInteger n = decipherKey.getModulus();
288: BigInteger r = null;
289: BigInteger pubExp = null;
290: if (blindingKey != null)
291: pubExp = blindingKey.getPublicExponent();
292: if (pubExp != null && (decipherKey instanceof RSAPrivateCrtKey))
293: pubExp = ((RSAPrivateCrtKey) decipherKey).getPublicExponent();
294: if (pubExp != null)
295: {
296: r = new BigInteger(n.bitLength() - 1, random);
297: enc = r.modPow(pubExp, n).multiply(enc).mod(n);
298: }
299: BigInteger dec = enc.modPow(decipherKey.getPrivateExponent(), n);
300: if (pubExp != null)
301: dec = dec.multiply(r.modInverse(n)).mod(n);
302: return dec.toByteArray();
303: }
304: }