Coverage Report - org.apache.shiro.crypto.CipherService
 
Classes in this File Line Coverage Branch Coverage Complexity
CipherService
N/A
N/A
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  
 }