001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.shiro.crypto.cipher;
020
021import org.apache.shiro.crypto.CryptoException;
022import org.apache.shiro.lang.util.ByteSource;
023
024import java.io.InputStream;
025import java.io.OutputStream;
026
027/**
028 * A {@code CipherService} uses a cryptographic algorithm called a
029 * <a href="http://en.wikipedia.org/wiki/Cipher">Cipher</a> to convert an original input source using a {@code key} to
030 * an uninterpretable format.  The resulting encrypted output is only able to be converted back to original form with
031 * a {@code key} as well.  {@code CipherService}s can perform both encryption and decryption.
032 * <h2>Cipher Basics</h2>
033 * For what is known as <em>Symmetric</em> {@code Cipher}s, the {@code Key} used to encrypt the source is the same
034 * as (or trivially similar to) the {@code Key} used to decrypt it.
035 * <p/>
036 * For <em>Asymmetric</em> {@code Cipher}s, the encryption {@code Key} is not the same as the decryption {@code Key}.
037 * The most common type of Asymmetric Ciphers are based on what is called public/private key pairs:
038 * <p/>
039 * A <em>private</em> key is known only to a single party, and as its name implies, is supposed be kept very private
040 * and secure.  A <em>public</em> key that is associated with the private key can be disseminated freely to anyone.
041 * Then data encrypted by the public key can only be decrypted by the private key and vice versa, but neither party
042 * need share their private key with anyone else.  By not sharing a private key, you can guarantee no 3rd party can
043 * intercept the key and therefore use it to decrypt a message.
044 * <p/>
045 * This asymmetric key technology was created as a
046 * more secure alternative to symmetric ciphers that sometimes suffer from man-in-the-middle attacks since, for
047 * data shared between two parties, the same Key must also be shared and may be compromised.
048 * <p/>
049 * Note that a symmetric cipher is perfectly fine to use if you just want to encode data in a format no one else
050 * can understand and you never give away the key.  Shiro uses a symmetric cipher when creating certain
051 * HTTP Cookies for example - because it is often undesirable to have user's identity stored in a plain-text cookie,
052 * that identity can be converted via a symmetric cipher.  Since the the same exact Shiro application will receive
053 * the cookie, it can decrypt it via the same {@code Key} and there is no potential for discovery since that Key
054 * is never shared with anyone.
055 * <h2>{@code CipherService}s vs JDK {@link javax.crypto.Cipher Cipher}s</h2>
056 * Shiro {@code CipherService}s essentially do the same things as JDK {@link javax.crypto.Cipher Cipher}s, but in
057 * simpler and easier-to-use ways for most application developers.  When thinking about encrypting and decrypting data
058 * in an application, most app developers want what a {@code CipherService} provides, rather than having to manage the
059 * lower-level intricacies of the JDK's {@code Cipher} API.  Here are a few reasons why most people prefer
060 * {@code CipherService}s:
061 * <ul>
062 * <li><b>Stateless Methods</b> - {@code CipherService} method calls do not retain state between method invocations.
063 * JDK {@code Cipher} instances do retain state across invocations, requiring its end-users to manage the instance
064 * and its state themselves.</li>
065 * <li><b>Thread Safety</b> - {@code CipherService} instances are thread-safe inherently because no state is
066 * retained across method invocations.  JDK {@code Cipher} instances retain state and cannot be used by multiple
067 * threads concurrently.</li>
068 * <li><b>Single Operation</b> - {@code CipherService} method calls are single operation methods: encryption or
069 * decryption in their entirety are done as a single method call.  This is ideal for the large majority of developer
070 * needs where you have something unencrypted and just want it decrypted (or vice versa) in a single method call.  In
071 * contrast, JDK {@code Cipher} instances can support encrypting/decrypting data in chunks over time (because it
072 * retains state), but this often introduces API clutter and confusion for most application developers.</li>
073 * <li><b>Type Safe</b> - There are {@code CipherService} implementations for different Cipher algorithms
074 * ({@code AesCipherService}, {@code BlowfishCipherService}, etc.).  There is only one JDK {@code Cipher} class to
075 * represent all cipher algorithms/instances.
076 * <li><b>Simple Construction</b> - Because {@code CipherService} instances are type-safe, instantiating and using
077 * one is often as simple as calling the default constructor, for example, <code>new AesCipherService();</code>.  The
078 * JDK {@code Cipher} class however requires using a procedural factory method with String arguments to indicate how
079 * the instance should be created.  The String arguments themselves are somewhat cryptic and hard to
080 * understand unless you're a security expert.  Shiro hides these details from you, but allows you to configure them
081 * if you want.</li>
082 * </ul>
083 *
084 * @see BlowfishCipherService
085 * @see AesCipherService
086 * @since 1.0
087 */
088public interface CipherService {
089
090    /**
091     * Decrypts encrypted data via the specified cipher key and returns the original (pre-encrypted) data.
092     * Note that the key must be in a format understood by the CipherService implementation.
093     *
094     * @param encrypted     the previously encrypted data to decrypt
095     * @param decryptionKey the cipher key used during decryption.
096     * @return a byte source representing the original form of the specified encrypted data.
097     * @throws CryptoException if there is an error during decryption
098     */
099    ByteSourceBroker decrypt(byte[] encrypted, byte[] decryptionKey) throws CryptoException;
100
101    /**
102     * Receives encrypted data from the given {@code InputStream}, decrypts it, and sends the resulting decrypted data
103     * to the given {@code OutputStream}.
104     * <p/>
105     * <b>NOTE:</b> This method <em>does NOT</em> flush or close either stream prior to returning - the caller must
106     * do so when they are finished with the streams.  For example:
107     * <pre>
108     * try {
109     *     InputStream in = ...
110     *     OutputStream out = ...
111     *     cipherService.decrypt(in, out, decryptionKey);
112     * } finally {
113     *     if (in != null) {
114     *         try {
115     *             in.close();
116     *         } catch (IOException ioe1) { ... log, trigger event, etc. }
117     *     }
118     *     if (out != null) {
119     *         try {
120     *             out.close();
121     *         } catch (IOException ioe2) { ... log, trigger event, etc. }
122     *     }
123     * }
124     * </pre>
125     *
126     * @param in            the stream supplying the data to decrypt
127     * @param out           the stream to send the decrypted data
128     * @param decryptionKey the cipher key to use for decryption
129     * @throws CryptoException if there is any problem during decryption.
130     */
131    void decrypt(InputStream in, OutputStream out, byte[] decryptionKey) throws CryptoException;
132
133    /**
134     * Encrypts data via the specified cipher key.  Note that the key must be in a format understood by
135     * the {@code CipherService} implementation.
136     *
137     * @param raw           the data to encrypt
138     * @param encryptionKey the cipher key used during encryption.
139     * @return a byte source with the encrypted representation of the specified raw data.
140     * @throws CryptoException if there is an error during encryption
141     */
142    ByteSource encrypt(byte[] raw, byte[] encryptionKey) throws CryptoException;
143
144    /**
145     * Receives the data from the given {@code InputStream}, encrypts it, and sends the resulting encrypted data to the
146     * given {@code OutputStream}.
147     * <p/>
148     * <b>NOTE:</b> This method <em>does NOT</em> flush or close either stream prior to returning - the caller must
149     * do so when they are finished with the streams.  For example:
150     * <pre>
151     * try {
152     *     InputStream in = ...
153     *     OutputStream out = ...
154     *     cipherService.encrypt(in, out, encryptionKey);
155     * } finally {
156     *     if (in != null) {
157     *         try {
158     *             in.close();
159     *         } catch (IOException ioe1) { ... log, trigger event, etc. }
160     *     }
161     *     if (out != null) {
162     *         try {
163     *             out.close();
164     *         } catch (IOException ioe2) { ... log, trigger event, etc. }
165     *     }
166     * }
167     * </pre>
168     *
169     * @param in            the stream supplying the data to encrypt
170     * @param out           the stream to send the encrypted data
171     * @param encryptionKey the cipher key to use for encryption
172     * @throws CryptoException if there is any problem during encryption.
173     */
174    void encrypt(InputStream in, OutputStream out, byte[] encryptionKey) throws CryptoException;
175
176}