Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
CipherService |
|
| 1.0;1 |
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 | package org.apache.shiro.crypto; | |
20 | ||
21 | import org.apache.shiro.util.ByteSource; | |
22 | ||
23 | import java.io.InputStream; | |
24 | import java.io.OutputStream; | |
25 | ||
26 | /** | |
27 | * A {@code CipherService} uses a cryptographic algorithm called a | |
28 | * <a href="http://en.wikipedia.org/wiki/Cipher">Cipher</a> to convert an original input source using a {@code key} to | |
29 | * an uninterpretable format. The resulting encrypted output is only able to be converted back to original form with | |
30 | * a {@code key} as well. {@code CipherService}s can perform both encryption and decryption. | |
31 | * <h2>Cipher Basics</h2> | |
32 | * For what is known as <em>Symmetric</em> {@code Cipher}s, the {@code Key} used to encrypt the source is the same | |
33 | * as (or trivially similar to) the {@code Key} used to decrypt it. | |
34 | * <p/> | |
35 | * For <em>Asymmetric</em> {@code Cipher}s, the encryption {@code Key} is not the same as the decryption {@code Key}. | |
36 | * The most common type of Asymmetric Ciphers are based on what is called public/private key pairs: | |
37 | * <p/> | |
38 | * A <em>private</em> key is known only to a single party, and as its name implies, is supposed be kept very private | |
39 | * and secure. A <em>public</em> key that is associated with the private key can be disseminated freely to anyone. | |
40 | * Then data encrypted by the public key can only be decrypted by the private key and vice versa, but neither party | |
41 | * need share their private key with anyone else. By not sharing a private key, you can guarantee no 3rd party can | |
42 | * intercept the key and therefore use it to decrypt a message. | |
43 | * <p/> | |
44 | * This asymmetric key technology was created as a | |
45 | * more secure alternative to symmetric ciphers that sometimes suffer from man-in-the-middle attacks since, for | |
46 | * data shared between two parties, the same Key must also be shared and may be compromised. | |
47 | * <p/> | |
48 | * Note that a symmetric cipher is perfectly fine to use if you just want to encode data in a format no one else | |
49 | * can understand and you never give away the key. Shiro uses a symmetric cipher when creating certain | |
50 | * HTTP Cookies for example - because it is often undesirable to have user's identity stored in a plain-text cookie, | |
51 | * that identity can be converted via a symmetric cipher. Since the the same exact Shiro application will receive | |
52 | * the cookie, it can decrypt it via the same {@code Key} and there is no potential for discovery since that Key | |
53 | * is never shared with anyone. | |
54 | * <h2>{@code CipherService}s vs JDK {@link javax.crypto.Cipher Cipher}s</h2> | |
55 | * Shiro {@code CipherService}s essentially do the same things as JDK {@link javax.crypto.Cipher Cipher}s, but in | |
56 | * simpler and easier-to-use ways for most application developers. When thinking about encrypting and decrypting data | |
57 | * in an application, most app developers want what a {@code CipherService} provides, rather than having to manage the | |
58 | * lower-level intricacies of the JDK's {@code Cipher} API. Here are a few reasons why most people prefer | |
59 | * {@code CipherService}s: | |
60 | * <ul> | |
61 | * <li><b>Stateless Methods</b> - {@code CipherService} method calls do not retain state between method invocations. | |
62 | * JDK {@code Cipher} instances do retain state across invocations, requiring its end-users to manage the instance | |
63 | * and its state themselves.</li> | |
64 | * <li><b>Thread Safety</b> - {@code CipherService} instances are thread-safe inherently because no state is | |
65 | * retained across method invocations. JDK {@code Cipher} instances retain state and cannot be used by multiple | |
66 | * threads concurrently.</li> | |
67 | * <li><b>Single Operation</b> - {@code CipherService} method calls are single operation methods: encryption or | |
68 | * decryption in their entirety are done as a single method call. This is ideal for the large majority of developer | |
69 | * needs where you have something unencrypted and just want it decrypted (or vice versa) in a single method call. In | |
70 | * contrast, JDK {@code Cipher} instances can support encrypting/decrypting data in chunks over time (because it | |
71 | * retains state), but this often introduces API clutter and confusion for most application developers.</li> | |
72 | * <li><b>Type Safe</b> - There are {@code CipherService} implementations for different Cipher algorithms | |
73 | * ({@code AesCipherService}, {@code BlowfishCipherService}, etc). There is only one JDK {@code Cipher} class to | |
74 | * represent all cipher algorithms/instances. | |
75 | * <li><b>Simple Construction</b> - Because {@code CipherService} instances are type-safe, instantiating and using | |
76 | * one is often as simple as calling the default constructor, for example, <code>new AesCipherService();</code>. The | |
77 | * JDK {@code Cipher} class however requires using a procedural factory method with String arguments to indicate how | |
78 | * the instance should be created. The String arguments themselves are somewhat cryptic and hard to | |
79 | * understand unless you're a security expert. Shiro hides these details from you, but allows you to configure them | |
80 | * if you want.</li> | |
81 | * </ul> | |
82 | * | |
83 | * @see BlowfishCipherService | |
84 | * @see AesCipherService | |
85 | * @since 1.0 | |
86 | */ | |
87 | public interface CipherService { | |
88 | ||
89 | /** | |
90 | * Decrypts encrypted data via the specified cipher key and returns the original (pre-encrypted) data. | |
91 | * Note that the key must be in a format understood by the CipherService implementation. | |
92 | * | |
93 | * @param encrypted the previously encrypted data to decrypt | |
94 | * @param decryptionKey the cipher key used during decryption. | |
95 | * @return a byte source representing the original form of the specified encrypted data. | |
96 | * @throws CryptoException if there is an error during decryption | |
97 | */ | |
98 | ByteSource decrypt(byte[] encrypted, byte[] decryptionKey) throws CryptoException; | |
99 | ||
100 | /** | |
101 | * Receives encrypted data from the given {@code InputStream}, decrypts it, and sends the resulting decrypted data | |
102 | * to the given {@code OutputStream}. | |
103 | * <p/> | |
104 | * <b>NOTE:</b> This method <em>does NOT</em> flush or close either stream prior to returning - the caller must | |
105 | * do so when they are finished with the streams. For example: | |
106 | * <pre> | |
107 | * try { | |
108 | * InputStream in = ... | |
109 | * OutputStream out = ... | |
110 | * cipherService.decrypt(in, out, decryptionKey); | |
111 | * } finally { | |
112 | * if (in != null) { | |
113 | * try { | |
114 | * in.close(); | |
115 | * } catch (IOException ioe1) { ... log, trigger event, etc } | |
116 | * } | |
117 | * if (out != null) { | |
118 | * try { | |
119 | * out.close(); | |
120 | * } catch (IOException ioe2) { ... log, trigger event, etc } | |
121 | * } | |
122 | * } | |
123 | * </pre> | |
124 | * | |
125 | * @param in the stream supplying the data to decrypt | |
126 | * @param out the stream to send the decrypted data | |
127 | * @param decryptionKey the cipher key to use for decryption | |
128 | * @throws CryptoException if there is any problem during decryption. | |
129 | */ | |
130 | void decrypt(InputStream in, OutputStream out, byte[] decryptionKey) throws CryptoException; | |
131 | ||
132 | /** | |
133 | * Encrypts data via the specified cipher key. Note that the key must be in a format understood by | |
134 | * the {@code CipherService} implementation. | |
135 | * | |
136 | * @param raw the data to encrypt | |
137 | * @param encryptionKey the cipher key used during encryption. | |
138 | * @return a byte source with the encrypted representation of the specified raw data. | |
139 | * @throws CryptoException if there is an error during encryption | |
140 | */ | |
141 | ByteSource encrypt(byte[] raw, byte[] encryptionKey) throws CryptoException; | |
142 | ||
143 | /** | |
144 | * Receives the data from the given {@code InputStream}, encrypts it, and sends the resulting encrypted data to the | |
145 | * given {@code OutputStream}. | |
146 | * <p/> | |
147 | * <b>NOTE:</b> This method <em>does NOT</em> flush or close either stream prior to returning - the caller must | |
148 | * do so when they are finished with the streams. For example: | |
149 | * <pre> | |
150 | * try { | |
151 | * InputStream in = ... | |
152 | * OutputStream out = ... | |
153 | * cipherService.encrypt(in, out, encryptionKey); | |
154 | * } finally { | |
155 | * if (in != null) { | |
156 | * try { | |
157 | * in.close(); | |
158 | * } catch (IOException ioe1) { ... log, trigger event, etc } | |
159 | * } | |
160 | * if (out != null) { | |
161 | * try { | |
162 | * out.close(); | |
163 | * } catch (IOException ioe2) { ... log, trigger event, etc } | |
164 | * } | |
165 | * } | |
166 | * </pre> | |
167 | * | |
168 | * @param in the stream supplying the data to encrypt | |
169 | * @param out the stream to send the encrypted data | |
170 | * @param encryptionKey the cipher key to use for encryption | |
171 | * @throws CryptoException if there is any problem during encryption. | |
172 | */ | |
173 | void encrypt(InputStream in, OutputStream out, byte[] encryptionKey) throws CryptoException; | |
174 | ||
175 | } |