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