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 import libcore.util.EmptyArray;
     23 
     24 /**
     25  * The key specification for a <i>password based encryption</i> key.
     26  * <p>
     27  * Password based encryption is described in <a
     28  * href="http://www.ietf.org/rfc/rfc2898.txt">PKCS #5</a>.
     29  */
     30 public class PBEKeySpec implements KeySpec {
     31 
     32     private char[] password;
     33     private final byte[] salt;
     34     private final int iterationCount;
     35     private final int keyLength;
     36 
     37     /**
     38      * Creates a new <code>PBEKeySpec</code> with the specified password.
     39      *
     40      * @param password
     41      *            the password.
     42      */
     43     public PBEKeySpec(char[] password) {
     44         if (password == null) {
     45             this.password = EmptyArray.CHAR;
     46         } else {
     47             this.password = new char[password.length];
     48             System.arraycopy(password, 0, this.password, 0, password.length);
     49         }
     50         salt = null;
     51         iterationCount = 0;
     52         keyLength = 0;
     53     }
     54 
     55     /**
     56      * Creates a new <code>PBEKeySpec</code> with the specified password, salt,
     57      * iteration count and the desired length of the derived key.
     58      *
     59      * @param password
     60      *            the password.
     61      * @param salt
     62      *            the salt.
     63      * @param iterationCount
     64      *            the iteration count.
     65      * @param keyLength
     66      *            the desired key length of the derived key,
     67      * @throws NullPointerException
     68      *             if the salt is null.
     69      * @throws IllegalArgumentException
     70      *             if the salt is empty, iteration count is zero or negative or
     71      *             the key length is zero or negative.
     72      */
     73     public PBEKeySpec(char[] password, byte[] salt, int iterationCount,
     74                       int keyLength) {
     75         if (salt == null) {
     76             throw new NullPointerException("salt == null");
     77         }
     78         if (salt.length == 0) {
     79             throw new IllegalArgumentException("salt.length == 0");
     80         }
     81         if (iterationCount <= 0) {
     82             throw new IllegalArgumentException("iterationCount <= 0");
     83         }
     84         if (keyLength <= 0) {
     85             throw new IllegalArgumentException("keyLength <= 0");
     86         }
     87 
     88         if (password == null) {
     89             this.password = EmptyArray.CHAR;
     90         } else {
     91             this.password = new char[password.length];
     92             System.arraycopy(password, 0, this.password, 0, password.length);
     93         }
     94         this.salt = new byte[salt.length];
     95         System.arraycopy(salt, 0, this.salt, 0, salt.length);
     96         this.iterationCount = iterationCount;
     97         this.keyLength = keyLength;
     98     }
     99 
    100     /**
    101      * Creates a new <code>PBEKeySpec</code> with the specified password, salt
    102      * and iteration count.
    103      *
    104      * @param password
    105      *            the password.
    106      * @param salt
    107      *            the salt.
    108      * @param iterationCount
    109      *            the iteration count.
    110      * @throws NullPointerException
    111      *             if salt is null.
    112      * @throws IllegalArgumentException
    113      *             if the salt is empty or iteration count is zero or negative.
    114      */
    115     public PBEKeySpec(char[] password, byte[] salt, int iterationCount) {
    116         if (salt == null) {
    117             throw new NullPointerException("salt == null");
    118         }
    119         if (salt.length == 0) {
    120             throw new IllegalArgumentException("salt.length == 0");
    121         }
    122         if (iterationCount <= 0) {
    123             throw new IllegalArgumentException("iterationCount <= 0");
    124         }
    125 
    126         if (password == null) {
    127             this.password = EmptyArray.CHAR;
    128         } else {
    129             this.password = new char[password.length];
    130             System.arraycopy(password, 0, this.password, 0, password.length);
    131         }
    132         this.salt = new byte[salt.length];
    133         System.arraycopy(salt, 0, this.salt, 0, salt.length);
    134         this.iterationCount = iterationCount;
    135         this.keyLength = 0;
    136     }
    137 
    138     /**
    139      * Clears the password by overwriting it.
    140      */
    141     public final void clearPassword() {
    142         Arrays.fill(password, '?');
    143         password = null;
    144     }
    145 
    146     /**
    147      * Returns a copy of the password of this key specification.
    148      *
    149      * @return a copy of the password of this key specification.
    150      * @throws IllegalStateException
    151      *             if the password has been cleared before.
    152      */
    153     public final char[] getPassword() {
    154         if (password == null) {
    155             throw new IllegalStateException("The password has been cleared");
    156         }
    157         char[] result = new char[password.length];
    158         System.arraycopy(password, 0, result, 0, password.length);
    159         return result;
    160     }
    161 
    162     /**
    163      * Returns a copy of the salt of this key specification.
    164      *
    165      * @return a copy of the salt of this key specification or null if none is
    166      *         specified.
    167      */
    168     public final byte[] getSalt() {
    169         if (salt == null) {
    170             return null;
    171         }
    172         byte[] result = new byte[salt.length];
    173         System.arraycopy(salt, 0, result, 0, salt.length);
    174         return result;
    175     }
    176 
    177     /**
    178      * Returns the iteration count of this key specification.
    179      *
    180      * @return the iteration count of this key specification.
    181      */
    182     public final int getIterationCount() {
    183         return iterationCount;
    184     }
    185 
    186     /**
    187      * Returns the desired key length of the derived key.
    188      *
    189      * @return the desired key length of the derived key.
    190      */
    191     public final int getKeyLength() {
    192         return keyLength;
    193     }
    194 }
    195