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.util.SerializationTester; 48 49 /** 50 */ 51 public class SealedObjectTest extends TestCase { 52 class Mock_SealedObject extends SealedObject { 53 public Mock_SealedObject(Serializable object, Cipher c) 54 throws IOException, IllegalBlockSizeException { 55 super(object, c); 56 } 57 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 */ 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 */ 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 */ 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 */ 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 /** 169 * getObject(Key key) method testing. Tests if the object sealed with 170 * encryption algorithm and specified parameters can be retrieved by 171 * specifying the cryptographic key. 172 */ 173 public void testGetObject1() throws Exception { 174 KeyGenerator kg = KeyGenerator.getInstance("DES"); 175 Key key = kg.generateKey(); 176 177 IvParameterSpec ips = new IvParameterSpec(new byte[] { 178 1, 2, 3, 4, 5, 6, 7, 8}); 179 180 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 181 cipher.init(Cipher.ENCRYPT_MODE, key, ips); 182 183 String secret = "secret string"; 184 Mock_SealedObject so = new Mock_SealedObject(secret, cipher); 185 186 assertEquals("The returned object does not equals to the " 187 + "original object.", secret, so.getObject(key)); 188 189 assertTrue("The encodedParams field of SealedObject object " 190 + "should contain the encoded algorithm parameters.", Arrays 191 .equals(so.get_encodedParams(), cipher.getParameters() 192 .getEncoded())); 193 try { 194 so.getObject((Key)null); 195 fail("InvalidKeyException expected"); 196 } catch (InvalidKeyException e) { 197 //expected 198 } catch (NullPointerException e) { 199 //also ok 200 } 201 } 202 203 /** 204 * getObject(Cipher c) method testing. Tests if the proper exception is 205 * thrown in the case of incorrect input parameters and if the object sealed 206 * with encryption algorithm and specified parameters can be retrieved by 207 * specifying the initialized Cipher object. 208 */ 209 public void testGetObject2() throws Exception { 210 try { 211 new SealedObject("secret string", new NullCipher()) 212 .getObject((Cipher) null); 213 fail("NullPointerException should be thrown in the case of " 214 + "null cipher."); 215 } catch (NullPointerException e) { 216 } 217 218 KeyGenerator kg = KeyGenerator.getInstance("DES"); 219 Key key = kg.generateKey(); 220 221 IvParameterSpec ips = new IvParameterSpec(new byte[] { 222 1, 2, 3, 4, 5, 6, 7, 8}); 223 224 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 225 cipher.init(Cipher.ENCRYPT_MODE, key, ips); 226 227 String secret = "secret string"; 228 SealedObject so = new SealedObject(secret, cipher); 229 230 cipher.init(Cipher.DECRYPT_MODE, key, ips); 231 assertEquals("The returned object does not equals to the " 232 + "original object.", secret, so.getObject(cipher)); 233 234 try { 235 so.getObject((Cipher)null); 236 fail("NullPointerException expected"); 237 } catch (NullPointerException e) { 238 //expected 239 } 240 } 241 242 /** 243 * getObject(Key key, String provider) method testing. Tests if the proper 244 * exception is thrown in the case of incorrect input parameters and if the 245 * object sealed with encryption algorithm can be retrieved by specifying 246 * the cryptographic key and provider name. 247 */ 248 public void testGetObject3() throws Exception { 249 try { 250 new SealedObject("secret string", new NullCipher()).getObject( 251 new SecretKeySpec(new byte[] {0, 0, 0}, "algorithm"), null); 252 fail("IllegalArgumentException should be thrown in the case of " 253 + "null provider."); 254 } catch (IllegalArgumentException e) { 255 } 256 257 try { 258 new SealedObject("secret string", new NullCipher()).getObject( 259 new SecretKeySpec(new byte[] {0, 0, 0}, "algorithm"), ""); 260 fail("IllegalArgumentException should be thrown in the case of " 261 + "empty provider."); 262 } catch (IllegalArgumentException e) { 263 } 264 265 KeyGenerator kg = KeyGenerator.getInstance("DES"); 266 Key key = kg.generateKey(); 267 268 Cipher cipher = Cipher.getInstance("DES"); 269 String provider = cipher.getProvider().getName(); 270 cipher.init(Cipher.ENCRYPT_MODE, key); 271 272 String secret = "secret string"; 273 SealedObject so = new SealedObject(secret, cipher); 274 275 cipher.init(Cipher.DECRYPT_MODE, key); 276 assertEquals("The returned object does not equals to the " 277 + "original object.", secret, so.getObject(key, provider)); 278 279 kg = KeyGenerator.getInstance("DESede"); 280 key = kg.generateKey(); 281 282 try { 283 so.getObject(key, provider); 284 fail("InvalidKeyException expected"); 285 } catch (InvalidKeyException e) { 286 //expected 287 } 288 289 try { 290 so.getObject(key, "Wrong provider name"); 291 fail("NoSuchProviderException expected"); 292 } catch (NoSuchProviderException e) { 293 //expected 294 } 295 } 296 297 // http://code.google.com/p/android/issues/detail?id=4834 298 public void testDeserialization() throws Exception { 299 // (Boilerplate so we can create SealedObject instances.) 300 KeyGenerator kg = KeyGenerator.getInstance("DES"); 301 Key key = kg.generateKey(); 302 Cipher cipher = Cipher.getInstance("DES"); 303 cipher.init(Cipher.ENCRYPT_MODE, key); 304 305 // Incorrect use of readUnshared meant you couldn't have two SealedObjects 306 // with the same algorithm or parameters algorithm... 307 ArrayList<SealedObject> sealedObjects = new ArrayList<SealedObject>(); 308 for (int i = 0; i < 10; ++i) { 309 sealedObjects.add(new SealedObject("hello", cipher)); 310 } 311 String serializedForm = SerializationTester.serializeHex(sealedObjects); 312 313 // ...so this would throw "java.io.InvalidObjectException: Unshared read of back reference". 314 SerializationTester.deserializeHex(serializedForm); 315 } 316 } 317