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/**
19 * @author Alexander Y. Kleymenov
20 */
21
22package org.apache.harmony.crypto.tests.javax.crypto.spec;
23
24import java.util.Arrays;
25
26import javax.crypto.spec.PBEKeySpec;
27
28import junit.framework.Test;
29import junit.framework.TestCase;
30import junit.framework.TestSuite;
31
32/**
33 */
34
35public class PBEKeySpecTest extends TestCase {
36
37    /**
38     * PBEKeySpec(char[] password) method testing. Tests the behavior of
39     * the method in the case of null input char array and tests that input
40     * array is copied during the object initialization.
41     */
42    public void testPBEKeySpec1() {
43        try {
44            PBEKeySpec pbeks = new PBEKeySpec(null);
45            assertTrue("An empty char[] should be used in case of null "
46                    + "char array.", pbeks.getPassword().length == 0);
47        } catch (NullPointerException e) {
48            fail("Unexpected NullPointerException was thrown.");
49        }
50
51        char[] password = new char[] { '1', '2', '3', '4', '5' };
52        PBEKeySpec pbeks = new PBEKeySpec(password);
53        password[0]++;
54        assertFalse("The change of password specified in the constructor "
55                + "should not cause the change of internal array.",
56                password[0] == pbeks.getPassword()[0]);
57    }
58
59    /**
60     * PBEKeySpec(char[] password, byte[] salt, int iterationCount, int
61     * keyLength) method testing. Tests the behavior of the method in the case
62     * of inappropriate parameters and checks that array objects specified as
63     * a parameters are copied during the object initialization.
64     */
65    public void testPBEKeySpec2() {
66        char[] password = new char[] { '1', '2', '3', '4', '5' };
67        byte[] salt = new byte[] { 1, 2, 3, 4, 5 };
68        int iterationCount = 10;
69        int keyLength = 10;
70
71        try {
72            PBEKeySpec pbeks = new PBEKeySpec(null, salt,
73                    iterationCount, keyLength);
74            assertTrue("An empty char[] should be used in case of null input "
75                    + "char array.", pbeks.getPassword().length == 0);
76        } catch (IllegalArgumentException e) {
77            fail("Unexpected IllegalArgumentException was thrown.");
78        } catch (NullPointerException e) {
79            fail("Unexpected NullPointerException was thrown.");
80        }
81
82        try {
83            new PBEKeySpec(password, null, iterationCount, keyLength);
84            fail("A NullPointerException should be was thrown "
85                    + "in the case of null salt.");
86        } catch (IllegalArgumentException e) {
87            fail("Unexpected IllegalArgumentException was thrown.");
88        } catch (NullPointerException e) {
89        }
90
91        try {
92            new PBEKeySpec(password, new byte[0], iterationCount, keyLength);
93            fail("An IllegalArgumentException should be thrown "
94                    + "in the case of empty salt.");
95        } catch (IllegalArgumentException e) {
96        }
97
98        try {
99            new PBEKeySpec(password, salt, -1, keyLength);
100            fail("An IllegalArgumentException should be thrown "
101                    + "in the case of negative iterationCount.");
102        } catch (IllegalArgumentException e) {
103        }
104
105        try {
106            new PBEKeySpec(password, salt, iterationCount, -1);
107            fail("An IllegalArgumentException should be thrown "
108                    + "in the case of negative keyLength.");
109        } catch (IllegalArgumentException e) {
110        }
111
112        try {
113            new PBEKeySpec(password, salt, 0, keyLength);
114            fail("An IllegalArgumentException should be thrown "
115                    + "in the case of zero iterationCount.");
116        } catch (IllegalArgumentException e) {
117        }
118
119        try {
120            new PBEKeySpec(password, salt, iterationCount, 0);
121            fail("An IllegalArgumentException should be thrown "
122                    + "in the case of zero keyLength.");
123        } catch (IllegalArgumentException e) {
124        }
125
126        PBEKeySpec pbeks = new PBEKeySpec(password, salt,
127                iterationCount, keyLength);
128        password[0]++;
129        assertFalse("The change of password specified in the constructor "
130                + "should not cause the change of internal array.",
131                password[0] == pbeks.getPassword()[0]);
132        salt[0]++;
133        assertFalse("The change of salt specified in the constructor "
134                + " should not cause the change of internal array.",
135                salt[0] == pbeks.getSalt()[0]);
136    }
137
138    /**
139     * PBEKeySpec(char[] password, byte[] salt, int iterationCount) method
140     * testing. Tests the behavior of the method in the case
141     * of inappropriate parameters and checks that array objects specified as
142     * a parameters are copied during the object initialization.
143     */
144    public void testPBEKeySpec3() {
145        char[] password = new char[] { '1', '2', '3', '4', '5' };
146        byte[] salt = new byte[] { 1, 2, 3, 4, 5 };
147        int iterationCount = 10;
148
149        try {
150            PBEKeySpec pbeks = new PBEKeySpec(null, salt, iterationCount);
151            assertTrue("An empty char[] should be used in case of null input "
152                    + "char array.", pbeks.getPassword().length == 0);
153        } catch (IllegalArgumentException e) {
154            fail("Unexpected IllegalArgumentException was thrown.");
155        } catch (NullPointerException e) {
156            fail("Unexpected NullPointerException was thrown.");
157        }
158
159        try {
160            new PBEKeySpec(password, null, iterationCount);
161            fail("A NullPointerException should be was thrown "
162                    + "in the case of null salt.");
163        } catch (IllegalArgumentException e) {
164            fail("Unexpected IllegalArgumentException was thrown.");
165        } catch (NullPointerException e) {
166        }
167
168        try {
169            new PBEKeySpec(password, new byte[0],
170                    iterationCount);
171            fail("An IllegalArgumentException should be thrown "
172                    + "in the case of empty salt.");
173        } catch (IllegalArgumentException e) {
174        }
175
176        try {
177            new PBEKeySpec(password, salt, -1);
178            fail("An IllegalArgumentException should be thrown "
179                    + "in the case of negative iterationCount.");
180        } catch (IllegalArgumentException e) {
181        }
182
183        try {
184            new PBEKeySpec(password, salt, 0);
185            fail("An IllegalArgumentException should be thrown "
186                    + "in the case of zero iterationCount.");
187        } catch (IllegalArgumentException e) {
188        }
189
190        PBEKeySpec pbeks = new PBEKeySpec(password, salt, iterationCount);
191        password[0]++;
192        assertFalse("The change of password specified in the constructor "
193                + "should not cause the change of internal array.",
194                password[0] == pbeks.getPassword()[0]);
195        salt[0]++;
196        assertFalse("The change of salt specified in the constructor "
197                + " should not cause the change of internal array.",
198                salt[0] == pbeks.getSalt()[0]);
199    }
200
201    /**
202     * clearPassword() method testing. Tests that internal copy of password
203     * is cleared after the method call.
204     */
205    public void testClearPassword() {
206        char[] password = new char[] { '1', '2', '3', '4', '5' };
207        PBEKeySpec pbeks = new PBEKeySpec(password);
208        pbeks.clearPassword();
209        try {
210            pbeks.getPassword();
211            fail("An IllegalStateException should be was thrown "
212                    + "after the clearing the password.");
213        } catch (IllegalStateException e) {
214        }
215    }
216
217    /**
218     * getPassword() method testing. Tests that returned password is equal
219     * to the password specified in the constructor and that the change of
220     * returned array does not cause the change of internal array.
221     */
222    public void testGetPassword() {
223        char[] password = new char[] { '1', '2', '3', '4', '5' };
224        PBEKeySpec pbeks = new PBEKeySpec(password);
225        char[] result = pbeks.getPassword();
226        if (!Arrays.equals(password, result)) {
227            fail("The returned password is not equal to the specified "
228                    + "in the constructor.");
229        }
230        result[0]++;
231        assertFalse("The change of returned by getPassword() method password "
232                + "should not cause the change of internal array.",
233                result[0] == pbeks.getPassword()[0]);
234    }
235
236    /**
237     * getSalt() method testing. Tests that returned salt is equal
238     * to the salt specified in the constructor and that the change of
239     * returned array does not cause the change of internal array.
240     * Also it checks that the method returns null if salt is not
241     * specified.
242     */
243    public void testGetSalt() {
244        char[] password = new char[] { '1', '2', '3', '4', '5' };
245        byte[] salt = new byte[] { 1, 2, 3, 4, 5 };
246        int iterationCount = 10;
247        PBEKeySpec pbeks = new PBEKeySpec(password, salt, iterationCount);
248        byte[] result = pbeks.getSalt();
249        if (!Arrays.equals(salt, result)) {
250            fail("The returned salt is not equal to the specified "
251                    + "in the constructor.");
252        }
253        result[0]++;
254        assertFalse("The change of returned by getSalt() method salt"
255                + "should not cause the change of internal array.",
256                result[0] == pbeks.getSalt()[0]);
257        pbeks = new PBEKeySpec(password);
258        assertNull("The getSalt() method should return null if the salt "
259                + "is not specified.", pbeks.getSalt());
260    }
261
262    /**
263     * getIterationCount() method testing. Tests that returned value is equal
264     * to the value specified in the constructor.
265     * Also it checks that the method returns 0 if iterationCount is not
266     * specified.
267     */
268    public void testGetIterationCount() {
269        char[] password = new char[] { '1', '2', '3', '4', '5' };
270        byte[] salt = new byte[] { 1, 2, 3, 4, 5 };
271        int iterationCount = 10;
272        PBEKeySpec pbeks = new PBEKeySpec(password, salt, iterationCount);
273        assertTrue("The returned iterationCount is not equal to the specified "
274                + "in the constructor.",
275                pbeks.getIterationCount() == iterationCount);
276        pbeks = new PBEKeySpec(password);
277        assertTrue("The getIterationCount() method should return 0 "
278                + "if the iterationCount is not specified.",
279                pbeks.getIterationCount() == 0);
280    }
281
282    /**
283     * getKeyLength() method testing.
284     */
285    public void testGetKeyLength() {
286        char[] password = new char[] { '1', '2', '3', '4', '5' };
287        byte[] salt = new byte[] { 1, 2, 3, 4, 5 };
288        int iterationCount = 10;
289        int keyLength = 10;
290        PBEKeySpec pbeks = new PBEKeySpec(password, salt,
291                iterationCount, keyLength);
292        assertTrue("The returned keyLength is not equal to the value specified "
293                + "in the constructor.",
294                pbeks.getKeyLength() == keyLength);
295        pbeks = new PBEKeySpec(password);
296        assertTrue("The getKeyLength() method should return 0 "
297                + "if the keyLength is not specified.",
298                pbeks.getKeyLength() == 0);
299    }
300
301    public static Test suite() {
302        return new TestSuite(PBEKeySpecTest.class);
303    }
304
305}
306