1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  this work for additional information regarding copyright ownership.
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  the License.  You may obtain a copy of the License at
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  See the License for the specific language governing permissions and
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  limitations under the License.
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage javax.crypto;
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ByteArrayInputStream;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ByteArrayOutputStream;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ObjectInputStream;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ObjectOutputStream;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.Serializable;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.AlgorithmParameters;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.InvalidAlgorithmParameterException;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.InvalidKeyException;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.Key;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.NoSuchAlgorithmException;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.NoSuchProviderException;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.crypto.IllegalBlockSizeException;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.crypto.NoSuchPaddingException;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.crypto.internal.nls.Messages;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A {@code SealedObject} is a wrapper around a {@code serializable} object
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instance and encrypts it using a cryptographic cipher.
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p>
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since a {@code SealedObject} instance is a serializable object itself it can
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * either be stored or transmitted over an insecure channel.
438207f1e8dbc63916f238f81dc46567c55090e95bJesse Wilson * <p>
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The wrapped object can later be decrypted (unsealed) using the corresponding
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * key and then be deserialized to retrieve the original object.The sealed
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * object itself keeps track of the cipher and corresponding parameters.
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class SealedObject implements Serializable {
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final long serialVersionUID = 4482838265551344752L;
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The {@link AlgorithmParameters} in encoded format.
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] encodedParams;
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] encryptedContent;
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private String sealAlg;
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private String paramsAlg;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void readObject(ObjectInputStream s)
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throws IOException, ClassNotFoundException {
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        encodedParams = (byte []) s.readUnshared();
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        encryptedContent = (byte []) s.readUnshared();
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sealAlg = (String) s.readUnshared();
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        paramsAlg = (String) s.readUnshared();
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Creates a new {@code SealedObject} instance wrapping the specified object
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and sealing it using the specified cipher.
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The cipher must be fully initialized.
738207f1e8dbc63916f238f81dc46567c55090e95bJesse Wilson     *
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param object
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the object to seal, can be {@code null}.
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the cipher to encrypt the object.
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the serialization fails.
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IllegalBlockSizeException
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the specified cipher is a block cipher and the length of
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             the serialized data is not a multiple of the ciphers block
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             size.
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws NullPointerException
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the cipher is {@code null}.
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public SealedObject(Serializable object, Cipher c)
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throws IOException, IllegalBlockSizeException {
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c == null) {
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException(Messages.getString("crypto.13")); //$NON-NLS-1$
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ByteArrayOutputStream bos = new ByteArrayOutputStream();
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ObjectOutputStream oos = new ObjectOutputStream(bos);
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oos.writeObject(object);
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            oos.flush();
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            AlgorithmParameters ap = c.getParameters();
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.encodedParams = (ap == null) ? null : ap.getEncoded();
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.paramsAlg = (ap == null) ? null : ap.getAlgorithm();
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.sealAlg = c.getAlgorithm();
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.encryptedContent = c.doFinal(bos.toByteArray());
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (BadPaddingException e) {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should be never thrown because the cipher
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should be initialized for encryption
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IOException(e.toString());
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Creates a new {@code SealedObject} instance by copying the data from
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the specified object.
1128207f1e8dbc63916f238f81dc46567c55090e95bJesse Wilson     *
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param so
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the object to copy.
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected SealedObject(SealedObject so) {
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (so == null) {
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException(Messages.getString("crypto.14")); //$NON-NLS-1$
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.encryptedContent = so.encryptedContent;
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.encodedParams = so.encodedParams;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.sealAlg = so.sealAlg;
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.paramsAlg = so.paramsAlg;
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the algorithm this object was sealed with.
1288207f1e8dbc63916f238f81dc46567c55090e95bJesse Wilson     *
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the algorithm this object was sealed with.
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final String getAlgorithm() {
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sealAlg;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the wrapped object, decrypting it using the specified key.
1378207f1e8dbc63916f238f81dc46567c55090e95bJesse Wilson     *
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param key
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the key to decrypt the data with.
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the encapsulated object.
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if deserialization fails.
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws ClassNotFoundException
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if deserialization fails.
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws NoSuchAlgorithmException
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the algorithm to decrypt the data is not available.
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws InvalidKeyException
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the specified key cannot be used to decrypt the data.
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final Object getObject(Key key)
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throws IOException, ClassNotFoundException,
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       NoSuchAlgorithmException, InvalidKeyException {
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // BEGIN android-added
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (key == null) {
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new InvalidKeyException(
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    Messages.getString("crypto.05"));
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // END android-added
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Cipher cipher = Cipher.getInstance(sealAlg);
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((paramsAlg != null) && (paramsAlg.length() != 0)) {
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                AlgorithmParameters params =
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    AlgorithmParameters.getInstance(paramsAlg);
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                params.init(encodedParams);
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cipher.init(Cipher.DECRYPT_MODE, key, params);
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cipher.init(Cipher.DECRYPT_MODE, key);
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            byte[] serialized = cipher.doFinal(encryptedContent);
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ObjectInputStream ois =
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    new ObjectInputStream(
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            new ByteArrayInputStream(serialized));
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return ois.readObject();
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (NoSuchPaddingException e)  {
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should not be thrown because cipher text was made
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // with existing padding
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (InvalidAlgorithmParameterException e) {
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should not be thrown because cipher text was made
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // with correct algorithm parameters
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IllegalBlockSizeException e) {
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should not be thrown because the cipher text
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // was correctly made
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (BadPaddingException e) {
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should not be thrown because the cipher text
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // was correctly made
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IllegalStateException  e) {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should never be thrown because cipher is initialized
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the wrapped object, decrypting it using the specified
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * cipher.
1998207f1e8dbc63916f238f81dc46567c55090e95bJesse Wilson     *
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param c
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the cipher to decrypt the data.
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the encapsulated object.
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if deserialization fails.
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws ClassNotFoundException
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if deserialization fails.
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IllegalBlockSizeException
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the specified cipher is a block cipher and the length of
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             the serialized data is not a multiple of the ciphers block
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             size.
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws BadPaddingException
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the padding of the data does not match the padding scheme.
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final Object getObject(Cipher c)
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throws IOException, ClassNotFoundException,
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       IllegalBlockSizeException, BadPaddingException {
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c == null) {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException(Messages.getString("crypto.13")); //$NON-NLS-1$
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] serialized = c.doFinal(encryptedContent);
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ObjectInputStream ois =
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                new ObjectInputStream(
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        new ByteArrayInputStream(serialized));
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ois.readObject();
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the wrapped object, decrypting it using the specified key. The
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * specified provider is used to retrieve the cipher algorithm.
2308207f1e8dbc63916f238f81dc46567c55090e95bJesse Wilson     *
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param key
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the key to decrypt the data.
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param provider
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the provider that provides the cipher algorithm.
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the encapsulated object.
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if deserialization fails.
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws ClassNotFoundException
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if deserialization fails.
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws NoSuchAlgorithmException
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the algorithm used to decrypt the data is not available.
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws NoSuchProviderException
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the specified provider is not available.
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws InvalidKeyException
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the specified key cannot be used to decrypt the data.
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final Object getObject(Key key, String provider)
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throws IOException, ClassNotFoundException,
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       NoSuchAlgorithmException, NoSuchProviderException,
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       InvalidKeyException {
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((provider == null) || (provider.length() == 0)) {
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException(
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    Messages.getString("crypto.15")); //$NON-NLS-1$
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Cipher cipher = Cipher.getInstance(sealAlg, provider);
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((paramsAlg != null) && (paramsAlg.length() != 0)) {
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                AlgorithmParameters params =
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    AlgorithmParameters.getInstance(paramsAlg);
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                params.init(encodedParams);
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cipher.init(Cipher.DECRYPT_MODE, key, params);
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cipher.init(Cipher.DECRYPT_MODE, key);
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            byte[] serialized = cipher.doFinal(encryptedContent);
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ObjectInputStream ois =
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    new ObjectInputStream(
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            new ByteArrayInputStream(serialized));
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return ois.readObject();
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (NoSuchPaddingException e)  {
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should not be thrown because cipher text was made
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // with existing padding
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (InvalidAlgorithmParameterException e) {
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should not be thrown because cipher text was made
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // with correct algorithm parameters
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IllegalBlockSizeException e) {
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should not be thrown because the cipher text
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // was correctly made
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (BadPaddingException e) {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should not be thrown because the cipher text
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // was correctly made
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IllegalStateException  e) {
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // should never be thrown because cipher is initialized
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NoSuchAlgorithmException(e.toString());
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
293