public interface CipherService
CipherService
uses a cryptographic algorithm called a
Cipher to convert an original input source using a key
to
an uninterpretable format. The resulting encrypted output is only able to be converted back to original form with
a key
as well. CipherService
s can perform both encryption and decryption.
Cipher
s, the Key
used to encrypt the source is the same
as (or trivially similar to) the Key
used to decrypt it.
For Asymmetric Cipher
s, the encryption Key
is not the same as the decryption Key
.
The most common type of Asymmetric Ciphers are based on what is called public/private key pairs:
A private key is known only to a single party, and as its name implies, is supposed be kept very private
and secure. A public key that is associated with the private key can be disseminated freely to anyone.
Then data encrypted by the public key can only be decrypted by the private key and vice versa, but neither party
need share their private key with anyone else. By not sharing a private key, you can guarantee no 3rd party can
intercept the key and therefore use it to decrypt a message.
This asymmetric key technology was created as a
more secure alternative to symmetric ciphers that sometimes suffer from man-in-the-middle attacks since, for
data shared between two parties, the same Key must also be shared and may be compromised.
Note that a symmetric cipher is perfectly fine to use if you just want to encode data in a format no one else
can understand and you never give away the key. Shiro uses a symmetric cipher when creating certain
HTTP Cookies for example - because it is often undesirable to have user's identity stored in a plain-text cookie,
that identity can be converted via a symmetric cipher. Since the the same exact Shiro application will receive
the cookie, it can decrypt it via the same Key
and there is no potential for discovery since that Key
is never shared with anyone.
CipherService
s vs JDK Cipher
sCipherService
s essentially do the same things as JDK Cipher
s, but in
simpler and easier-to-use ways for most application developers. When thinking about encrypting and decrypting data
in an application, most app developers want what a CipherService
provides, rather than having to manage the
lower-level intricacies of the JDK's Cipher
API. Here are a few reasons why most people prefer
CipherService
s:
CipherService
method calls do not retain state between method invocations.
JDK Cipher
instances do retain state across invocations, requiring its end-users to manage the instance
and its state themselves.CipherService
instances are thread-safe inherently because no state is
retained across method invocations. JDK Cipher
instances retain state and cannot be used by multiple
threads concurrently.CipherService
method calls are single operation methods: encryption or
decryption in their entirety are done as a single method call. This is ideal for the large majority of developer
needs where you have something unencrypted and just want it decrypted (or vice versa) in a single method call. In
contrast, JDK Cipher
instances can support encrypting/decrypting data in chunks over time (because it
retains state), but this often introduces API clutter and confusion for most application developers.CipherService
implementations for different Cipher algorithms
(AesCipherService
, BlowfishCipherService
, etc). There is only one JDK Cipher
class to
represent all cipher algorithms/instances.
CipherService
instances are type-safe, instantiating and using
one is often as simple as calling the default constructor, for example, new AesCipherService();
. The
JDK Cipher
class however requires using a procedural factory method with String arguments to indicate how
the instance should be created. The String arguments themselves are somewhat cryptic and hard to
understand unless you're a security expert. Shiro hides these details from you, but allows you to configure them
if you want.BlowfishCipherService
,
AesCipherService
Modifier and Type | Method and Description |
---|---|
ByteSource |
decrypt(byte[] encrypted,
byte[] decryptionKey)
Decrypts encrypted data via the specified cipher key and returns the original (pre-encrypted) data.
|
void |
decrypt(InputStream in,
OutputStream out,
byte[] decryptionKey)
Receives encrypted data from the given
InputStream , decrypts it, and sends the resulting decrypted data
to the given OutputStream . |
ByteSource |
encrypt(byte[] raw,
byte[] encryptionKey)
Encrypts data via the specified cipher key.
|
void |
encrypt(InputStream in,
OutputStream out,
byte[] encryptionKey)
Receives the data from the given
InputStream , encrypts it, and sends the resulting encrypted data to the
given OutputStream . |
ByteSource decrypt(byte[] encrypted, byte[] decryptionKey) throws CryptoException
encrypted
- the previously encrypted data to decryptdecryptionKey
- the cipher key used during decryption.CryptoException
- if there is an error during decryptionvoid decrypt(InputStream in, OutputStream out, byte[] decryptionKey) throws CryptoException
InputStream
, decrypts it, and sends the resulting decrypted data
to the given OutputStream
.
NOTE: This method does NOT flush or close either stream prior to returning - the caller must
do so when they are finished with the streams. For example:
try { InputStream in = ... OutputStream out = ... cipherService.decrypt(in, out, decryptionKey); } finally { if (in != null) { try { in.close(); } catch (IOException ioe1) { ... log, trigger event, etc } } if (out != null) { try { out.close(); } catch (IOException ioe2) { ... log, trigger event, etc } } }
in
- the stream supplying the data to decryptout
- the stream to send the decrypted datadecryptionKey
- the cipher key to use for decryptionCryptoException
- if there is any problem during decryption.ByteSource encrypt(byte[] raw, byte[] encryptionKey) throws CryptoException
CipherService
implementation.raw
- the data to encryptencryptionKey
- the cipher key used during encryption.CryptoException
- if there is an error during encryptionvoid encrypt(InputStream in, OutputStream out, byte[] encryptionKey) throws CryptoException
InputStream
, encrypts it, and sends the resulting encrypted data to the
given OutputStream
.
NOTE: This method does NOT flush or close either stream prior to returning - the caller must
do so when they are finished with the streams. For example:
try { InputStream in = ... OutputStream out = ... cipherService.encrypt(in, out, encryptionKey); } finally { if (in != null) { try { in.close(); } catch (IOException ioe1) { ... log, trigger event, etc } } if (out != null) { try { out.close(); } catch (IOException ioe2) { ... log, trigger event, etc } } }
in
- the stream supplying the data to encryptout
- the stream to send the encrypted dataencryptionKey
- the cipher key to use for encryptionCryptoException
- if there is any problem during encryption.Copyright © 2004–2016 The Apache Software Foundation. All rights reserved.