Home | History | Annotate | Download | only in crypto
      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