source: contrib/MailArchiver/sources/vendor/mime4j/apache-mime4j-0.7-SNAPSHOT-20110327.010440-17/storage/src/main/java/org/apache/james/mime4j/storage/CipherStorageProvider.java @ 6785

Revision 6785, 6.3 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2946 - Liberado codigo do MailArchiver?. Documentação na subpasta DOCS.

Line 
1/****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one   *
3 * or more contributor license agreements.  See the NOTICE file *
4 * distributed with this work for additional information        *
5 * regarding copyright ownership.  The ASF licenses this file   *
6 * to you under the Apache License, Version 2.0 (the            *
7 * "License"); you may not use this file except in compliance   *
8 * with the License.  You may obtain a copy of the License at   *
9 *                                                              *
10 *   http://www.apache.org/licenses/LICENSE-2.0                 *
11 *                                                              *
12 * Unless required by applicable law or agreed to in writing,   *
13 * software distributed under the License is distributed on an  *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15 * KIND, either express or implied.  See the License for the    *
16 * specific language governing permissions and limitations      *
17 * under the License.                                           *
18 ****************************************************************/
19
20package org.apache.james.mime4j.storage;
21
22import java.io.IOException;
23import java.io.InputStream;
24import java.security.GeneralSecurityException;
25import java.security.NoSuchAlgorithmException;
26
27import javax.crypto.Cipher;
28import javax.crypto.CipherInputStream;
29import javax.crypto.CipherOutputStream;
30import javax.crypto.KeyGenerator;
31import javax.crypto.spec.SecretKeySpec;
32
33/**
34 * A {@link StorageProvider} that transparently scrambles and unscrambles the
35 * data stored by another <code>StorageProvider</code>.
36 *
37 * <p>
38 * Example usage:
39 *
40 * <pre>
41 * StorageProvider mistrusted = new TempFileStorageProvider();
42 * StorageProvider enciphered = new CipherStorageProvider(mistrusted);
43 * StorageProvider provider = new ThresholdStorageProvider(enciphered);
44 * DefaultStorageProvider.setInstance(provider);
45 * </pre>
46 */
47public class CipherStorageProvider extends AbstractStorageProvider {
48
49    private final StorageProvider backend;
50    private final String algorithm;
51    private final KeyGenerator keygen;
52
53    /**
54     * Creates a new <code>CipherStorageProvider</code> for the given back-end
55     * using the Blowfish cipher algorithm.
56     *
57     * @param backend
58     *            back-end storage strategy to encrypt.
59     */
60    public CipherStorageProvider(StorageProvider backend) {
61        this(backend, "Blowfish");
62    }
63
64    /**
65     * Creates a new <code>CipherStorageProvider</code> for the given back-end
66     * and cipher algorithm.
67     *
68     * @param backend
69     *            back-end storage strategy to encrypt.
70     * @param algorithm
71     *            the name of the symmetric block cipher algorithm such as
72     *            "Blowfish", "AES" or "RC2".
73     */
74    public CipherStorageProvider(StorageProvider backend, String algorithm) {
75        if (backend == null)
76            throw new IllegalArgumentException();
77
78        try {
79            this.backend = backend;
80            this.algorithm = algorithm;
81            this.keygen = KeyGenerator.getInstance(algorithm);
82        } catch (NoSuchAlgorithmException e) {
83            throw new IllegalArgumentException(e);
84        }
85    }
86
87    public StorageOutputStream createStorageOutputStream() throws IOException {
88        SecretKeySpec skeySpec = getSecretKeySpec();
89
90        return new CipherStorageOutputStream(backend
91                .createStorageOutputStream(), algorithm, skeySpec);
92    }
93
94    private SecretKeySpec getSecretKeySpec() {
95        byte[] raw = keygen.generateKey().getEncoded();
96        return new SecretKeySpec(raw, algorithm);
97    }
98
99    private static final class CipherStorageOutputStream extends
100            StorageOutputStream {
101        private final StorageOutputStream storageOut;
102        private final String algorithm;
103        private final SecretKeySpec skeySpec;
104        private final CipherOutputStream cipherOut;
105
106        public CipherStorageOutputStream(StorageOutputStream out,
107                String algorithm, SecretKeySpec skeySpec) throws IOException {
108            try {
109                this.storageOut = out;
110                this.algorithm = algorithm;
111                this.skeySpec = skeySpec;
112
113                Cipher cipher = Cipher.getInstance(algorithm);
114                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
115
116                this.cipherOut = new CipherOutputStream(out, cipher);
117            } catch (GeneralSecurityException e) {
118                throw (IOException) new IOException().initCause(e);
119            }
120        }
121
122        @Override
123        public void close() throws IOException {
124            super.close();
125            cipherOut.close();
126        }
127
128        @Override
129        protected void write0(byte[] buffer, int offset, int length)
130                throws IOException {
131            cipherOut.write(buffer, offset, length);
132        }
133
134        @Override
135        protected Storage toStorage0() throws IOException {
136            // cipherOut has already been closed because toStorage calls close
137            Storage encrypted = storageOut.toStorage();
138            return new CipherStorage(encrypted, algorithm, skeySpec);
139        }
140    }
141
142    private static final class CipherStorage implements Storage {
143        private Storage encrypted;
144        private final String algorithm;
145        private final SecretKeySpec skeySpec;
146
147        public CipherStorage(Storage encrypted, String algorithm,
148                SecretKeySpec skeySpec) {
149            this.encrypted = encrypted;
150            this.algorithm = algorithm;
151            this.skeySpec = skeySpec;
152        }
153
154        public void delete() {
155            if (encrypted != null) {
156                encrypted.delete();
157                encrypted = null;
158            }
159        }
160
161        public InputStream getInputStream() throws IOException {
162            if (encrypted == null)
163                throw new IllegalStateException("storage has been deleted");
164
165            try {
166                Cipher cipher = Cipher.getInstance(algorithm);
167                cipher.init(Cipher.DECRYPT_MODE, skeySpec);
168
169                InputStream in = encrypted.getInputStream();
170                return new CipherInputStream(in, cipher);
171            } catch (GeneralSecurityException e) {
172                throw (IOException) new IOException().initCause(e);
173            }
174        }
175    }
176
177}
Note: See TracBrowser for help on using the repository browser.