SealedObject.java revision 2ad60cfc28e14ee8f0bb038720836a4696c478ad
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  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,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19* @author Alexander Y. Kleymenov
20* @version $Revision$
21*/
22
23package javax.crypto;
24
25import java.io.ByteArrayInputStream;
26import java.io.ByteArrayOutputStream;
27import java.io.IOException;
28import java.io.ObjectInputStream;
29import java.io.ObjectOutputStream;
30import java.io.Serializable;
31import java.security.AlgorithmParameters;
32import java.security.InvalidAlgorithmParameterException;
33import java.security.InvalidKeyException;
34import java.security.Key;
35import java.security.NoSuchAlgorithmException;
36import java.security.NoSuchProviderException;
37import javax.crypto.IllegalBlockSizeException;
38import javax.crypto.NoSuchPaddingException;
39
40import org.apache.harmony.crypto.internal.nls.Messages;
41
42/**
43 * @com.intel.drl.spec_ref
44 */
45public class SealedObject implements Serializable {
46
47    // the value of this field was derived by using serialver utility
48    /**
49     * @com.intel.drl.spec_ref
50     */
51    private static final long serialVersionUID = 4482838265551344752L;
52
53    /**
54     * @com.intel.drl.spec_ref
55     */
56    protected byte[] encodedParams;
57    private byte[] encryptedContent;
58    private String sealAlg;
59    private String paramsAlg;
60
61    private void readObject(ObjectInputStream s)
62                throws IOException, ClassNotFoundException {
63        encodedParams = (byte []) s.readUnshared();
64        encryptedContent = (byte []) s.readUnshared();
65        sealAlg = (String) s.readUnshared();
66        paramsAlg = (String) s.readUnshared();
67    }
68
69    /**
70     * @com.intel.drl.spec_ref
71     */
72    public SealedObject(Serializable object, Cipher c)
73                throws IOException, IllegalBlockSizeException {
74        if (c == null) {
75            throw new NullPointerException(Messages.getString("crypto.13")); //$NON-NLS-1$
76        }
77        try {
78            ByteArrayOutputStream bos = new ByteArrayOutputStream();
79            ObjectOutputStream oos = new ObjectOutputStream(bos);
80            oos.writeObject(object);
81            oos.flush();
82            AlgorithmParameters ap = c.getParameters();
83            this.encodedParams = (ap == null) ? null : ap.getEncoded();
84            this.paramsAlg = (ap == null) ? null : ap.getAlgorithm();
85            this.sealAlg = c.getAlgorithm();
86            this.encryptedContent = c.doFinal(bos.toByteArray());
87        } catch (BadPaddingException e) {
88            // should be never thrown because the cipher
89            // should be initialized for encryption
90            throw new IOException(e.toString());
91        }
92    }
93
94    /**
95     * @com.intel.drl.spec_ref
96     */
97    protected SealedObject(SealedObject so) {
98        if (so == null) {
99            throw new NullPointerException(Messages.getString("crypto.14")); //$NON-NLS-1$
100        }
101        this.encryptedContent = so.encryptedContent;
102        this.encodedParams = so.encodedParams;
103        this.sealAlg = so.sealAlg;
104        this.paramsAlg = so.paramsAlg;
105    }
106
107    /**
108     * @com.intel.drl.spec_ref
109     */
110    public final String getAlgorithm() {
111        return sealAlg;
112    }
113
114    /**
115     * @com.intel.drl.spec_ref
116     */
117    public final Object getObject(Key key)
118                throws IOException, ClassNotFoundException,
119                       NoSuchAlgorithmException, InvalidKeyException {
120        try {
121            Cipher cipher = Cipher.getInstance(sealAlg);
122            if ((paramsAlg != null) && (paramsAlg.length() != 0)) {
123                AlgorithmParameters params =
124                    AlgorithmParameters.getInstance(paramsAlg);
125                params.init(encodedParams);
126                cipher.init(Cipher.DECRYPT_MODE, key, params);
127            } else {
128                cipher.init(Cipher.DECRYPT_MODE, key);
129            }
130            byte[] serialized = cipher.doFinal(encryptedContent);
131            ObjectInputStream ois =
132                    new ObjectInputStream(
133                            new ByteArrayInputStream(serialized));
134            return ois.readObject();
135        } catch (NoSuchPaddingException e)  {
136            // should not be thrown because cipher text was made
137            // with existing padding
138            throw new NoSuchAlgorithmException(e.toString());
139        } catch (InvalidAlgorithmParameterException e) {
140            // should not be thrown because cipher text was made
141            // with correct algorithm parameters
142            throw new NoSuchAlgorithmException(e.toString());
143        } catch (IllegalBlockSizeException e) {
144            // should not be thrown because the cipher text
145            // was correctly made
146            throw new NoSuchAlgorithmException(e.toString());
147        } catch (BadPaddingException e) {
148            // should not be thrown because the cipher text
149            // was correctly made
150            throw new NoSuchAlgorithmException(e.toString());
151        } catch (IllegalStateException  e) {
152            // should never be thrown because cipher is initialized
153            throw new NoSuchAlgorithmException(e.toString());
154        }
155    }
156
157    /**
158     * @com.intel.drl.spec_ref
159     */
160    public final Object getObject(Cipher c)
161                throws IOException, ClassNotFoundException,
162                       IllegalBlockSizeException, BadPaddingException {
163        if (c == null) {
164            throw new NullPointerException(Messages.getString("crypto.13")); //$NON-NLS-1$
165        }
166        byte[] serialized = c.doFinal(encryptedContent);
167        ObjectInputStream ois =
168                new ObjectInputStream(
169                        new ByteArrayInputStream(serialized));
170        return ois.readObject();
171    }
172
173    /**
174     * @com.intel.drl.spec_ref
175     */
176    public final Object getObject(Key key, String provider)
177                throws IOException, ClassNotFoundException,
178                       NoSuchAlgorithmException, NoSuchProviderException,
179                       InvalidKeyException {
180        if ((provider == null) || (provider.length() == 0)) {
181            throw new IllegalArgumentException(
182                    Messages.getString("crypto.15")); //$NON-NLS-1$
183        }
184        try {
185            Cipher cipher = Cipher.getInstance(sealAlg, provider);
186            if ((paramsAlg != null) && (paramsAlg.length() != 0)) {
187                AlgorithmParameters params =
188                    AlgorithmParameters.getInstance(paramsAlg);
189                params.init(encodedParams);
190                cipher.init(Cipher.DECRYPT_MODE, key, params);
191            } else {
192                cipher.init(Cipher.DECRYPT_MODE, key);
193            }
194            byte[] serialized = cipher.doFinal(encryptedContent);
195            ObjectInputStream ois =
196                    new ObjectInputStream(
197                            new ByteArrayInputStream(serialized));
198            return ois.readObject();
199        } catch (NoSuchPaddingException e)  {
200            // should not be thrown because cipher text was made
201            // with existing padding
202            throw new NoSuchAlgorithmException(e.toString());
203        } catch (InvalidAlgorithmParameterException e) {
204            // should not be thrown because cipher text was made
205            // with correct algorithm parameters
206            throw new NoSuchAlgorithmException(e.toString());
207        } catch (IllegalBlockSizeException e) {
208            // should not be thrown because the cipher text
209            // was correctly made
210            throw new NoSuchAlgorithmException(e.toString());
211        } catch (BadPaddingException e) {
212            // should not be thrown because the cipher text
213            // was correctly made
214            throw new NoSuchAlgorithmException(e.toString());
215        } catch (IllegalStateException  e) {
216            // should never be thrown because cipher is initialized
217            throw new NoSuchAlgorithmException(e.toString());
218        }
219    }
220}
221
222