1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with this
4 * work for additional information regarding copyright ownership. The ASF
5 * licenses this file to You under the Apache License, Version 2.0 (the
6 * "License"); you may not use this file except in compliance with the License.
7 * 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, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 */
17
18/**
19 * @author Alexander Y. Kleymenov
20 * @version $Revision$
21 */
22
23package org.apache.harmony.crypto.tests.javax.crypto;
24
25import dalvik.annotation.TestLevel;
26import dalvik.annotation.TestTargetClass;
27import dalvik.annotation.TestTargetNew;
28
29import junit.framework.TestCase;
30
31import java.io.ByteArrayInputStream;
32import java.io.ByteArrayOutputStream;
33import java.io.IOException;
34import java.io.ObjectInputStream;
35import java.io.ObjectOutputStream;
36import java.io.Serializable;
37import java.security.InvalidKeyException;
38import java.security.Key;
39import java.security.NoSuchProviderException;
40import java.util.Arrays;
41
42import javax.crypto.Cipher;
43import javax.crypto.IllegalBlockSizeException;
44import javax.crypto.KeyGenerator;
45import javax.crypto.NullCipher;
46import javax.crypto.SealedObject;
47import javax.crypto.spec.IvParameterSpec;
48import javax.crypto.spec.SecretKeySpec;
49
50@TestTargetClass(SealedObject.class)
51/**
52 */
53public class SealedObjectTest extends TestCase {
54    class Mock_SealedObject extends SealedObject {
55        public Mock_SealedObject(Serializable object, Cipher c)
56                throws IOException, IllegalBlockSizeException {
57            super(object, c);
58        }
59
60        public byte[] get_encodedParams() {
61            return super.encodedParams;
62        }
63
64    }
65
66    /**
67     * readObject(ObjectInputStream s) method testing. Tests if the
68     * serialization/deserialization works correctly: object is serialized,
69     * deserialized, the content od deserialized object equals to the content of
70     * initial object.
71     */
72    @TestTargetNew(
73        level = TestLevel.COMPLETE,
74        notes = "",
75        method = "!Serialization",
76        args = {}
77    )
78    public void testReadObject() throws Exception {
79        String secret = "secret string";
80        SealedObject so = new SealedObject(secret, new NullCipher());
81        ByteArrayOutputStream bos = new ByteArrayOutputStream();
82        ObjectOutputStream oos = new ObjectOutputStream(bos);
83        oos.writeObject(so);
84
85        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
86                bos.toByteArray()));
87
88        SealedObject so_des = (SealedObject) ois.readObject();
89        assertEquals("The secret content of deserialized object "
90                + "should be equal to the secret content of initial object",
91                secret, so_des.getObject(new NullCipher()));
92        assertEquals("The value returned by getAlgorithm() method of "
93                + "deserialized object should be equal to the value returned "
94                + "by getAlgorithm() method of initial object", so
95                .getAlgorithm(), so_des.getAlgorithm());
96    }
97
98    /**
99     * SealedObject(Serializable object, Cipher c) method testing. Tests if the
100     * NullPointerException is thrown in the case of null cipher.
101     */
102    @TestTargetNew(
103        level = TestLevel.COMPLETE,
104        method = "SealedObject",
105        args = {java.io.Serializable.class, javax.crypto.Cipher.class}
106    )
107    public void testSealedObject1() throws Exception {
108        String secret = "secret string";
109        try {
110            new SealedObject(secret, null);
111            fail("NullPointerException should be thrown in the case "
112                    + "of null cipher.");
113        } catch (NullPointerException e) {
114        }
115
116        KeyGenerator kg = KeyGenerator.getInstance("DES");
117        Key key = kg.generateKey();
118
119        IvParameterSpec ips = new IvParameterSpec(new byte[] {
120                1, 2, 3, 4, 5, 6, 7, 8});
121
122        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
123        cipher.init(Cipher.ENCRYPT_MODE, key, ips);
124
125        SealedObject so = new SealedObject(secret, cipher);
126
127        cipher = Cipher.getInstance("DES/CBC/NoPadding");
128        cipher.init(Cipher.ENCRYPT_MODE, key, ips);
129
130        try {
131            new SealedObject(secret, cipher);
132            fail("IllegalBlockSizeException expected");
133        } catch (IllegalBlockSizeException e) {
134            //expected
135        }
136    }
137
138    /**
139     * SealedObject(SealedObject so) method testing. Tests if the
140     * NullPointerException is thrown in the case of null SealedObject.
141     */
142    @TestTargetNew(
143        level = TestLevel.COMPLETE,
144        notes = "",
145        method = "SealedObject",
146        args = {javax.crypto.SealedObject.class}
147    )
148    public void testSealedObject2() throws Exception {
149        try {
150            new SealedObject(null) {};
151            fail("NullPointerException should be thrown in the case "
152                    + "of null SealedObject.");
153        } catch (NullPointerException e) {
154        }
155
156        String secret = "secret string";
157        Cipher cipher = new NullCipher();
158        SealedObject so1 = new SealedObject(secret, cipher);
159        SealedObject so2 = new SealedObject(so1) {};
160
161        assertEquals("The secret content of the object should equals "
162                + "to the secret content of initial object.", secret, so2
163                .getObject(cipher));
164        assertEquals("The algorithm which was used to seal the object "
165                + "should be the same as the algorithm used to seal the "
166                + "initial object", so1.getAlgorithm(), so2.getAlgorithm());
167    }
168
169    /**
170     * getAlgorithm() method testing. Tests if the returned value equals to the
171     * corresponding value of Cipher object.
172     */
173    @TestTargetNew(
174        level = TestLevel.COMPLETE,
175        notes = "",
176        method = "getAlgorithm",
177        args = {}
178    )
179    public void testGetAlgorithm() throws Exception {
180        String secret = "secret string";
181        String algorithm = "DES";
182        KeyGenerator kg = KeyGenerator.getInstance(algorithm);
183        Key key = kg.generateKey();
184
185        Cipher cipher = Cipher.getInstance(algorithm);
186        cipher.init(Cipher.ENCRYPT_MODE, key);
187        SealedObject so = new SealedObject(secret, cipher);
188
189        assertEquals("The algorithm name should be the same as used "
190                + "in cipher.", algorithm, so.getAlgorithm());
191    }
192
193    /**
194     * getObject(Key key) method testing. Tests if the object sealed with
195     * encryption algorithm and specified parameters can be retrieved by
196     * specifying the cryptographic key.
197     */
198    @TestTargetNew(
199        level = TestLevel.COMPLETE,
200        notes = "Not all exceptions can be checked.",
201        method = "getObject",
202        args = {java.security.Key.class}
203    )
204    public void testGetObject1() throws Exception {
205        KeyGenerator kg = KeyGenerator.getInstance("DES");
206        Key key = kg.generateKey();
207
208        IvParameterSpec ips = new IvParameterSpec(new byte[] {
209                1, 2, 3, 4, 5, 6, 7, 8});
210
211        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
212        cipher.init(Cipher.ENCRYPT_MODE, key, ips);
213
214        String secret = "secret string";
215        Mock_SealedObject so = new Mock_SealedObject(secret, cipher);
216
217        assertEquals("The returned object does not equals to the "
218                + "original object.", secret, so.getObject(key));
219
220        assertTrue("The encodedParams field of SealedObject object "
221                + "should contain the encoded algorithm parameters.", Arrays
222                .equals(so.get_encodedParams(), cipher.getParameters()
223                        .getEncoded()));
224        try {
225            so.getObject((Key)null);
226            fail("InvalidKeyException expected");
227        } catch (InvalidKeyException e) {
228            //expected
229        } catch (NullPointerException e) {
230            //also ok
231        }
232    }
233
234    /**
235     * getObject(Cipher c) method testing. Tests if the proper exception is
236     * thrown in the case of incorrect input parameters and if the object sealed
237     * with encryption algorithm and specified parameters can be retrieved by
238     * specifying the initialized Cipher object.
239     */
240    @TestTargetNew(
241        level = TestLevel.COMPLETE,
242        notes = "Not all exceptions can be checked.",
243        method = "getObject",
244        args = {javax.crypto.Cipher.class}
245    )
246    public void testGetObject2() throws Exception {
247        try {
248            new SealedObject("secret string", new NullCipher())
249                    .getObject((Cipher) null);
250            fail("NullPointerException should be thrown in the case of "
251                    + "null cipher.");
252        } catch (NullPointerException e) {
253        }
254
255        KeyGenerator kg = KeyGenerator.getInstance("DES");
256        Key key = kg.generateKey();
257
258        IvParameterSpec ips = new IvParameterSpec(new byte[] {
259                1, 2, 3, 4, 5, 6, 7, 8});
260
261        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
262        cipher.init(Cipher.ENCRYPT_MODE, key, ips);
263
264        String secret = "secret string";
265        SealedObject so = new SealedObject(secret, cipher);
266
267        cipher.init(Cipher.DECRYPT_MODE, key, ips);
268        assertEquals("The returned object does not equals to the "
269                + "original object.", secret, so.getObject(cipher));
270
271        try {
272            so.getObject((Cipher)null);
273            fail("NullPointerException expected");
274        } catch (NullPointerException e) {
275            //expected
276        }
277    }
278
279    /**
280     * getObject(Key key, String provider) method testing. Tests if the proper
281     * exception is thrown in the case of incorrect input parameters and if the
282     * object sealed with encryption algorithm can be retrieved by specifying
283     * the cryptographic key and provider name.
284     */
285    @TestTargetNew(
286        level = TestLevel.COMPLETE,
287        notes = "Not all exceptions can be checked.",
288        method = "getObject",
289        args = {java.security.Key.class, java.lang.String.class}
290    )
291    public void testGetObject3() throws Exception {
292        try {
293            new SealedObject("secret string", new NullCipher()).getObject(
294                    new SecretKeySpec(new byte[] {0, 0, 0}, "algorithm"), null);
295            fail("IllegalArgumentException should be thrown in the case of "
296                    + "null provider.");
297        } catch (IllegalArgumentException e) {
298        }
299
300        try {
301            new SealedObject("secret string", new NullCipher()).getObject(
302                    new SecretKeySpec(new byte[] {0, 0, 0}, "algorithm"), "");
303            fail("IllegalArgumentException should be thrown in the case of "
304                    + "empty provider.");
305        } catch (IllegalArgumentException e) {
306        }
307
308        KeyGenerator kg = KeyGenerator.getInstance("DES");
309        Key key = kg.generateKey();
310
311        Cipher cipher = Cipher.getInstance("DES");
312        String provider = cipher.getProvider().getName();
313        cipher.init(Cipher.ENCRYPT_MODE, key);
314
315        String secret = "secret string";
316        SealedObject so = new SealedObject(secret, cipher);
317
318        cipher.init(Cipher.DECRYPT_MODE, key);
319        assertEquals("The returned object does not equals to the "
320                + "original object.", secret, so.getObject(key, provider));
321
322        kg = KeyGenerator.getInstance("DESede");
323        key = kg.generateKey();
324
325        try {
326            so.getObject(key, provider);
327            fail("InvalidKeyException expected");
328        } catch (InvalidKeyException e) {
329            //expected
330        }
331
332        try {
333            so.getObject(key, "Wrong provider name");
334            fail("NoSuchProviderException expected");
335        } catch (NoSuchProviderException e) {
336            //expected
337        }
338    }
339
340}
341