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 module hunt.shiro.crypto.CipherService;
20 
21 import hunt.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 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 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);
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 is null) {
113      *         try {
114      *             in.close();
115      *         } catch (IOException ioe1) { ... log, trigger event, etc }
116      *     }
117      *     if (out is 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);
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);
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 is null) {
156      *         try {
157      *             in.close();
158      *         } catch (IOException ioe1) { ... log, trigger event, etc }
159      *     }
160      *     if (out is 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);
174 
175 }