Home | History | Annotate | Download | only in spec
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package javax.crypto.spec;
     19 
     20 import java.security.spec.KeySpec;
     21 import java.util.Arrays;
     22 
     23 import org.apache.harmony.crypto.internal.nls.Messages;
     24 
     25 /**
     26  * The key specification for a <i>password based encryption</i> key.
     27  * <p>
     28  * Password based encryption is described in <a
     29  * href="http://www.ietf.org/rfc/rfc2898.txt">PKCS #5</a>.
     30  */
     31 public class PBEKeySpec implements KeySpec {
     32 
     33     private char[] password;
     34     private final byte[] salt;
     35     private final int iterationCount;
     36     private final int keyLength;
     37 
     38     /**
     39      * Creates a new <code>PBEKeySpec</code> with the specified password.
     40      *
     41      * @param password
     42      *            the password.
     43      */
     44     public PBEKeySpec(char[] password) {
     45         if (password == null) {
     46             this.password = new char[0];
     47         } else {
     48             this.password = new char[password.length];
     49             System.arraycopy(password, 0, this.password, 0, password.length);
     50         }
     51         salt = null;
     52         iterationCount = 0;
     53         keyLength = 0;
     54     }
     55 
     56     /**
     57      * Creates a new <code>PBEKeySpec</code> with the specified password, salt,
     58      * iteration count and the desired length of the derived key.
     59      *
     60      * @param password
     61      *            the password.
     62      * @param salt
     63      *            the salt.
     64      * @param iterationCount
     65      *            the iteration count.
     66      * @param keyLength
     67      *            the desired key length of the derived key,
     68      * @throws NullPointerException
     69      *             if the salt is null.
     70      * @throws IllegalArgumentException
     71      *             if the salt is empty, iteration count is zero or negative or
     72      *             the key length is zero or negative.
     73      */
     74     public PBEKeySpec(char[] password, byte[] salt, int iterationCount,
     75                       int keyLength) {
     76         if (salt == null) {
     77             throw new NullPointerException(Messages.getString("crypto.3B")); //$NON-NLS-1$
     78         }
     79         if (salt.length == 0) {
     80             throw new IllegalArgumentException(Messages.getString("crypto.3C")); //$NON-NLS-1$
     81         }
     82         if (iterationCount <= 0) {
     83             throw new IllegalArgumentException(
     84                     Messages.getString("crypto.3D")); //$NON-NLS-1$
     85         }
     86         if (keyLength <= 0) {
     87             throw new IllegalArgumentException(Messages.getString("crypto.3E")); //$NON-NLS-1$
     88         }
     89 
     90         if (password == null) {
     91             this.password = new char[0];
     92         } else {
     93             this.password = new char[password.length];
     94             System.arraycopy(password, 0, this.password, 0, password.length);
     95         }
     96         this.salt = new byte[salt.length];
     97         System.arraycopy(salt, 0, this.salt, 0, salt.length);
     98         this.iterationCount = iterationCount;
     99         this.keyLength = keyLength;
    100     }
    101 
    102     /**
    103      * Creates a new <code>PBEKeySpec</code> with the specified password, salt
    104      * and iteration count.
    105      *
    106      * @param password
    107      *            the password.
    108      * @param salt
    109      *            the salt.
    110      * @param iterationCount
    111      *            the iteration count.
    112      * @throws NullPointerException
    113      *             if salt is null.
    114      * @throws IllegalArgumentException
    115      *             if the salt is empty or iteration count is zero or negative.
    116      */
    117     public PBEKeySpec(char[] password, byte[] salt, int iterationCount) {
    118         if (salt == null) {
    119             throw new NullPointerException(Messages.getString("crypto.3B")); //$NON-NLS-1$
    120         }
    121         if (salt.length == 0) {
    122             throw new IllegalArgumentException(Messages.getString("crypto.3C")); //$NON-NLS-1$
    123         }
    124         if (iterationCount <= 0) {
    125             throw new IllegalArgumentException(
    126                     Messages.getString("crypto.3D")); //$NON-NLS-1$
    127         }
    128 
    129         if (password == null) {
    130             this.password = new char[0];
    131         } else {
    132             this.password = new char[password.length];
    133             System.arraycopy(password, 0, this.password, 0, password.length);
    134         }
    135         this.salt = new byte[salt.length];
    136         System.arraycopy(salt, 0, this.salt, 0, salt.length);
    137         this.iterationCount = iterationCount;
    138         this.keyLength = 0;
    139     }
    140 
    141     /**
    142      * Clears the password by overwriting it.
    143      */
    144     public final void clearPassword() {
    145         Arrays.fill(password, '?');
    146         password = null;
    147     }
    148 
    149     /**
    150      * Returns a copy of the password of this key specification.
    151      *
    152      * @return a copy of the password of this key specification.
    153      * @throws IllegalStateException
    154      *             if the password has been cleared before.
    155      */
    156     public final char[] getPassword() {
    157         if (password == null) {
    158             throw new IllegalStateException(Messages.getString("crypto.3F")); //$NON-NLS-1$
    159         }
    160         char[] result = new char[password.length];
    161         System.arraycopy(password, 0, result, 0, password.length);
    162         return result;
    163     }
    164 
    165     /**
    166      * Returns a copy of the salt of this key specification.
    167      *
    168      * @return a copy of the salt of this key specification or null if none is
    169      *         specified.
    170      */
    171     public final byte[] getSalt() {
    172         if (salt == null) {
    173             return null;
    174         }
    175         byte[] result = new byte[salt.length];
    176         System.arraycopy(salt, 0, result, 0, salt.length);
    177         return result;
    178     }
    179 
    180     /**
    181      * Returns the iteration count of this key specification.
    182      *
    183      * @return the iteration count of this key specification.
    184      */
    185     public final int getIterationCount() {
    186         return iterationCount;
    187     }
    188 
    189     /**
    190      * Returns the desired key length of the derived key.
    191      *
    192      * @return the desired key length of the derived key.
    193      */
    194     public final int getKeyLength() {
    195         return keyLength;
    196     }
    197 }
    198 
    199