OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [javax/] [crypto/] [Cipher.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* Cipher.java -- Interface to a cryptographic cipher.
2
   Copyright (C) 2004  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath 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, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.crypto;
40
 
41
import gnu.java.security.Engine;
42
 
43
import java.security.AlgorithmParameters;
44
import java.security.InvalidAlgorithmParameterException;
45
import java.security.InvalidKeyException;
46
import java.security.Key;
47
import java.security.NoSuchAlgorithmException;
48
import java.security.NoSuchProviderException;
49
import java.security.Provider;
50
import java.security.SecureRandom;
51
import java.security.Security;
52
import java.security.cert.Certificate;
53
import java.security.cert.X509Certificate;
54
import java.security.spec.AlgorithmParameterSpec;
55
import java.util.StringTokenizer;
56
 
57
/**
58
 * <p>This class implements a cryptographic cipher for transforming
59
 * data.</p>
60
 *
61
 * <p>Ciphers cannot be instantiated directly; rather one of the
62
 * <code>getInstance</code> must be used to instantiate a given
63
 * <i>transformation</i>, optionally with a specific provider.</p>
64
 *
65
 * <p>A transformation is of the form:</p>
66
 *
67
 * <ul>
68
 * <li><i>algorithm</i>/<i>mode</i>/<i>padding</i>, or</li>
69
 * <li><i>algorithm</i>
70
 * </ul>
71
 *
72
 * <p>where <i>algorithm</i> is the base name of a cryptographic cipher
73
 * (such as "AES"), <i>mode</i> is the abbreviated name of a block
74
 * cipher mode (such as "CBC" for cipher block chaining mode), and
75
 * <i>padding</i> is the name of a padding scheme (such as
76
 * "PKCS5Padding"). If only the algorithm name is supplied, then the
77
 * provider-specific default mode and padding will be used.</p>
78
 *
79
 * <p>An example transformation is:</p>
80
 *
81
 * <blockquote><code>Cipher c =
82
 * Cipher.getInstance("AES/CBC/PKCS5Padding");</code></blockquote>
83
 *
84
 * <p>Finally, when requesting a block cipher in stream cipher mode
85
 * (such as <acronym title="Advanced Encryption Standard">AES</acronym>
86
 * in OFB or CFB mode) the number of bits to be processed
87
 * at a time may be specified by appending it to the name of the mode;
88
 * e.g. <code>"AES/OFB8/NoPadding"</code>. If no such number is
89
 * specified a provider-specific default value is used.</p>
90
 *
91
 * @author Casey Marshall (csm@gnu.org)
92
 * @see java.security.KeyGenerator
93
 * @see javax.crypto.SecretKey
94
 */
95
public class Cipher
96
{
97
 
98
  // Constants and variables.
99
  // ------------------------------------------------------------------------
100
 
101
  private static final String SERVICE = "Cipher";
102
 
103
  /**
104
   * The decryption operation mode.
105
   */
106
  public static final int DECRYPT_MODE = 2;
107
 
108
  /**
109
   * The encryption operation mode.
110
   */
111
  public static final int ENCRYPT_MODE = 1;
112
 
113
  /**
114
   * Constant for when the key to be unwrapped is a private key.
115
   */
116
  public static final int PRIVATE_KEY = 2;
117
 
118
  /**
119
   * Constant for when the key to be unwrapped is a public key.
120
   */
121
  public static final int PUBLIC_KEY = 1;
122
 
123
  /**
124
   * Constant for when the key to be unwrapped is a secret key.
125
   */
126
  public static final int SECRET_KEY = 3;
127
 
128
  /**
129
   * The key unwrapping operation mode.
130
   */
131
  public static final int UNWRAP_MODE = 4;
132
 
133
  /**
134
   * The key wrapping operation mode.
135
   */
136
  public static final int WRAP_MODE = 3;
137
 
138
  /**
139
   * The uninitialized state. This state signals that any of the
140
   * <code>init</code> methods have not been called, and therefore no
141
   * transformations can be done.
142
   */
143
  private static final int INITIAL_STATE = 0;
144
 
145
  /** The underlying cipher service provider interface. */
146
  private CipherSpi cipherSpi;
147
 
148
  /** The provider from which this instance came. */
149
  private Provider provider;
150
 
151
  /** The transformation requested. */
152
  private String transformation;
153
 
154
  /** Our current state (encrypting, wrapping, etc.) */
155
  private int state;
156
 
157
 
158
  // Class methods.
159
  // ------------------------------------------------------------------------
160
 
161
  /**
162
   * <p>Creates a new cipher instance for the given transformation.</p>
163
   *
164
   * <p>The installed providers are tried in order for an
165
   * implementation, and the first appropriate instance is returned. If
166
   * no installed provider can provide the implementation, an
167
   * appropriate exception is thrown.</p>
168
   *
169
   * @param transformation The transformation to create.
170
   * @return An appropriate cipher for this transformation.
171
   * @throws java.security.NoSuchAlgorithmException If no installed
172
   *         provider can supply the appropriate cipher or mode.
173
   * @throws javax.crypto.NoSuchPaddingException If no installed
174
   *         provider can supply the appropriate padding.
175
   */
176
  public static final Cipher getInstance(String transformation)
177
    throws NoSuchAlgorithmException, NoSuchPaddingException
178
  {
179
    Provider[] providers = Security.getProviders();
180
    NoSuchPaddingException ex = null;
181
    String msg = "";
182
    for (int i = 0; i < providers.length; i++)
183
      {
184
        try
185
          {
186
            return getInstance(transformation, providers[i]);
187
          }
188
        catch (NoSuchAlgorithmException nsae)
189
          {
190
            msg = nsae.getMessage();
191
            ex = null;
192
          }
193
        catch (NoSuchPaddingException nspe)
194
          {
195
            ex = nspe;
196
          }
197
      }
198
    if (ex != null)
199
      {
200
        throw ex;
201
      }
202
    throw new NoSuchAlgorithmException(msg);
203
  }
204
 
205
  /**
206
   * <p>Creates a new cipher instance for the given transformation and
207
   * the named provider.</p>
208
   *
209
   * @param transformation The transformation to create.
210
   * @param provider       The name of the provider to use.
211
   * @return An appropriate cipher for this transformation.
212
   * @throws java.security.NoSuchAlgorithmException If the provider cannot
213
   *         supply the appropriate cipher or mode.
214
   * @throws java.security.NoSuchProviderException If the named provider
215
   *         is not installed.
216
   * @throws javax.crypto.NoSuchPaddingException If the provider cannot
217
   *         supply the appropriate padding.
218
   */
219
  public static final Cipher getInstance(String transformation, String provider)
220
    throws NoSuchAlgorithmException, NoSuchProviderException,
221
           NoSuchPaddingException
222
  {
223
    Provider p = Security.getProvider(provider);
224
    if (p == null)
225
      {
226
        throw new NoSuchProviderException(provider);
227
      }
228
    return getInstance(transformation, p);
229
  }
230
 
231
  /**
232
   * Creates a new cipher instance for the given transform and the given
233
   * provider.
234
   *
235
   * @param transformation The transformation to create.
236
   * @param provider       The provider to use.
237
   * @return An appropriate cipher for this transformation.
238
   * @throws java.security.NoSuchAlgorithmException If the given
239
   *         provider cannot supply the appropriate cipher or mode.
240
   * @throws javax.crypto.NoSuchPaddingException If the given
241
   *         provider cannot supply the appropriate padding scheme.
242
   */
243
  public static final Cipher getInstance(String transformation, Provider provider)
244
    throws NoSuchAlgorithmException, NoSuchPaddingException
245
  {
246
    CipherSpi result = null;
247
    String key = null;
248
    String alg = null, mode = null, pad = null;
249
    String msg = "";
250
    if (transformation.indexOf('/') < 0)
251
      {
252
        try
253
          {
254
            result = (CipherSpi) Engine.getInstance(SERVICE, transformation,
255
                                                    provider);
256
            return new Cipher(result, provider, transformation);
257
          }
258
        catch (Exception e)
259
          {
260
            msg = e.getMessage();
261
          }
262
      }
263
    else
264
      {
265
        StringTokenizer tok = new StringTokenizer(transformation, "/");
266
        if (tok.countTokens() != 3)
267
          {
268
            throw new NoSuchAlgorithmException("badly formed transformation");
269
          }
270
        alg = tok.nextToken();
271
        mode = tok.nextToken();
272
        pad = tok.nextToken();
273
        try
274
          {
275
            result = (CipherSpi) Engine.getInstance(SERVICE, transformation,
276
                                                    provider);
277
            return new Cipher(result, provider, transformation);
278
          }
279
        catch (Exception e)
280
          {
281
            msg = e.getMessage();
282
          }
283
        try
284
          {
285
            result = (CipherSpi) Engine.getInstance(SERVICE, alg + '/' + mode,
286
                                                    provider);
287
            result.engineSetPadding(pad);
288
            return new Cipher(result, provider, transformation);
289
          }
290
        catch (Exception e)
291
          {
292
            if (e instanceof NoSuchPaddingException)
293
              {
294
                throw (NoSuchPaddingException) e;
295
              }
296
            msg = e.getMessage();
297
          }
298
        try
299
          {
300
            result = (CipherSpi) Engine.getInstance(SERVICE, alg + "//" + pad,
301
                                                    provider);
302
            result.engineSetMode(mode);
303
            return new Cipher(result, provider, transformation);
304
          }
305
        catch (Exception e)
306
          {
307
            msg = e.getMessage();
308
          }
309
        try
310
          {
311
            result = (CipherSpi) Engine.getInstance(SERVICE, alg, provider);
312
            result.engineSetMode(mode);
313
            result.engineSetPadding(pad);
314
            return new Cipher(result, provider, transformation);
315
          }
316
        catch (Exception e)
317
          {
318
            if (e instanceof NoSuchPaddingException)
319
              {
320
                throw (NoSuchPaddingException) e;
321
              }
322
            msg = e.getMessage();
323
          }
324
      }
325
    throw new NoSuchAlgorithmException(transformation + ": " + msg);
326
  }
327
 
328
// Constructor.
329
  // ------------------------------------------------------------------------
330
 
331
  /**
332
   * Create a cipher.
333
   *
334
   * @param cipherSpi The underlying implementation of the cipher.
335
   * @param provider  The provider of this cipher implementation.
336
   * @param transformation The transformation this cipher performs.
337
   */
338
  protected
339
  Cipher(CipherSpi cipherSpi, Provider provider, String transformation)
340
  {
341
    this.cipherSpi = cipherSpi;
342
    this.provider = provider;
343
    this.transformation = transformation;
344
    state = INITIAL_STATE;
345
  }
346
 
347
// Public instance methods.
348
  // ------------------------------------------------------------------------
349
 
350
  /**
351
   * Get the name that this cipher instance was created with; this is
352
   * equivalent to the "transformation" argument given to any of the
353
   * {@link #getInstance()} methods.
354
   *
355
   * @return The cipher name.
356
   */
357
  public final String getAlgorithm()
358
  {
359
    return transformation;
360
  }
361
 
362
  /**
363
   * Return the size of blocks, in bytes, that this cipher processes.
364
   *
365
   * @return The block size.
366
   */
367
  public final int getBlockSize()
368
  {
369
    if (cipherSpi != null)
370
      {
371
        return cipherSpi.engineGetBlockSize();
372
      }
373
    return 1;
374
  }
375
 
376
  /**
377
   * Return the currently-operating {@link ExemptionMechanism}.
378
   *
379
   * @return null, currently.
380
   */
381
  public final ExemptionMechanism getExemptionMechanism()
382
  {
383
    return null;
384
  }
385
 
386
  /**
387
   * Return the <i>initialization vector</i> that this instance was
388
   * initialized with.
389
   *
390
   * @return The IV.
391
   */
392
  public final byte[] getIV()
393
  {
394
    if (cipherSpi != null)
395
      {
396
        return cipherSpi.engineGetIV();
397
      }
398
    return null;
399
  }
400
 
401
  /**
402
   * Return the {@link java.security.AlgorithmParameters} that this
403
   * instance was initialized with.
404
   *
405
   * @return The parameters.
406
   */
407
  public final AlgorithmParameters getParameters()
408
  {
409
    if (cipherSpi != null) {
410
      return cipherSpi.engineGetParameters();
411
    }
412
    return null;
413
  }
414
 
415
  /**
416
   * Return this cipher's provider.
417
   *
418
   * @return The provider.
419
   */
420
  public final Provider getProvider()
421
  {
422
    return provider;
423
  }
424
 
425
  /**
426
   * Finishes a multi-part transformation, and returns the final
427
   * transformed bytes.
428
   *
429
   * @return The final transformed bytes.
430
   * @throws java.lang.IllegalStateException If this instance has not
431
   *         been initialized, or if a <tt>doFinal</tt> call has already
432
   *         been made.
433
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
434
   *         no padding and the input is not a multiple of this cipher's
435
   *         block size.
436
   * @throws javax.crypto.BadPaddingException If this instance is
437
   *         decrypting and the padding bytes do not match this
438
   *         instance's padding scheme.
439
   */
440
  public final byte[] doFinal()
441
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
442
  {
443
    return doFinal(new byte[0], 0, 0);
444
  }
445
 
446
  /**
447
   * Finishes a multi-part transformation or does an entire
448
   * transformation on the input, and returns the transformed bytes.
449
   *
450
   * @param input The final input bytes.
451
   * @return The final transformed bytes.
452
   * @throws java.lang.IllegalStateException If this instance has not
453
   *         been initialized, or if a <tt>doFinal</tt> call has already
454
   *         been made.
455
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
456
   *         no padding and the input is not a multiple of this cipher's
457
   *         block size.
458
   * @throws javax.crypto.BadPaddingException If this instance is
459
   *         decrypting and the padding bytes do not match this
460
   *         instance's padding scheme.
461
   */
462
  public final byte[] doFinal(byte[] input)
463
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
464
  {
465
    return doFinal(input, 0, input.length);
466
  }
467
 
468
  /**
469
   * Finishes a multi-part transformation or does an entire
470
   * transformation on the input, and returns the transformed bytes.
471
   *
472
   * @param input       The final input bytes.
473
   * @param inputOffset The index in the input bytes to start.
474
   * @param inputLength The number of bytes to read from the input.
475
   * @return The final transformed bytes.
476
   * @throws java.lang.IllegalStateException If this instance has not
477
   *         been initialized, or if a <tt>doFinal</tt> call has already
478
   *         been made.
479
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
480
   *         no padding and the input is not a multiple of this cipher's
481
   *         block size.
482
   * @throws javax.crypto.BadPaddingException If this instance is
483
   *         decrypting and the padding bytes do not match this
484
   *         instance's padding scheme.
485
   */
486
  public final byte[] doFinal(byte[] input, int inputOffset, int inputLength)
487
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
488
  {
489
    if (cipherSpi == null)
490
      {
491
        byte[] b = new byte[inputLength];
492
        System.arraycopy(input, inputOffset, b, 0, inputLength);
493
        return b;
494
      }
495
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
496
      {
497
        throw new IllegalStateException("neither encrypting nor decrypting");
498
      }
499
    state = INITIAL_STATE;
500
    return cipherSpi.engineDoFinal(input, inputOffset, inputLength);
501
  }
502
 
503
  /**
504
   * Finishes a multi-part transformation and stores the transformed
505
   * bytes into the given array.
506
   *
507
   * @param output       The destination for the transformed bytes.
508
   * @param outputOffset The offset in <tt>output</tt> to start storing
509
   *        bytes.
510
   * @return The number of bytes placed into the output array.
511
   * @throws java.lang.IllegalStateException If this instance has not
512
   *         been initialized, or if a <tt>doFinal</tt> call has already
513
   *         been made.
514
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
515
   *         no padding and the input is not a multiple of this cipher's
516
   *         block size.
517
   * @throws javax.crypto.BadPaddingException If this instance is
518
   *         decrypting and the padding bytes do not match this
519
   *         instance's padding scheme.
520
   * @throws javax.crypto.ShortBufferException If the output array is
521
   *         not large enough to hold the transformed bytes.
522
   */
523
  public final int doFinal(byte[] output, int outputOffset)
524
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException,
525
           ShortBufferException
526
  {
527
    if (cipherSpi == null)
528
      {
529
        return 0;
530
      }
531
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
532
      {
533
        throw new IllegalStateException("neither encrypting nor decrypting");
534
      }
535
    state = INITIAL_STATE;
536
    return cipherSpi.engineDoFinal(new byte[0], 0, 0, output, outputOffset);
537
  }
538
 
539
  /**
540
   * Finishes a multi-part transformation or transforms a portion of a
541
   * byte array, and stores the result in the given byte array.
542
   *
543
   * @param input        The input bytes.
544
   * @param inputOffset  The index in <tt>input</tt> to start.
545
   * @param inputLength  The number of bytes to transform.
546
   * @param output       The output buffer.
547
   * @param outputOffset The index in <tt>output</tt> to start.
548
   * @return The number of bytes placed into the output array.
549
   * @throws java.lang.IllegalStateException If this instance has not
550
   *         been initialized, or if a <tt>doFinal</tt> call has already
551
   *         been made.
552
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
553
   *         no padding and the input is not a multiple of this cipher's
554
   *         block size.
555
   * @throws javax.crypto.BadPaddingException If this instance is
556
   *         decrypting and the padding bytes do not match this
557
   *         instance's padding scheme.
558
   * @throws javax.crypto.ShortBufferException If the output array is
559
   *         not large enough to hold the transformed bytes.
560
   */
561
  public final int doFinal(byte[] input, int inputOffset, int inputLength,
562
                           byte[] output, int outputOffset)
563
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException,
564
           ShortBufferException
565
  {
566
    if (cipherSpi == null)
567
      {
568
        if (inputLength > output.length - outputOffset)
569
          {
570
            throw new ShortBufferException();
571
          }
572
        System.arraycopy(input, inputOffset, output, outputOffset, inputLength);
573
        return inputLength;
574
      }
575
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
576
      {
577
        throw new IllegalStateException("neither encrypting nor decrypting");
578
      }
579
    state = INITIAL_STATE;
580
    return cipherSpi.engineDoFinal(input, inputOffset, inputLength,
581
                                   output, outputOffset);
582
  }
583
 
584
  public final int doFinal(byte[] input, int inputOffset, int inputLength,
585
                           byte[] output)
586
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException,
587
           ShortBufferException
588
  {
589
    return doFinal(input, inputOffset, inputLength, output, 0);
590
  }
591
 
592
  /**
593
   * Returns the size an output buffer needs to be if this cipher is
594
   * updated with a number of bytes.
595
   *
596
   * @param inputLength The input length.
597
   * @return The output length given this input length.
598
   * @throws java.lang.IllegalStateException If this instance has not
599
   *         been initialized, or if a <tt>doFinal</tt> call has already
600
   *         been made.
601
   */
602
  public final int getOutputSize(int inputLength) throws IllegalStateException
603
  {
604
    if (cipherSpi == null)
605
      {
606
        return inputLength;
607
      }
608
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
609
      {
610
        throw new IllegalStateException("neither encrypting nor decrypting");
611
      }
612
    return cipherSpi.engineGetOutputSize(inputLength);
613
  }
614
 
615
  /**
616
   * <p>Initialize this cipher with the public key from the given
617
   * certificate.</p>
618
   *
619
   * <p>The cipher will be initialized for encryption, decryption, key
620
   * wrapping, or key unwrapping, depending upon whether the
621
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
622
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
623
   * respectively.</p>
624
   *
625
   * <p>As per the Java 1.4 specification, if <code>cert</code> is an
626
   * instance of an {@link java.security.cert.X509Certificate} and its
627
   * <i>key usage</i> extension field is incompatible with
628
   * <code>opmode</code> then an {@link
629
   * java.security.InvalidKeyException} is thrown.</p>
630
   *
631
   * <p>If this cipher requires any random bytes (for example for an
632
   * initilization vector) than the {@link java.security.SecureRandom}
633
   * with the highest priority is used as the source of these bytes.</p>
634
   *
635
   * <p>A call to any of the <code>init</code> methods overrides the
636
   * state of the instance, and is equivalent to creating a new instance
637
   * and calling its <code>init</code> method.</p>
638
   *
639
   * @param opmode      The operation mode to use.
640
   * @param certificate The certificate.
641
   * @throws java.security.InvalidKeyException If the underlying cipher
642
   *         instance rejects the certificate's public key, or if the
643
   *         public key cannot be used as described above.
644
   */
645
  public final void init(int opmode, Certificate certificate)
646
    throws InvalidKeyException
647
  {
648
    init(opmode, certificate, new SecureRandom());
649
  }
650
 
651
  /**
652
   * <p>Initialize this cipher with the supplied key.</p>
653
   *
654
   * <p>The cipher will be initialized for encryption, decryption, key
655
   * wrapping, or key unwrapping, depending upon whether the
656
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
657
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
658
   * respectively.</p>
659
   *
660
   * <p>If this cipher requires any random bytes (for example for an
661
   * initilization vector) than the {@link java.security.SecureRandom}
662
   * with the highest priority is used as the source of these bytes.</p>
663
   *
664
   * <p>A call to any of the <code>init</code> methods overrides the
665
   * state of the instance, and is equivalent to creating a new instance
666
   * and calling its <code>init</code> method.</p>
667
   *
668
   * @param opmode The operation mode to use.
669
   * @param key    The key.
670
   * @throws java.security.InvalidKeyException If the underlying cipher
671
   *         instance rejects the given key.
672
   */
673
  public final void init(int opmode, Key key) throws InvalidKeyException
674
  {
675
    state = opmode;
676
    if (cipherSpi != null)
677
      {
678
        cipherSpi.engineInit(opmode, key, new SecureRandom());
679
      }
680
  }
681
 
682
  /**
683
   * <p>Initialize this cipher with the public key from the given
684
   * certificate and the specified source of randomness.</p>
685
   *
686
   * <p>The cipher will be initialized for encryption, decryption, key
687
   * wrapping, or key unwrapping, depending upon whether the
688
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
689
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
690
   * respectively.</p>
691
   *
692
   * <p>As per the Java 1.4 specification, if <code>cert</code> is an
693
   * instance of an {@link java.security.cert.X509Certificate} and its
694
   * <i>key usage</i> extension field is incompatible with
695
   * <code>opmode</code> then an {@link
696
   * java.security.InvalidKeyException} is thrown.</p>
697
   *
698
   * <p>If this cipher requires any random bytes (for example for an
699
   * initilization vector) than the {@link java.security.SecureRandom}
700
   * with the highest priority is used as the source of these bytes.</p>
701
   *
702
   * <p>A call to any of the <code>init</code> methods overrides the
703
   * state of the instance, and is equivalent to creating a new instance
704
   * and calling its <code>init</code> method.</p>
705
   *
706
   * @param opmode      The operation mode to use.
707
   * @param certificate The certificate.
708
   * @param random      The source of randomness.
709
   * @throws java.security.InvalidKeyException If the underlying cipher
710
   *         instance rejects the certificate's public key, or if the
711
   *         public key cannot be used as described above.
712
   */
713
  public final void
714
  init(int opmode, Certificate certificate, SecureRandom random)
715
  throws InvalidKeyException
716
  {
717
    if (certificate instanceof X509Certificate)
718
      {
719
        boolean[] keyInfo = ((X509Certificate) certificate).getKeyUsage();
720
        if (keyInfo != null)
721
          {
722
            switch (opmode)
723
              {
724
              case DECRYPT_MODE:
725
                if (!keyInfo[3])
726
                  {
727
                    throw new InvalidKeyException(
728
                      "the certificate's key cannot be used for transforming data");
729
                  }
730
                if (keyInfo[7])
731
                  {
732
                    throw new InvalidKeyException(
733
                      "the certificate's key can only be used for encryption");
734
                  }
735
                break;
736
 
737
              case ENCRYPT_MODE:
738
                if (!keyInfo[3])
739
                  {
740
                    throw new InvalidKeyException(
741
                      "the certificate's key cannot be used for transforming data");
742
                  }
743
                if (keyInfo[8])
744
                  {
745
                    throw new InvalidKeyException(
746
                      "the certificate's key can only be used for decryption");
747
                  }
748
                break;
749
 
750
              case UNWRAP_MODE:
751
                if (!keyInfo[2] || keyInfo[7])
752
                  {
753
                    throw new InvalidKeyException(
754
                      "the certificate's key cannot be used for key unwrapping");
755
                  }
756
                break;
757
 
758
              case WRAP_MODE:
759
                if (!keyInfo[2] || keyInfo[8])
760
                  {
761
                    throw new InvalidKeyException(
762
                      "the certificate's key cannot be used for key wrapping");
763
                  }
764
                break;
765
              }
766
          }
767
      }
768
    init(opmode, certificate.getPublicKey(), random);
769
  }
770
 
771
  /**
772
   * <p>Initialize this cipher with the supplied key and source of
773
   * randomness.</p>
774
   *
775
   * <p>The cipher will be initialized for encryption, decryption, key
776
   * wrapping, or key unwrapping, depending upon whether the
777
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
778
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
779
   * respectively.</p>
780
   *
781
   * <p>A call to any of the <code>init</code> methods overrides the
782
   * state of the instance, and is equivalent to creating a new instance
783
   * and calling its <code>init</code> method.</p>
784
   *
785
   * @param opmode The operation mode to use.
786
   * @param key    The key.
787
   * @param random The source of randomness to use.
788
   * @throws java.security.InvalidKeyException If the underlying cipher
789
   *         instance rejects the given key.
790
   */
791
  public final void init(int opmode, Key key, SecureRandom random)
792
    throws InvalidKeyException
793
  {
794
    state = opmode;
795
    if (cipherSpi != null)
796
      {
797
        cipherSpi.engineInit(opmode, key, random);
798
      }
799
  }
800
 
801
  /**
802
   * <p>Initialize this cipher with the supplied key and parameters.</p>
803
   *
804
   * <p>The cipher will be initialized for encryption, decryption, key
805
   * wrapping, or key unwrapping, depending upon whether the
806
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
807
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
808
   * respectively.</p>
809
   *
810
   * <p>If this cipher requires any random bytes (for example for an
811
   * initilization vector) then the {@link java.security.SecureRandom}
812
   * with the highest priority is used as the source of these bytes.</p>
813
   *
814
   * <p>A call to any of the <code>init</code> methods overrides the
815
   * state of the instance, and is equivalent to creating a new instance
816
   * and calling its <code>init</code> method.</p>
817
   *
818
   * @param opmode The operation mode to use.
819
   * @param key    The key.
820
   * @param params The algorithm parameters to initialize this instance
821
   *               with.
822
   * @throws java.security.InvalidKeyException If the underlying cipher
823
   *         instance rejects the given key.
824
   * @throws java.security.InvalidAlgorithmParameterException If the
825
   *         supplied parameters are inappropriate for this cipher.
826
   */
827
  public final void init(int opmode, Key key, AlgorithmParameters params)
828
    throws InvalidKeyException, InvalidAlgorithmParameterException
829
  {
830
    init(opmode, key, params, new SecureRandom());
831
  }
832
 
833
  /**
834
   * <p>Initialize this cipher with the supplied key and parameters.</p>
835
   *
836
   * <p>The cipher will be initialized for encryption, decryption, key
837
   * wrapping, or key unwrapping, depending upon whether the
838
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
839
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
840
   * respectively.</p>
841
   *
842
   * <p>If this cipher requires any random bytes (for example for an
843
   * initilization vector) then the {@link java.security.SecureRandom}
844
   * with the highest priority is used as the source of these bytes.</p>
845
   *
846
   * <p>A call to any of the <code>init</code> methods overrides the
847
   * state of the instance, and is equivalent to creating a new instance
848
   * and calling its <code>init</code> method.</p>
849
   *
850
   * @param opmode The operation mode to use.
851
   * @param key    The key.
852
   * @param params The algorithm parameters to initialize this instance
853
   *               with.
854
   * @throws java.security.InvalidKeyException If the underlying cipher
855
   *         instance rejects the given key.
856
   * @throws java.security.InvalidAlgorithmParameterException If the
857
   *         supplied parameters are inappropriate for this cipher.
858
   */
859
  public final void init(int opmode, Key key, AlgorithmParameterSpec params)
860
    throws InvalidKeyException, InvalidAlgorithmParameterException
861
  {
862
    init(opmode, key, params, new SecureRandom());
863
  }
864
 
865
  /**
866
   * <p>Initialize this cipher with the supplied key, parameters, and
867
   * source of randomness.</p>
868
   *
869
   * <p>The cipher will be initialized for encryption, decryption, key
870
   * wrapping, or key unwrapping, depending upon whether the
871
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
872
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
873
   * respectively.</p>
874
   *
875
   * <p>A call to any of the <code>init</code> methods overrides the
876
   * state of the instance, and is equivalent to creating a new instance
877
   * and calling its <code>init</code> method.</p>
878
   *
879
   * @param opmode The operation mode to use.
880
   * @param key    The key.
881
   * @param params The algorithm parameters to initialize this instance
882
   *               with.
883
   * @param random The source of randomness to use.
884
   * @throws java.security.InvalidKeyException If the underlying cipher
885
   *         instance rejects the given key.
886
   * @throws java.security.InvalidAlgorithmParameterException If the
887
   *         supplied parameters are inappropriate for this cipher.
888
   */
889
  public final void init(int opmode, Key key, AlgorithmParameters params,
890
                         SecureRandom random)
891
    throws InvalidKeyException, InvalidAlgorithmParameterException
892
  {
893
    state = opmode;
894
    if (cipherSpi != null)
895
      {
896
        cipherSpi.engineInit(opmode, key, params, random);
897
      }
898
  }
899
 
900
  /**
901
   * <p>Initialize this cipher with the supplied key, parameters, and
902
   * source of randomness.</p>
903
   *
904
   * <p>The cipher will be initialized for encryption, decryption, key
905
   * wrapping, or key unwrapping, depending upon whether the
906
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
907
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
908
   * respectively.</p>
909
   *
910
   * <p>A call to any of the <code>init</code> methods overrides the
911
   * state of the instance, and is equivalent to creating a new instance
912
   * and calling its <code>init</code> method.</p>
913
   *
914
   * @param opmode The operation mode to use.
915
   * @param key    The key.
916
   * @param params The algorithm parameters to initialize this instance
917
   *               with.
918
   * @param random The source of randomness to use.
919
   * @throws java.security.InvalidKeyException If the underlying cipher
920
   *         instance rejects the given key.
921
   * @throws java.security.InvalidAlgorithmParameterException If the
922
   *         supplied parameters are inappropriate for this cipher.
923
   */
924
  public final void init(int opmode, Key key, AlgorithmParameterSpec params,
925
                         SecureRandom random)
926
    throws InvalidKeyException, InvalidAlgorithmParameterException
927
  {
928
    state = opmode;
929
    if (cipherSpi != null)
930
      {
931
        cipherSpi.engineInit(opmode, key, params, random);
932
      }
933
  }
934
 
935
  /**
936
   * Unwrap a previously-wrapped key.
937
   *
938
   * @param wrappedKey          The wrapped key.
939
   * @param wrappedKeyAlgorithm The algorithm with which the key was
940
   *        wrapped.
941
   * @param wrappedKeyType      The type of key (public, private, or
942
   *        secret) that this wrapped key respresents.
943
   * @return The unwrapped key.
944
   * @throws java.lang.IllegalStateException If this instance has not be
945
   *         initialized for unwrapping.
946
   * @throws java.security.InvalidKeyException If <code>wrappedKey</code>
947
   *         is not a wrapped key, if the algorithm cannot unwrap this
948
   *         key, or if the unwrapped key's type differs from the
949
   *         specified type.
950
   * @throws java.security.NoSuchAlgorithmException If
951
   *         <code>wrappedKeyAlgorithm</code> is not a valid algorithm
952
   *         name.
953
   */
954
  public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
955
                          int wrappedKeyType)
956
    throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException
957
  {
958
    if (cipherSpi == null)
959
      {
960
        return null;
961
      }
962
    if (state != UNWRAP_MODE)
963
      {
964
        throw new IllegalStateException("instance is not for unwrapping");
965
      }
966
    return cipherSpi.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
967
                                  wrappedKeyType);
968
  }
969
 
970
  /**
971
   * Continue a multi-part transformation on an entire byte array,
972
   * returning the transformed bytes.
973
   *
974
   * @param input The input bytes.
975
   * @return The transformed bytes.
976
   * @throws java.lang.IllegalStateException If this cipher was not
977
   *         initialized for encryption or decryption.
978
   */
979
  public final byte[] update(byte[] input) throws IllegalStateException
980
  {
981
    return update(input, 0, input.length);
982
  }
983
 
984
  /**
985
   * Continue a multi-part transformation on part of a byte array,
986
   * returning the transformed bytes.
987
   *
988
   * @param input       The input bytes.
989
   * @param inputOffset The index in the input to start.
990
   * @param inputLength The number of bytes to transform.
991
   * @return The transformed bytes.
992
   * @throws java.lang.IllegalStateException If this cipher was not
993
   *         initialized for encryption or decryption.
994
   */
995
  public final byte[] update(byte[] input, int inputOffset, int inputLength)
996
    throws IllegalStateException
997
  {
998
    if (cipherSpi == null)
999
      {
1000
        byte[] b = new byte[inputLength];
1001
        System.arraycopy(input, inputOffset, b, 0, inputLength);
1002
        return b;
1003
      }
1004
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
1005
      {
1006
        throw new IllegalStateException(
1007
          "cipher is not for encrypting or decrypting");
1008
      }
1009
    return cipherSpi.engineUpdate(input, inputOffset, inputLength);
1010
  }
1011
 
1012
  /**
1013
   * Continue a multi-part transformation on part of a byte array,
1014
   * placing the transformed bytes into the given array.
1015
   *
1016
   * @param input       The input bytes.
1017
   * @param inputOffset The index in the input to start.
1018
   * @param inputLength The number of bytes to transform.
1019
   * @param output      The output byte array.
1020
   * @return The number of transformed bytes.
1021
   * @throws java.lang.IllegalStateException If this cipher was not
1022
   *         initialized for encryption or decryption.
1023
   * @throws javax.security.ShortBufferException If there is not enough
1024
   *         room in the output array to hold the transformed bytes.
1025
   */
1026
  public final int update(byte[] input, int inputOffset, int inputLength,
1027
                          byte[] output)
1028
    throws IllegalStateException, ShortBufferException
1029
  {
1030
    return update(input, inputOffset, inputLength, output, 0);
1031
  }
1032
 
1033
  /**
1034
   * Continue a multi-part transformation on part of a byte array,
1035
   * placing the transformed bytes into the given array.
1036
   *
1037
   * @param input        The input bytes.
1038
   * @param inputOffset  The index in the input to start.
1039
   * @param inputLength  The number of bytes to transform.
1040
   * @param output       The output byte array.
1041
   * @param outputOffset The index in the output array to start.
1042
   * @return The number of transformed bytes.
1043
   * @throws java.lang.IllegalStateException If this cipher was not
1044
   *         initialized for encryption or decryption.
1045
   * @throws javax.security.ShortBufferException If there is not enough
1046
   *         room in the output array to hold the transformed bytes.
1047
   */
1048
  public final int update(byte[] input, int inputOffset, int inputLength,
1049
                          byte[] output, int outputOffset)
1050
    throws IllegalStateException, ShortBufferException
1051
  {
1052
    if (cipherSpi == null)
1053
      {
1054
        if (inputLength > output.length - outputOffset)
1055
          {
1056
            throw new ShortBufferException();
1057
          }
1058
        System.arraycopy(input, inputOffset, output, outputOffset, inputLength);
1059
        return inputLength;
1060
      }
1061
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
1062
      {
1063
        throw new IllegalStateException(
1064
          "cipher is not for encrypting or decrypting");
1065
      }
1066
    return cipherSpi.engineUpdate(input, inputOffset, inputLength,
1067
                                  output, outputOffset);
1068
  }
1069
 
1070
  /**
1071
   * Wrap a key.
1072
   *
1073
   * @param key The key to wrap.
1074
   * @return The wrapped key.
1075
   * @throws java.lang.IllegalStateException If this instance was not
1076
   *         initialized for key wrapping.
1077
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
1078
   *         no padding and the key is not a multiple of the block size.
1079
   * @throws java.security.InvalidKeyException If this instance cannot
1080
   *         wrap this key.
1081
   */
1082
  public final byte[] wrap(Key key)
1083
    throws IllegalStateException, IllegalBlockSizeException, InvalidKeyException
1084
  {
1085
    if (cipherSpi == null)
1086
      {
1087
        return null;
1088
      }
1089
    if (state != WRAP_MODE)
1090
      {
1091
        throw new IllegalStateException("instance is not for key wrapping");
1092
      }
1093
    return cipherSpi.engineWrap(key);
1094
  }
1095
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.