Source for javax.crypto.spec.PBEKeySpec

   1: /* PBEKeySpec.java -- Wrapper for password-based keys.
   2:    Copyright (C) 2004, 2006  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.spec;
  40: 
  41: import java.security.spec.KeySpec;
  42: 
  43: /**
  44:  * A wrapper for a password-based key, used for password-based
  45:  * encryption (PBE).
  46:  *
  47:  * <p>Examples of password-based encryption algorithms include:
  48:  *
  49:  * <ul>
  50:  * <li><a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/">PKCS #5
  51:  * - Password-Based Cryptography Standard</a></li>
  52:  * <li><a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-12/">PKCS
  53:  * #12 - Personal Information Exchange Syntax Standard</a></li>
  54:  * </ul>
  55:  *
  56:  * @author Casey Marshall (csm@gnu.org)
  57:  * @since 1.4
  58:  * @see javax.crypto.SecretKeyFactory
  59:  * @see PBEParameterSpec
  60:  */
  61: public class PBEKeySpec implements KeySpec
  62: {
  63: 
  64:   // Fields.
  65:   // ------------------------------------------------------------------------
  66: 
  67:   /** The iteration count. */
  68:   private int iterationCount;
  69: 
  70:   /** The generated key length. */
  71:   private int keyLength;
  72: 
  73:   /** The password. */
  74:   private char[] password;
  75: 
  76:   /** The salt. */
  77:   private byte[] salt;
  78: 
  79:   /** The password state */
  80:   private boolean passwordValid = true;
  81:   
  82:   // Constructors.
  83:   // ------------------------------------------------------------------------
  84: 
  85:   /**
  86:    * Create a new PBE key spec with just a password.
  87:    * <p>
  88:    * A copy of the password argument is stored instead of the argument itself.
  89:    * 
  90:    * @param password The password char array.
  91:    */
  92:   public PBEKeySpec(char[] password)
  93:   {
  94:     setPassword(password);
  95:     
  96:     // load the default values for unspecified variables.
  97:     salt = null;
  98:     iterationCount = 0;
  99:     keyLength = 0;
 100:   }
 101: 
 102:   /**
 103:    * Create a PBE key spec with a password, salt, and iteration count.
 104:    * <p>
 105:    * A copy of the password and salt arguments are stored instead of the
 106:    * arguments themselves.
 107:    * 
 108:    * @param password The password char array.
 109:    * @param salt The salt bytes.
 110:    * @param iterationCount The iteration count.
 111:    * @throws NullPointerException If salt is null
 112:    * @throws IllegalArgumentException If salt is an empty array, or
 113:    *           iterationCount is negative
 114:    */
 115:   public PBEKeySpec(char[] password, byte[] salt, int iterationCount)
 116:   {
 117:     setPassword(password);
 118:     setSalt(salt);
 119:     setIterationCount(iterationCount);
 120: 
 121:     // load default values into unspecified variables.
 122:     keyLength = 0;
 123:   }
 124: 
 125:   /**
 126:    * Create a PBE key spec with a password, salt, iteration count, and key
 127:    * length.
 128:    * <p>
 129:    * A copy of the password and salt arguments are stored instead of the
 130:    * arguments themselves.
 131:    * 
 132:    * @param password The password char array.
 133:    * @param salt The salt bytes.
 134:    * @param iterationCount The iteration count.
 135:    * @param keyLength The generated key length.
 136:    * @throws NullPointerException If salt is null
 137:    * @throws IllegalArgumentException If salt is an empty array, if
 138:    *           iterationCount or keyLength is negative
 139:    */
 140:   public PBEKeySpec(char[] password, byte[] salt, int iterationCount,
 141:                     int keyLength)
 142:   {
 143:     setPassword(password);
 144:     setSalt(salt);
 145:     setIterationCount(iterationCount);
 146:     setKeyLength(keyLength);
 147:   }
 148: 
 149:   // Instance methods.
 150:   // ------------------------------------------------------------------------
 151: 
 152:   /**
 153:    * Clear the password array by filling it with null characters.
 154:    * <p>
 155:    * This clears the stored copy of the password, not the original char array
 156:    * used to create the password.
 157:    */
 158:   public final void clearPassword()
 159:   {
 160:     if (password == null)
 161:       return;
 162:     for (int i = 0; i < password.length; i++)
 163:       password[i] = '\u0000';
 164:     
 165:     // since the password is cleared, it is no longer valid
 166:     passwordValid = false;
 167:   }
 168: 
 169:   /**
 170:    * Get the iteration count, or 0 if it has not been specified.
 171:    *
 172:    * @return The iteration count, or 0 if it has not been specified.
 173:    */
 174:   public final int getIterationCount()
 175:   {
 176:     return iterationCount;
 177:   }
 178: 
 179:   /**
 180:    * Get the generated key length, or 0 if it has not been specified.
 181:    *
 182:    * @return The key length, or 0 if it has not been specified.
 183:    */
 184:   public final int getKeyLength()
 185:   {
 186:     return keyLength;
 187:   }
 188: 
 189:   /**
 190:    * Get the password character array copy.
 191:    * <p>
 192:    * This returns a copy of the password, not the password itself.
 193:    * 
 194:    * @return a clone of the password.
 195:    * @throws IllegalStateException If {@link #clearPassword()} has already been
 196:    *           called.
 197:    */
 198:   public final char[] getPassword()
 199:   {
 200:     if (! passwordValid)
 201:       throw new IllegalStateException("clearPassword() has been called, the "
 202:                                       + "password is no longer valid");
 203:     return (char[]) password.clone();
 204:   }
 205: 
 206:   /**
 207:    * Get the salt bytes array copy.
 208:    * <p>
 209:    * This returns a copy of the salt, not the salt itself.
 210:    * 
 211:    * @return The salt.
 212:    */
 213:   public final byte[] getSalt()
 214:   {
 215:     if (salt != null)
 216:       return (byte[]) salt.clone();
 217:     return null;
 218:   }
 219: 
 220:   /**
 221:    * Set the password char array.
 222:    * <p>
 223:    * A copy of the password argument is stored instead of the argument itself.
 224:    * 
 225:    * @param password The password to be set
 226:    */
 227:   private void setPassword(char[] password)
 228:   {
 229:     if (password != null)
 230:       this.password = (char[]) password.clone();
 231:     else
 232:       this.password = new char[0];
 233: 
 234:     passwordValid = true;
 235:   }
 236: 
 237:   /**
 238:    * Set the salt byte array.
 239:    * <p>
 240:    * A copy of the salt arguments is stored instead of the argument itself.
 241:    * 
 242:    * @param salt The salt to be set.
 243:    * @throws NullPointerException If the salt is null.
 244:    * @throws IllegalArgumentException If the salt is an empty array.
 245:    */
 246:   private void setSalt(byte[] salt)
 247:   {
 248:     if (salt.length == 0)
 249:       throw new IllegalArgumentException("salt MUST NOT be an empty byte array");
 250: 
 251:     this.salt = (byte[]) salt.clone();
 252:   }
 253: 
 254:   /**
 255:    * Set the iterationCount.
 256:    * 
 257:    * @param iterationCount The iteration count to be set.
 258:    * @throws IllegalArgumentException If the iterationCount is negative.
 259:    */
 260:   private void setIterationCount(int iterationCount)
 261:   {
 262:     if (iterationCount < 0)
 263:       throw new IllegalArgumentException("iterationCount MUST be positive");
 264: 
 265:     this.iterationCount = iterationCount;
 266:   }
 267: 
 268:   /**
 269:    * Set the keyLength.
 270:    * 
 271:    * @param keyLength The keyLength to be set.
 272:    * @throws IllegalArgumentException if the keyLength is negative.
 273:    */
 274:   private void setKeyLength(int keyLength)
 275:   {
 276:     if (keyLength < 0)
 277:       throw new IllegalArgumentException("keyLength MUST be positive");
 278: 
 279:     this.keyLength = keyLength;
 280:   }
 281: }