Frames | No Frames |
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: }