View | Details | Return to bug 26067 | Differences between
and this patch

Collapse All | Expand All

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

Return to bug 26067