• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 package org.apache.harmony.crypto.tests.javax.crypto;
24 
25 import junit.framework.TestCase;
26 
27 import java.io.ByteArrayInputStream;
28 import java.io.ByteArrayOutputStream;
29 import java.io.IOException;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32 import java.io.Serializable;
33 import java.security.InvalidKeyException;
34 import java.security.Key;
35 import java.security.NoSuchProviderException;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 
39 import javax.crypto.Cipher;
40 import javax.crypto.IllegalBlockSizeException;
41 import javax.crypto.KeyGenerator;
42 import javax.crypto.NullCipher;
43 import javax.crypto.SealedObject;
44 import javax.crypto.spec.IvParameterSpec;
45 import javax.crypto.spec.SecretKeySpec;
46 
47 import libcore.libcore.util.SerializationTester;
48 
49 /**
50  */
51 public class SealedObjectTest extends TestCase {
52     class Mock_SealedObject extends SealedObject {
Mock_SealedObject(Serializable object, Cipher c)53         public Mock_SealedObject(Serializable object, Cipher c)
54                 throws IOException, IllegalBlockSizeException {
55             super(object, c);
56         }
57 
get_encodedParams()58         public byte[] get_encodedParams() {
59             return super.encodedParams;
60         }
61 
62     }
63 
64     /**
65      * readObject(ObjectInputStream s) method testing. Tests if the
66      * serialization/deserialization works correctly: object is serialized,
67      * deserialized, the content od deserialized object equals to the content of
68      * initial object.
69      */
testReadObject()70     public void testReadObject() throws Exception {
71         String secret = "secret string";
72         SealedObject so = new SealedObject(secret, new NullCipher());
73         ByteArrayOutputStream bos = new ByteArrayOutputStream();
74         ObjectOutputStream oos = new ObjectOutputStream(bos);
75         oos.writeObject(so);
76 
77         ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
78                 bos.toByteArray()));
79 
80         SealedObject so_des = (SealedObject) ois.readObject();
81         assertEquals("The secret content of deserialized object "
82                 + "should be equal to the secret content of initial object",
83                 secret, so_des.getObject(new NullCipher()));
84         assertEquals("The value returned by getAlgorithm() method of "
85                 + "deserialized object should be equal to the value returned "
86                 + "by getAlgorithm() method of initial object", so
87                 .getAlgorithm(), so_des.getAlgorithm());
88     }
89 
90     /**
91      * SealedObject(Serializable object, Cipher c) method testing. Tests if the
92      * NullPointerException is thrown in the case of null cipher.
93      */
testSealedObject1()94     public void testSealedObject1() throws Exception {
95         String secret = "secret string";
96         try {
97             new SealedObject(secret, null);
98             fail("NullPointerException should be thrown in the case "
99                     + "of null cipher.");
100         } catch (NullPointerException e) {
101         }
102 
103         KeyGenerator kg = KeyGenerator.getInstance("DES");
104         Key key = kg.generateKey();
105 
106         IvParameterSpec ips = new IvParameterSpec(new byte[] {
107                 1, 2, 3, 4, 5, 6, 7, 8});
108 
109         Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
110         cipher.init(Cipher.ENCRYPT_MODE, key, ips);
111 
112         SealedObject so = new SealedObject(secret, cipher);
113 
114         cipher = Cipher.getInstance("DES/CBC/NoPadding");
115         cipher.init(Cipher.ENCRYPT_MODE, key, ips);
116 
117         try {
118             new SealedObject(secret, cipher);
119             fail("IllegalBlockSizeException expected");
120         } catch (IllegalBlockSizeException e) {
121             //expected
122         }
123     }
124 
125     /**
126      * SealedObject(SealedObject so) method testing. Tests if the
127      * NullPointerException is thrown in the case of null SealedObject.
128      */
testSealedObject2()129     public void testSealedObject2() throws Exception {
130         try {
131             new SealedObject(null) {};
132             fail("NullPointerException should be thrown in the case "
133                     + "of null SealedObject.");
134         } catch (NullPointerException e) {
135         }
136 
137         String secret = "secret string";
138         Cipher cipher = new NullCipher();
139         SealedObject so1 = new SealedObject(secret, cipher);
140         SealedObject so2 = new SealedObject(so1) {};
141 
142         assertEquals("The secret content of the object should equals "
143                 + "to the secret content of initial object.", secret, so2
144                 .getObject(cipher));
145         assertEquals("The algorithm which was used to seal the object "
146                 + "should be the same as the algorithm used to seal the "
147                 + "initial object", so1.getAlgorithm(), so2.getAlgorithm());
148     }
149 
150     /**
151      * getAlgorithm() method testing. Tests if the returned value equals to the
152      * corresponding value of Cipher object.
153      */
testGetAlgorithm()154     public void testGetAlgorithm() throws Exception {
155         String secret = "secret string";
156         String algorithm = "DES";
157         KeyGenerator kg = KeyGenerator.getInstance(algorithm);
158         Key key = kg.generateKey();
159 
160         Cipher cipher = Cipher.getInstance(algorithm);
161         cipher.init(Cipher.ENCRYPT_MODE, key);
162         SealedObject so = new SealedObject(secret, cipher);
163 
164         assertEquals("The algorithm name should be the same as used "
165                 + "in cipher.", algorithm, so.getAlgorithm());
166     }
167 
168     // https://code.google.com/p/android/issues/detail?id=73235
testGetAlgorithmAfterSerialization()169     public void testGetAlgorithmAfterSerialization() throws Exception {
170         String secret = "secret string";
171         String algorithm = "DES";
172         KeyGenerator kg = KeyGenerator.getInstance(algorithm);
173         Key key = kg.generateKey();
174 
175         Cipher cipher = Cipher.getInstance(algorithm);
176         cipher.init(Cipher.ENCRYPT_MODE, key);
177         SealedObject so = new SealedObject(secret, cipher);
178 
179         assertEquals("The algorithm name should be the same as used "
180                 + "in cipher.", algorithm, so.getAlgorithm());
181 
182         ByteArrayOutputStream baos = new ByteArrayOutputStream();
183         ObjectOutputStream oos = new ObjectOutputStream(baos);
184         oos.writeObject(so);
185         oos.close();
186 
187         ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
188         SealedObject readSo = (SealedObject) ois.readObject();
189         ois.close();
190 
191         // Bug 73235 would swap the Cipher algorithm and parameters. Parameters is not public but
192         // algorithm is so we check that.
193         assertEquals(so.getAlgorithm(), readSo.getAlgorithm());
194     }
195 
196     /**
197      * getObject(Key key) method testing. Tests if the object sealed with
198      * encryption algorithm and specified parameters can be retrieved by
199      * specifying the cryptographic key.
200      */
testGetObject1()201     public void testGetObject1() throws Exception {
202         KeyGenerator kg = KeyGenerator.getInstance("DES");
203         Key key = kg.generateKey();
204 
205         IvParameterSpec ips = new IvParameterSpec(new byte[] {
206                 1, 2, 3, 4, 5, 6, 7, 8});
207 
208         Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
209         cipher.init(Cipher.ENCRYPT_MODE, key, ips);
210 
211         String secret = "secret string";
212         Mock_SealedObject so = new Mock_SealedObject(secret, cipher);
213 
214         assertEquals("The returned object does not equals to the "
215                 + "original object.", secret, so.getObject(key));
216 
217         assertTrue("The encodedParams field of SealedObject object "
218                 + "should contain the encoded algorithm parameters.", Arrays
219                 .equals(so.get_encodedParams(), cipher.getParameters()
220                         .getEncoded()));
221         try {
222             so.getObject((Key)null);
223             fail("InvalidKeyException expected");
224         } catch (InvalidKeyException e) {
225             //expected
226         } catch (NullPointerException e) {
227             //also ok
228         }
229     }
230 
231     /**
232      * getObject(Cipher c) method testing. Tests if the proper exception is
233      * thrown in the case of incorrect input parameters and if the object sealed
234      * with encryption algorithm and specified parameters can be retrieved by
235      * specifying the initialized Cipher object.
236      */
testGetObject2()237     public void testGetObject2() throws Exception {
238         try {
239             new SealedObject("secret string", new NullCipher())
240                     .getObject((Cipher) null);
241             fail("NullPointerException should be thrown in the case of "
242                     + "null cipher.");
243         } catch (NullPointerException e) {
244         }
245 
246         KeyGenerator kg = KeyGenerator.getInstance("DES");
247         Key key = kg.generateKey();
248 
249         IvParameterSpec ips = new IvParameterSpec(new byte[] {
250                 1, 2, 3, 4, 5, 6, 7, 8});
251 
252         Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
253         cipher.init(Cipher.ENCRYPT_MODE, key, ips);
254 
255         String secret = "secret string";
256         SealedObject so = new SealedObject(secret, cipher);
257 
258         cipher.init(Cipher.DECRYPT_MODE, key, ips);
259         assertEquals("The returned object does not equals to the "
260                 + "original object.", secret, so.getObject(cipher));
261 
262         try {
263             so.getObject((Cipher)null);
264             fail("NullPointerException expected");
265         } catch (NullPointerException e) {
266             //expected
267         }
268     }
269 
270     /**
271      * getObject(Key key, String provider) method testing. Tests if the proper
272      * exception is thrown in the case of incorrect input parameters and if the
273      * object sealed with encryption algorithm can be retrieved by specifying
274      * the cryptographic key and provider name.
275      */
testGetObject3()276     public void testGetObject3() throws Exception {
277         try {
278             new SealedObject("secret string", new NullCipher()).getObject(
279                     new SecretKeySpec(new byte[] {0, 0, 0}, "algorithm"), null);
280             fail("IllegalArgumentException should be thrown in the case of "
281                     + "null provider.");
282         } catch (IllegalArgumentException e) {
283         }
284 
285         try {
286             new SealedObject("secret string", new NullCipher()).getObject(
287                     new SecretKeySpec(new byte[] {0, 0, 0}, "algorithm"), "");
288             fail("IllegalArgumentException should be thrown in the case of "
289                     + "empty provider.");
290         } catch (IllegalArgumentException e) {
291         }
292 
293         KeyGenerator kg = KeyGenerator.getInstance("DES");
294         Key key = kg.generateKey();
295 
296         Cipher cipher = Cipher.getInstance("DES");
297         String provider = cipher.getProvider().getName();
298         cipher.init(Cipher.ENCRYPT_MODE, key);
299 
300         String secret = "secret string";
301         SealedObject so = new SealedObject(secret, cipher);
302 
303         cipher.init(Cipher.DECRYPT_MODE, key);
304         assertEquals("The returned object does not equals to the "
305                 + "original object.", secret, so.getObject(key, provider));
306 
307         kg = KeyGenerator.getInstance("DESede");
308         key = kg.generateKey();
309 
310         try {
311             so.getObject(key, provider);
312             fail("InvalidKeyException expected");
313         } catch (InvalidKeyException e) {
314             //expected
315         }
316 
317         try {
318             so.getObject(key, "Wrong provider name");
319             fail("NoSuchProviderException expected");
320         } catch (NoSuchProviderException e) {
321             //expected
322         }
323     }
324 
325     // http://code.google.com/p/android/issues/detail?id=4834
testDeserialization()326     public void testDeserialization() throws Exception {
327         // (Boilerplate so we can create SealedObject instances.)
328         KeyGenerator kg = KeyGenerator.getInstance("DES");
329         Key key = kg.generateKey();
330         Cipher cipher = Cipher.getInstance("DES");
331         cipher.init(Cipher.ENCRYPT_MODE, key);
332 
333         // Incorrect use of readUnshared meant you couldn't have two SealedObjects
334         // with the same algorithm or parameters algorithm...
335         ArrayList<SealedObject> sealedObjects = new ArrayList<SealedObject>();
336         for (int i = 0; i < 10; ++i) {
337             sealedObjects.add(new SealedObject("hello", cipher));
338         }
339         String serializedForm = SerializationTester.serializeHex(sealedObjects);
340 
341         // ...so this would throw "java.io.InvalidObjectException: Unshared read of back reference".
342         SerializationTester.deserializeHex(serializedForm);
343     }
344 }
345