You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by lh...@apache.org on 2010/04/17 04:00:41 UTC

svn commit: r935106 [2/2] - in /incubator/shiro/trunk: core/src/main/java/org/apache/shiro/crypto/ core/src/main/java/org/apache/shiro/crypto/hash/ core/src/main/java/org/apache/shiro/io/ core/src/main/java/org/apache/shiro/mgt/ core/src/main/java/org/...

Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/OperationMode.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/OperationMode.java?rev=935106&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/OperationMode.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/OperationMode.java Sat Apr 17 02:00:40 2010
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.crypto;
+
+/**
+ * A cipher <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation">mode of operation</a>
+ * directs a cipher algorithm how to convert data during the encryption or decryption process.  This enum represents
+ * all JDK-standard Cipher operation mode names as defined in
+ * <a href="http://java.sun.com/javase/6/docs/technotes/guides/security/StandardNames.html">JDK Security Standard
+ * Names</a>, as well as a few more that are well-known and supported by other JCA Providers.
+ * <p/>
+ * This {@code enum} exists to provide Shiro end-users type-safety when declaring an operation mode.  This helps reduce
+ * error by providing a compile-time mechanism to specify a mode and guarantees a valid name that will be
+ * recognized by an underling JCA Provider.
+ * <h2>Standard or Non-Standard?</h2>
+ * All modes listed specify whether they are a JDK standard mode or a non-standard mode.  Standard modes are included
+ * in all JDK distributions.  Non-standard modes can
+ * sometimes result in better performance or more secure output, but may not be available on the target JDK
+ * platform and rely on an external JCA Provider to be installed.  Some providers
+ * (like <a href="http://www.bouncycastle.org">Bouncy Castle</a>) may support these modes however.
+ *
+ * @author Les Hazlewood
+ * @see <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation">Block Cipher Modes of Operation<a/>
+ * @since 1.0
+ */
+public enum OperationMode {
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29">
+     * Cipher-block Chaining</a> mode, defined in <a href="http://csrc.nist.gov/publications/fips/index.html">FIPS
+     * PUB 81</a>.
+     * <p/>
+     * This is a standard JDK operation mode and should be supported by all JDK environments.
+     */
+    CBC,
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/CCM_mode">Counter with CBC-MAC</a> mode<b>*</b> - for block ciphers with
+     * 128 bit block-size only. See <a href="http://www.ietf.org/rfc/rfc3610.txt">RFC 3610</a> for AES Ciphers.
+     * This mode has essentially been replaced by the more-capable {@link #EAX EAX} mode.
+     * <p/>
+     * <b>*THIS IS A NON-STANDARD MODE</b>. It is not guaranteed to be supported across JDK installations.  You must
+     * ensure you have a JCA Provider that can support this cipher operation mode.
+     * <a href="http://www.bouncycastle.org">Bouncy Castle</a> <em>may</em> be one such provider.
+     */
+    CCM,
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29">Cipher
+     * Feedback<a/> mode, defined in <a href="http://csrc.nist.gov/publications/fips/index.html">FIPS PUB 81</a>.
+     * <p/>
+     * This is a standard JDK operation mode and should be supported by all JDK environments.
+     */
+    CFB,
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29">Counter Mode</a>, aka
+     * Integer Counter Mode (ICM) and Segmented Integer Counter (SIC).  Counter is a simplification of {@link #OFB OFB}
+     * and updates the input block as a counter.
+     * <p/>
+     * This is a standard JDK operation mode and should be supported by all JDK environments.
+     */
+    CTR,
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/EAX_mode">EAX Mode</a><b>*</b>.  This is a patent-free but less-effecient
+     * alternative to {@link #OCB OCB} and has capabilities beyond what {@link #CCM CCM} can provide.
+     * <p/>
+     * <b>*THIS IS A NON-STANDARD MODE</b>. It is not guaranteed to be supported across JDK installations.  You must
+     * ensure you have a JCA Provider that can support this cipher operation mode.
+     * <a href="http://www.bouncycastle.org">Bouncy Castle</a> <em>may</em> be one such provider.
+     */
+    EAX,
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29">Electronic
+     * Codebook</a> mode, defined in <a href="http://csrc.nist.gov/publications/fips/index.html">FIPS PUB 81</a>.
+     * ECB is the only mode that does <em>not</em> require an Initialization Vector, but because of this, can be seen
+     * as less secure than operation modes that require an IV.
+     * <p/>
+     * This is a standard JDK operation mode and should be supported by all JDK environments.
+     */
+    ECB,
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/GCM_mode">Galois/Counter</a> mode<b>*</b> - for block ciphers with 128
+     * bit block-size only.
+     * <p/>
+     * <b>*THIS IS A NON-STANDARD MODE</b>. It is not guaranteed to be supported across JDK installations.  You must
+     * ensure you have a JCA Provider that can support this cipher operation mode.
+     * <a href="http://www.bouncycastle.org">Bouncy Castle</a> <em>may</em> be one such provider.
+     */
+    GCM,
+
+    /**
+     * No mode.
+     * <p/>
+     * This is a standard JDK operation mode and should be supported by all JDK environments.
+     */
+    NONE,
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/OCB_mode">Offset Codebook</a> mode<b>*</b>.  Parallel mode that provides
+     * both message privacy and authenticity in a single pass.  This is a very efficient mode, but is patent-encumbered.
+     * A less-efficient (two pass) alternative is available by using {@link #EAX EAX} mode.
+     * <p/>
+     * <b>*THIS IS A NON-STANDARD MODE</b>. It is not guaranteed to be supported across JDK installations.  You must
+     * ensure you have a JCA Provider that can support this cipher operation mode.
+     * <a href="http://www.bouncycastle.org">Bouncy Castle</a> <em>may</em> be one such provider.
+     */
+    OCB,
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29">Output
+     * Feedback</a> mode, defined in <a href="http://csrc.nist.gov/publications/fips/index.html">FIPS PUB 81</a>.
+     * <p/>
+     * This is a standard JDK operation mode and should be supported by all JDK environments.
+     */
+    OFB,
+
+    /**
+     * <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Propagating_cipher-block_chaining_.28PCBC.29">
+     * Propagating Cipher Block Chaining</a> mode, defined in <a href="http://web.mit.edu/kerberos/">Kerberos version 4<a/>.
+     * <p/>
+     * This is a standard JDK operation mode and should be supported by all JDK environments.
+     */
+    PCBC
+}

Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/PaddingScheme.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/PaddingScheme.java?rev=935106&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/PaddingScheme.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/PaddingScheme.java Sat Apr 17 02:00:40 2010
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.crypto;
+
+/**
+ * A {@code CipherPaddingScheme} represents well-known
+ * <a href="http://en.wikipedia.org/wiki/Padding_(cryptography)">padding schemes</a> supported by JPA providers in a
+ * type-safe manner.
+ * <p/>
+ * When encrypted data is transferred, it is usually desirable to ensure that all 'chunks' transferred are a fixed-length:
+ * different length blocks might give cryptanalysts clues about what the data might be, among other reasons.  Of course
+ * not all data will convert to neat fixed-length blocks, so padding schemes are used to 'fill in' (pad) any remaining
+ * space with unintelligible data.
+ * <p/>
+ * Padding schemes can be used in both asymmetric key ciphers as well as symmetric key ciphers (e.g. block ciphers).
+ * Block-ciphers especially regularly use padding schemes as they are based on the notion of fixed-length block sizes.
+ *
+ * @author Les Hazlewood
+ * @see <a href="http://en.wikipedia.org/wiki/Padding_(cryptography)">Wikipedia: Cryptographic Padding</a>
+ * @since 1.0
+ */
+public enum PaddingScheme {
+
+    /**
+     * No padding.  Useful when the block size is 8 bits for block cipher streaming operations. (Because
+     * a byte is the most primitive block size, there is nothing to pad).
+     */
+    NONE("NoPadding"),
+
+    /**
+     * Padding scheme as defined in the W3C's &quot;XML Encryption Syntax and Processing&quot; document,
+     * <a href="http://www.w3.org/TR/xmlenc-core/#sec-Alg-Block">Section 5.2 - Block Encryption Algorithms</a>.
+     */
+    ISO10126("ISO10126Padding"),
+
+    /**
+     * Optimal Asymmetric Encryption Padding defined in RSA's <a href="http://en.wikipedia.org/wiki/PKCS1">PKSC#1
+     * standard</a> (aka <a href="http://tools.ietf.org/html/rfc3447">RFC 3447</a>).
+     * <p/>
+     * <b>NOTE:</b> using this padding requires initializing {@link javax.crypto.Cipher Cipher} instances with a
+     * {@link javax.crypto.spec.OAEPParameterSpec OAEPParameterSpec} object which provides the 1) message digest and
+     * 2) mask generation function to use for the scheme.
+     * <h3>Convenient Alternatives</h3>
+     * While using this scheme enables you full customization of the message digest + mask generation function
+     * combination, it does require the extra burden of providing your own {@code OAEPParameterSpec} object.  This is
+     * often unnecessary, because most combinations are fairly standard.  These common combinations are pre-defined
+     * in this enum in the {@code OAEP}* variants.
+     * <p/>
+     * If you find that these common combinations still do not meet your needs, then you will need to
+     * specify your own message digest and mask generation function, either as an {@code OAEPParameterSpec} object
+     * during Cipher initialization or, maybe more easily, in the scheme name directly.  If you want to use scheme name
+     * approach, the name format is specified in the
+     * <a href="http://java.sun.com/javase/6/docs/technotes/guides/security/StandardNames.html">Standard Names</a>
+     * document in the <code>Cipher Algorithm Padding</code> section.
+     *
+     * @see #OAEPWithMd5AndMgf1
+     * @see #OAEPWithSha1AndMgf1
+     * @see #OAEPWithSha256AndMgf1
+     * @see #OAEPWithSha384AndMgf1
+     * @see #OAEPWithSha512AndMgf1
+     */
+    OAEP("OAEPPadding"),
+
+    /**
+     * Optimal Asymmetric Encryption Padding with {@code MD5} message digest and {@code MGF1} mask generation function.
+     * <p/>
+     * This is a convenient pre-defined OAEP padding scheme that embeds the message digest and mask generation function.
+     * When using this padding scheme, there is no need to init the {@code Cipher} instance with an
+     * {@link javax.crypto.spec.OAEPParameterSpec OAEPParameterSpec} object, as it is already 'built in' to the scheme
+     * name (unlike the {@link #OAEP OAEP} scheme, which requires a bit more work).
+     */
+    OAEPWithMd5AndMgf1("OAEPWithMD5AndMGF1Padding"),
+
+    /**
+     * Optimal Asymmetric Encryption Padding with {@code SHA-1} message digest and {@code MGF1} mask generation function.
+     * <p/>
+     * This is a convenient pre-defined OAEP padding scheme that embeds the message digest and mask generation function.
+     * When using this padding scheme, there is no need to init the {@code Cipher} instance with an
+     * {@link javax.crypto.spec.OAEPParameterSpec OAEPParameterSpec} object, as it is already 'built in' to the scheme
+     * name (unlike the {@link #OAEP OAEP} scheme, which requires a bit more work).
+     */
+    OAEPWithSha1AndMgf1("OAEPWithSHA-1AndMGF1Padding"),
+
+    /**
+     * Optimal Asymmetric Encryption Padding with {@code SHA-256} message digest and {@code MGF1} mask generation function.
+     * <p/>
+     * This is a convenient pre-defined OAEP padding scheme that embeds the message digest and mask generation function.
+     * When using this padding scheme, there is no need to init the {@code Cipher} instance with an
+     * {@link javax.crypto.spec.OAEPParameterSpec OAEPParameterSpec} object, as it is already 'built in' to the scheme
+     * name (unlike the {@link #OAEP OAEP} scheme, which requires a bit more work).
+     */
+    OAEPWithSha256AndMgf1("OAEPWithSHA-256AndMGF1Padding"),
+
+    /**
+     * Optimal Asymmetric Encryption Padding with {@code SHA-384} message digest and {@code MGF1} mask generation function.
+     * <p/>
+     * This is a convenient pre-defined OAEP padding scheme that embeds the message digest and mask generation function.
+     * When using this padding scheme, there is no need to init the {@code Cipher} instance with an
+     * {@link javax.crypto.spec.OAEPParameterSpec OAEPParameterSpec} object, as it is already 'built in' to the scheme
+     * name (unlike the {@link #OAEP OAEP} scheme, which requires a bit more work).
+     */
+    OAEPWithSha384AndMgf1("OAEPWithSHA-384AndMGF1Padding"),
+
+    /**
+     * Optimal Asymmetric Encryption Padding with {@code SHA-512} message digest and {@code MGF1} mask generation function.
+     * <p/>
+     * This is a convenient pre-defined OAEP padding scheme that embeds the message digest and mask generation function.
+     * When using this padding scheme, there is no need to init the {@code Cipher} instance with an
+     * {@link javax.crypto.spec.OAEPParameterSpec OAEPParameterSpec} object, as it is already 'built in' to the scheme
+     * name (unlike the {@link #OAEP OAEP} scheme, which requires a bit more work).
+     */
+    OAEPWithSha512AndMgf1("OAEPWithSHA-512AndMGF1Padding"),
+
+    /**
+     * Padding scheme used with the {@code RSA} algorithm defined in RSA's
+     * <a href="http://en.wikipedia.org/wiki/PKCS1">PKSC#1 standard</a> (aka
+     * <a href="http://tools.ietf.org/html/rfc3447">RFC 3447</a>).
+     */
+    PKCS1("PKCS1Padding"),
+
+    /**
+     * Padding scheme defined in RSA's <a href="http://www.rsa.com/rsalabs/node.asp?id=2127">Password-Based
+     * Cryptography Standard</a>.
+     */
+    PKCS5("PKCS5Padding"),
+
+    /**
+     * Padding scheme defined in the <a href="http://www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt">SSL
+     * 3.0 specification</a>, section <code>5.2.3.2 (CBC block cipher)</code>.
+     */
+    SSL3("SSL3Padding");
+
+    private final String transformationName;
+
+    private PaddingScheme(String transformationName) {
+        this.transformationName = transformationName;
+    }
+
+    /**
+     * Returns the actual string name to use when building the {@link javax.crypto.Cipher Cipher}
+     * {@code transformation string}.
+     *
+     * @return the actual string name to use when building the {@link javax.crypto.Cipher Cipher}
+     *         {@code transformation string}.
+     * @see javax.crypto.Cipher#getInstance(String)
+     */
+    public String getTransformationName() {
+        return this.transformationName;
+    }
+}

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/AbstractHash.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/AbstractHash.java?rev=935106&r1=935105&r2=935106&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/AbstractHash.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/AbstractHash.java Sat Apr 17 02:00:40 2010
@@ -110,7 +110,8 @@ public abstract class AbstractHash exten
      * {@code hashIterations} times.
      * <p/>
      * By default, this class only supports Object method arguments of
-     * type {@code byte[]}, {@code char[]} and {@code String}.  If either argument is anything other than these
+     * type {@code byte[]}, {@code char[]}, {@link String}, {@link java.io.File File}, or
+     * {@link java.io.InputStream InputStream}.  If either argument is anything other than these
      * types a {@link org.apache.shiro.codec.CodecException CodecException} will be thrown.
      * <p/>
      * If you want to be able to hash other object types, or use other salt types, you need to override the

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/Hash.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/Hash.java?rev=935106&r1=935105&r2=935106&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/Hash.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/Hash.java Sat Apr 17 02:00:40 2010
@@ -19,8 +19,8 @@
 package org.apache.shiro.crypto.hash;
 
 /**
- * A Cryptoraphic <tt>Hash</tt> represents a one-way conversion algorithm that transforms an input source to an underlying
- * byte array.
+ * A Cryptographic {@code Hash} represents a one-way conversion algorithm that transforms an input source to an
+ * underlying byte array.
  *
  * @author Les Hazlewood
  * @see AbstractHash

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/package-info.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/package-info.java?rev=935106&r1=935105&r2=935106&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/package-info.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/package-info.java Sat Apr 17 02:00:40 2010
@@ -20,7 +20,7 @@
  * Cryptography Cipher and Hashing components that greatly simplify the JDK's cryptography concepts and
  * add additional convenient behavior.
  * <p/>
- * The most important interface in this package is the {@link org.apache.shiro.crypto.Cipher Cipher} interface, which
- * allows other Shiro components to encrypt and decrypt potentially sensitive data.
+ * The most important interface in this package is the {@link org.apache.shiro.crypto.CipherService CipherService}
+ * interface, which allows one to encrypt and decrypt sensitive data.
  */
 package org.apache.shiro.crypto;

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/Serializer.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/Serializer.java?rev=935106&r1=935105&r2=935106&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/Serializer.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/Serializer.java Sat Apr 17 02:00:40 2010
@@ -23,10 +23,11 @@ package org.apache.shiro.io;
  * of objects to files, HTTP cookies, or other mechanism.
  * <p/>
  * A <code>Serializer</code> should only do conversion, never change the data, such as encoding/decoding or
- * encryption.  These orthoganal concerns are handled elsewhere by Shiro, for example, via
- * {@link org.apache.shiro.codec.CodecSupport CodecSupport} and {@link org.apache.shiro.crypto.Cipher Cipher}s.
- * @param <T> The type of the object being serialized and deserialized.
+ * encryption.  These orthogonal concerns are handled elsewhere by Shiro, for example, via
+ * {@link org.apache.shiro.codec.CodecSupport CodecSupport} and {@link org.apache.shiro.crypto.CipherService CipherService}s.
+ *
  * @author Les Hazlewood
+ * @param <T> The type of the object being serialized and deserialized.
  * @since 0.9
  */
 public interface Serializer<T> {
@@ -34,6 +35,7 @@ public interface Serializer<T> {
     /**
      * Converts the specified Object into a byte[] array.  This byte[] array must be able to be reconstructed
      * back into the original Object form via the {@link #deserialize(byte[]) deserialize} method.
+     *
      * @param o the Object to convert into a byte[] array.
      * @return a byte[] array representing the Object's state that can be restored later.
      * @throws SerializationException if an error occurrs converting the Object into a byte[] array.
@@ -44,7 +46,7 @@ public interface Serializer<T> {
      * Converts the specified raw byte[] array back into an original Object form.  This byte[] array is expected to
      * be the output of a previous {@link #serialize(Object) serialize} method call.
      *
-     * @param serialized the raw data resulting from a previous {@link #serialize(Object) serialize} call. 
+     * @param serialized the raw data resulting from a previous {@link #serialize(Object) serialize} call.
      * @return the Object that was previously serialized into the raw byte[] array.
      * @throws SerializationException if an error occurrs converting the raw byte[] array back into an Object.
      */

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java?rev=935106&r1=935105&r2=935106&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java Sat Apr 17 02:00:40 2010
@@ -24,12 +24,13 @@ import org.apache.shiro.authc.Authentica
 import org.apache.shiro.authc.RememberMeAuthenticationToken;
 import org.apache.shiro.codec.Base64;
 import org.apache.shiro.codec.Hex;
-import org.apache.shiro.crypto.BlowfishCipher;
-import org.apache.shiro.crypto.Cipher;
+import org.apache.shiro.crypto.AesCipherService;
+import org.apache.shiro.crypto.CipherService;
 import org.apache.shiro.io.DefaultSerializer;
 import org.apache.shiro.io.Serializer;
 import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.ByteSource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,9 +39,27 @@ import java.util.Map;
 /**
  * Abstract implementation of the {@code RememberMeManager} interface that handles
  * {@link #setSerializer(org.apache.shiro.io.Serializer) serialization} and
- * {@link #setCipher(org.apache.shiro.crypto.Cipher) encryption} of the remembered user identity.
+ * {@link #setCipherService encryption} of the remembered user identity.
  * <p/>
  * The remembered identity storage location and details are left to subclasses.
+ * <h2>Default encryption key</h2>
+ * This implementation uses an {@link AesCipherService AesCipherService} for strong encryption by default.  It also
+ * uses a default generated symmetric key to both encrypt and decrypt data.Shiro's default symmetric block Cipher using the Blowfish algorithm.  As it is a symmetric Cipher, it uses the
+ * same <tt>Key</tt> to both encrypt and decrypt data, BUT NOTE:
+ * <p/>
+ * Because Shiro is an open-source project, if anyone knew that you were using Shiro's default
+ * {@code key}, they could download/view the source, and with enough effort, reconstruct the {@code key}
+ * and decode encrypted data at will.
+ * <p/>
+ * Of course, this key is only really used to encrypt the remembered {@code PrincipalCollection} which is typically
+ * a user id or username.  So if you do not consider that sensitive information, and you think the default key still
+ * makes things 'sufficiently difficult', then you can ignore this issue.
+ * <p/>
+ * However, if you do feel this constitutes sensitive information, it is recommended that you provide your own
+ * {@code key} via the {@link #setCipherKey setCipherKey} method to a key known only to your application,
+ * guaranteeing that no third party can decrypt your data.  You can generate your own key by calling the
+ * {@code CipherService}'s {@link org.apache.shiro.crypto.AesCipherService#generateNewKey() generateNewKey} method
+ * and using that result as the {@link #setCipherKey cipherKey} configuration attribute.
  *
  * @author Les Hazlewood
  * @author Jeremy Haile
@@ -54,6 +73,17 @@ public abstract class AbstractRememberMe
     private static final Logger log = LoggerFactory.getLogger(AbstractRememberMeManager.class);
 
     /**
+     * The following Base64 string was generated by auto-generating an AES Key:
+     * <pre>
+     * AesCipherService aes = new AesCipherService();
+     * byte[] key = aes.generateNewKey().getEncoded();
+     * String base64 = Base64.encodeToString(key);
+     * </pre>
+     * The value of 'base64' was copied-n-pasted here:
+     */
+    private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");
+
+    /**
      * Serializer to use for converting PrincipalCollection instances to/from byte arrays
      */
     private Serializer<PrincipalCollection> serializer;
@@ -61,7 +91,7 @@ public abstract class AbstractRememberMe
     /**
      * Cipher to use for encrypting/decrypting serialized byte arrays for added security
      */
-    private Cipher cipher;
+    private CipherService cipherService;
 
     /**
      * Cipher encryption key to use with the Cipher when encrypting data
@@ -75,11 +105,12 @@ public abstract class AbstractRememberMe
 
     /**
      * Default constructor that initializes a {@link DefaultSerializer} as the {@link #getSerializer() serializer} and
-     * a {@link BlowfishCipher BlowfishCipher} as the {@link #getCipher() cipher}.
+     * an {@link AesCipherService} as the {@link #getCipherService() cipherService}.
      */
     public AbstractRememberMeManager() {
         this.serializer = new DefaultSerializer<PrincipalCollection>();
-        this.cipher = new BlowfishCipher();
+        this.cipherService = new AesCipherService();
+        setCipherKey(DEFAULT_CIPHER_KEY_BYTES);
     }
 
     /**
@@ -110,23 +141,23 @@ public abstract class AbstractRememberMe
     }
 
     /**
-     * Returns the {@code Cipher} to use for encrypting and decrypting serialized identity data to prevent easy
+     * Returns the {@code CipherService} to use for encrypting and decrypting serialized identity data to prevent easy
      * inspection of Subject identity data.
      * <p/>
-     * Unless overridden by the {@link #setCipher} method, the default instance is a {@link BlowfishCipher}.
+     * Unless overridden by the {@link #setCipherService} method, the default instance is an {@link AesCipherService}.
      *
      * @return the {@code Cipher} to use for encrypting and decrypting serialized identity data to prevent easy
      *         inspection of Subject identity data
      */
-    public Cipher getCipher() {
-        return cipher;
+    public CipherService getCipherService() {
+        return cipherService;
     }
 
     /**
-     * Sets the {@code Cipher} to use for encrypting and decrypting serialized identity data to prevent easy
+     * Sets the {@code CipherService} to use for encrypting and decrypting serialized identity data to prevent easy
      * inspection of Subject identity data.
      * <p/>
-     * If the cipher is an symmetric cipher (using the same key for both encryption and decryption), you
+     * If the CipherService is a symmetric CipherService (using the same key for both encryption and decryption), you
      * should set your key via one of the three following methods:
      * <ul>
      * <li>{@link #setCipherKey(byte[])}</li>
@@ -134,8 +165,8 @@ public abstract class AbstractRememberMe
      * <li>{@link #setCipherKeyHex(String)}</li>
      * </ul>
      * <p/>
-     * If the cipher is an asymmetric cipher (different keys for encryption and decryption, such as public/private key
-     * pairs), you should set your encryption key via one of these methods:
+     * If the CipherService is an asymmetric CipherService (different keys for encryption and decryption, such as
+     * public/private key pairs), you should set your encryption key via one of these methods:
      * <ul>
      * <li>{@link #setEncryptionCipherKey(byte[])}</li>
      * <li>{@link #setEncryptionCipherKeyHex(String)}, or</li>
@@ -148,23 +179,23 @@ public abstract class AbstractRememberMe
      * <li>{@link #setDecryptionCipherKeyBase64(String)}</li>
      * </ul>
      * <p/>
-     * <b>N.B.</b> Unless overridden by this method, the default Cipher instance is a
-     * {@link BlowfishCipher}.  Shiro's {@code BlowfishCipher} already has a configured symmetric key to use for
-     * encryption and decryption, but it is recommended to provide your own for added security.  See the
-     * {@link BlowfishCipher} class-level JavaDoc for more information and why it might be good to provide your own.
+     * <b>N.B.</b> Unless overridden by this method, the default CipherService instance is an
+     * {@link AesCipherService}.  This {@code RememberMeManager} implementation already has a configured symmetric key
+     * to use for encryption and decryption, but it is recommended to provide your own for added security.  See the
+     * class-level JavaDoc for more information and why it might be good to provide your own.
      *
-     * @param cipher the {@code Cipher} to use for encrypting and decrypting serialized identity data to prevent easy
-     *               inspection of Subject identity data.
+     * @param cipherService the {@code CipherService} to use for encrypting and decrypting serialized identity data to
+     *                      prevent easy inspection of Subject identity data.
      */
-    public void setCipher(Cipher cipher) {
-        this.cipher = cipher;
+    public void setCipherService(CipherService cipherService) {
+        this.cipherService = cipherService;
     }
 
     /**
      * Returns the cipher key to use for encryption operations.
      *
      * @return the cipher key to use for encryption operations.
-     * @see #setCipher for a description of the various {@code get/set*Key} methods.
+     * @see #setCipherService for a description of the various {@code get/set*Key} methods.
      */
     public byte[] getEncryptionCipherKey() {
         return encryptionCipherKey;
@@ -176,31 +207,31 @@ public abstract class AbstractRememberMe
      * {@link #setEncryptionCipherKeyBase64(String) encryptionCipherKeyBase64} methods are probably more convenient.
      *
      * @param encryptionCipherKey the encryption key to use for encryption operations.
-     * @see #setCipher for a description of the various {@code get/set*Key} methods.
+     * @see #setCipherService for a description of the various {@code get/set*Key} methods.
      */
     public void setEncryptionCipherKey(byte[] encryptionCipherKey) {
         this.encryptionCipherKey = encryptionCipherKey;
     }
 
     /**
-     * Convenience method that allows configuration of the encryption {@link Cipher cipher} key by specifying a
+     * Convenience method that allows configuration of the encryption cipher key by specifying a
      * {@code hex}-encoded string.  The string is {@code hex}-decoded and the resulting byte array is used
-     * as the {@link #setEncryptionCipherKey(byte[]) encryption cipher key}.
+     * as the {@link #setEncryptionCipherKey(byte[]) encryptionCipherKey}.
      *
      * @param hex hex-encoded encryption cipher key to decode into the raw encryption cipher key bytes.
-     * @see #setCipher for a description of the various {@code get/set*Key} methods.
+     * @see #setCipherService for a description of the various {@code get/set*Key} methods.
      */
     public void setEncryptionCipherKeyHex(String hex) {
         setEncryptionCipherKey(Hex.decode(hex));
     }
 
     /**
-     * Convenience method that allows configuration of the encryption {@link Cipher cipher} key by specifying a
+     * Convenience method that allows configuration of the encryption cipher key by specifying a
      * {@code BASE 64}-encoded string.  The string is {@code BASE 64}-decoded and the resulting byte array is used
-     * as the {@link #setEncryptionCipherKey(byte[]) cipher key}.
+     * as the {@link #setEncryptionCipherKey(byte[]) encryptionCipherKey}.
      *
      * @param base64 base64-encoded encryption cipher key to decode into the raw encryption cipher key bytes
-     * @see #setCipher for a description of the various {@code get/set*Key} methods.
+     * @see #setCipherService for a description of the various {@code get/set*Key} methods.
      */
     public void setEncryptionCipherKeyBase64(String base64) {
         setEncryptionCipherKey(Base64.decode(base64));
@@ -210,7 +241,7 @@ public abstract class AbstractRememberMe
      * Returns the decryption cipher key to use for decryption operations.
      *
      * @return the cipher key to use for decryption operations.
-     * @see #setCipher for a description of the various {@code get/set*Key} methods.
+     * @see #setCipherService for a description of the various {@code get/set*Key} methods.
      */
     public byte[] getDecryptionCipherKey() {
         return decryptionCipherKey;
@@ -222,31 +253,31 @@ public abstract class AbstractRememberMe
      * {@link #setDecryptionCipherKeyBase64(String) decryptionCipherKeyBase64} methods are probably more convenient.
      *
      * @param decryptionCipherKey the decryption key to use for decryption operations.
-     * @see #setCipher for a description of the various {@code get/set*Key} methods.
+     * @see #setCipherService for a description of the various {@code get/set*Key} methods.
      */
     public void setDecryptionCipherKey(byte[] decryptionCipherKey) {
         this.decryptionCipherKey = decryptionCipherKey;
     }
 
     /**
-     * Convenience method that allows configuration of the decryption {@link Cipher cipher} key by specifying a
+     * Convenience method that allows configuration of the decryption cipher key by specifying a
      * {@code hex}-encoded string.  The string is {@code hex}-decoded and the resulting byte array is used
-     * as the {@link #setDecryptionCipherKey(byte[]) decryption cipher key}.
+     * as the {@link #setDecryptionCipherKey(byte[]) decryptionCipherKey}.
      *
      * @param hex hex-encoded decryption cipher key to decode into the raw decryption cipher key bytes.
-     * @see #setCipher for a description of the various {@code get/set*Key} methods.
+     * @see #setCipherService for a description of the various {@code get/set*Key} methods.
      */
     public void setDecryptionCipherKeyHex(String hex) {
         setDecryptionCipherKey(Hex.decode(hex));
     }
 
     /**
-     * Convenience method that allows configuration of the decryption {@link Cipher cipher} key by specifying a
+     * Convenience method that allows configuration of the decryption cipher key by specifying a
      * {@code BASE 64}-encoded string.  The string is {@code BASE 64}-decoded and the resulting byte array is used
-     * as the {@link #setDecryptionCipherKey(byte[]) cipher key}.
+     * as the {@link #setDecryptionCipherKey(byte[]) decryptionCipherKey}.
      *
      * @param base64 base64-encoded decryption cipher key to decode into the raw decryption cipher key bytes
-     * @see #setCipher for a description of the various {@code get/set*Key} methods.
+     * @see #setCipherService for a description of the various {@code get/set*Key} methods.
      */
     public void setDecryptionCipherKeyBase64(String base64) {
         setDecryptionCipherKey(Base64.decode(base64));
@@ -255,13 +286,13 @@ public abstract class AbstractRememberMe
     /**
      * Convenience method that returns the cipher key to use for <em>both</em> encryption and decryption.
      * <p/>
-     * <b>N.B.</b> This method can only be called if the underlying {@link #getCipher() cipher} is a symmetric cipher
-     * which by definition uses the same key for both encryption and decryption.  If using an asymmetric cipher
-     * (such as a public/private key pair), you cannot use this method, and should instead use the
+     * <b>N.B.</b> This method can only be called if the underlying {@link #getCipherService() cipherService} is a symmetric
+     * CipherService which by definition uses the same key for both encryption and decryption.  If using an asymmetric
+     * CipherService public/private key pair, you cannot use this method, and should instead use the
      * {@link #getEncryptionCipherKey()} and {@link #getDecryptionCipherKey()} methods individually.
      * <p/>
-     * The default {@link BlowfishCipher} instance is a symmetric cipher, so this method can be used if you are using
-     * the default.
+     * The default {@link AesCipherService} instance is a symmetric cipher service, so this method can be used if you are
+     * using the default.
      *
      * @return the symmetric cipher key used for both encryption and decryption.
      */
@@ -274,13 +305,13 @@ public abstract class AbstractRememberMe
     /**
      * Convenience method that sets the cipher key to use for <em>both</em> encryption and decryption.
      * <p/>
-     * <b>N.B.</b> This method can only be called if the underlying {@link #getCipher() cipher} is a symmetric cipher
-     * which by definition uses the same key for both encryption and decryption.  If using an asymmetric cipher
-     * (such as a public/private key pair), you cannot use this method, and should instead use the
-     * {@link #setEncryptionCipherKey(byte[])} and {@link #setDecryptionCipherKey(byte[])} methods individually.
+     * <b>N.B.</b> This method can only be called if the underlying {@link #getCipherService() cipherService} is a
+     * symmetric CipherService?which by definition uses the same key for both encryption and decryption.  If using an
+     * asymmetric CipherService?(such as a public/private key pair), you cannot use this method, and should instead use
+     * the {@link #setEncryptionCipherKey(byte[])} and {@link #setDecryptionCipherKey(byte[])} methods individually.
      * <p/>
-     * The default {@link BlowfishCipher} instance is a symmetric cipher, so this method can be used if you are using
-     * the default.
+     * The default {@link AesCipherService} instance is a symmetric CipherService, so this method can be used if you
+     * are using the default.
      *
      * @param cipherKey the symmetric cipher key to use for both encryption and decryption.
      */
@@ -292,18 +323,17 @@ public abstract class AbstractRememberMe
     }
 
     /**
-     * Convenience method that allows configuration of the (symmetric) {@link Cipher cipher} key by specifying a
+     * Convenience method that allows configuration of the (symmetric) cipher key by specifying a
      * {@code hex}-encoded string.  The string is {@code hex}-decoded and the resulting byte array is used
-     * as the {@link #setCipherKey(byte[]) cipher key}.
+     * as the {@link #setCipherKey(byte[]) cipherKey}.
      * <p/>
-     * <b>N.B.</b> This is a convenience method to set <em>both</em> the {@link Cipher} encryption key and the
-     * decryption key and should only be called if using a symmetric cipher.  If using an asymmetric cipher (such
-     * as a public/private key pair) you cannot
-     * call this method and instead should use the {@link #setEncryptionCipherKeyHex(String)} and
-     * {@link #setDecryptionCipherKeyHex(String)} methods instead.
+     * <b>N.B.</b> This is a convenience method to set <em>both</em> the {@link CipherService} encryption key and the
+     * decryption key and should only be called if using a symmetric CipherService.  If using an asymmetric CipherService
+     * (such as a public/private key pair) you cannot call this method and instead should use the
+     * {@link #setEncryptionCipherKeyHex(String)} and {@link #setDecryptionCipherKeyHex(String)} methods instead.
      * <p/>
-     * The default {@link BlowfishCipher} instance is a symmetric cipher, so this method can be used if you are using
-     * the default.
+     * The default {@link AesCipherService} instance is a symmetric CipherService, so this method can be used if you are
+     * using the default.
      *
      * @param hex hex-encoded symmetric cipher key to decode into the raw cipher key bytes.
      */
@@ -312,17 +342,17 @@ public abstract class AbstractRememberMe
     }
 
     /**
-     * Convenience method that allows configuration of the (symmetric) {@link Cipher cipher} key by specifying a
-     * {@code BASE 64}-encoded string.  The string is {@code BASE 64}-decoded and the resulting byte array is used
-     * as the {@link #setCipherKey(byte[]) cipher key}.
-     * <p/>
-     * <b>N.B.</b> This is a convenience method to set <em>both</em> the {@link Cipher} encryption key and the
-     * decryption key and should only be called if using a symmetric cipher.  If using an asymmetric cipher, you cannot
-     * call this method and instead should use the {@link #setEncryptionCipherKeyBase64(String)} and
-     * {@link #setDecryptionCipherKeyBase64(String)} methods instead.
+     * Convenience method that allows configuration of the (symmetric) cipher key
+     * by specifying a {@code BASE 64}-encoded string.  The string is {@code BASE 64}-decoded and the resulting byte
+     * array is used as the {@link #setCipherKey(byte[]) cipherKey}.
+     * <p/>
+     * <b>N.B.</b> This is a convenience method to set <em>both</em> the {@link CipherService} encryption key and the
+     * decryption key and should only be called if using a symmetric CipherService.  If using an asymmetric
+     * CipherService, you cannot call this method and instead should use the {@link #setEncryptionCipherKeyBase64(String)}
+     * and {@link #setDecryptionCipherKeyBase64(String)} methods instead.
      * <p/>
-     * The default {@link BlowfishCipher} instance is a symmetric cipher, so this method can be used if you are using
-     * the default.
+     * The default {@link AesCipherService} instance is a symmetric CipherService, so this method can be used if you are
+     * using the default.
      *
      * @param base64 base64-encoded symmetric cipher key to decode into the raw cipher key bytes.
      */
@@ -447,7 +477,7 @@ public abstract class AbstractRememberMe
      */
     protected byte[] convertPrincipalsToBytes(PrincipalCollection principals) {
         byte[] bytes = serialize(principals);
-        if (getCipher() != null) {
+        if (getCipherService() != null) {
             bytes = encrypt(bytes);
         }
         return bytes;
@@ -481,7 +511,7 @@ public abstract class AbstractRememberMe
         try {
             byte[] bytes = getRememberedSerializedIdentity(subjectContext);
             //SHIRO-138 - only call convertBytesToPrincipals if bytes exist:
-            if ( bytes != null && bytes.length > 0 ) {
+            if (bytes != null && bytes.length > 0) {
                 principals = convertBytesToPrincipals(bytes, subjectContext);
             }
         } catch (RuntimeException re) {
@@ -505,8 +535,8 @@ public abstract class AbstractRememberMe
     protected abstract byte[] getRememberedSerializedIdentity(Map subjectContext);
 
     /**
-     * If a {@link #getCipher() cipher} is available, it will be used to first decrypt the byte array.  Then the
-     * bytes are then {@link #deserialize(byte[]) deserialized} and then returned.
+     * If a {@link #getCipherService() cipherService} is available, it will be used to first decrypt the byte array.
+     * Then the bytes are then {@link #deserialize(byte[]) deserialized} and then returned.
      *
      * @param bytes          the bytes to decrypt if necessary and then deserialize.
      * @param subjectContext the contextual data, usually provided by a {@link Subject.Builder} implementation, that
@@ -514,7 +544,7 @@ public abstract class AbstractRememberMe
      * @return the de-serialized and possibly decrypted principals
      */
     protected PrincipalCollection convertBytesToPrincipals(byte[] bytes, Map subjectContext) {
-        if (getCipher() != null) {
+        if (getCipherService() != null) {
             bytes = decrypt(bytes);
         }
         return deserialize(bytes);
@@ -550,31 +580,33 @@ public abstract class AbstractRememberMe
     }
 
     /**
-     * Encrypts the byte array by using the configured {@link #getCipher() cipher}.
+     * Encrypts the byte array by using the configured {@link #getCipherService() cipherService}.
      *
      * @param serialized the serialized object byte array to be encrypted
-     * @return an encrypted byte array returned by the configured {@link #getCipher() cipher}.
+     * @return an encrypted byte array returned by the configured {@link #getCipherService () cipher}.
      */
     protected byte[] encrypt(byte[] serialized) {
         byte[] value = serialized;
-        Cipher cipher = getCipher();
-        if (cipher != null) {
-            value = cipher.encrypt(serialized, getEncryptionCipherKey());
+        CipherService cipherService = getCipherService();
+        if (cipherService != null) {
+            ByteSource byteSource = cipherService.encrypt(serialized, getEncryptionCipherKey());
+            value = byteSource.getBytes();
         }
         return value;
     }
 
     /**
-     * Decrypts the byte array using the configured {@link #getCipher() cipher}.
+     * Decrypts the byte array using the configured {@link #getCipherService() cipherService}.
      *
      * @param encrypted the encrypted byte array to decrypt
-     * @return the decrypted byte array returned by the configured {@link #getCipher() cipher}.
+     * @return the decrypted byte array returned by the configured {@link #getCipherService () cipher}.
      */
     protected byte[] decrypt(byte[] encrypted) {
         byte[] serialized = encrypted;
-        Cipher cipher = getCipher();
-        if (cipher != null) {
-            serialized = cipher.decrypt(encrypted, getDecryptionCipherKey());
+        CipherService cipherService = getCipherService();
+        if (cipherService != null) {
+            ByteSource byteSource = cipherService.decrypt(encrypted, getDecryptionCipherKey());
+            serialized = byteSource.getBytes();
         }
         return serialized;
     }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java?rev=935106&r1=935105&r2=935106&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java Sat Apr 17 02:00:40 2010
@@ -20,7 +20,7 @@ package org.apache.shiro.mgt;
 
 import org.apache.shiro.authc.*;
 import org.apache.shiro.authz.Authorizer;
-import org.apache.shiro.crypto.Cipher;
+import org.apache.shiro.crypto.CipherService;
 import org.apache.shiro.realm.Realm;
 import org.apache.shiro.session.InvalidSessionException;
 import org.apache.shiro.session.Session;
@@ -132,8 +132,8 @@ public class DefaultSecurityManager exte
         return (AbstractRememberMeManager) this.rememberMeManager;
     }
 
-    public void setRememberMeCipher(Cipher cipher) {
-        getRememberMeManagerForCipherAttributes().setCipher(cipher);
+    public void setRememberMeCipherService(CipherService cipherService) {
+        getRememberMeManagerForCipherAttributes().setCipherService(cipherService);
     }
 
     public void setRememberMeCipherKey(byte[] bytes) {

Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/ByteSource.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/ByteSource.java?rev=935106&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/ByteSource.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/ByteSource.java Sat Apr 17 02:00:40 2010
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Les Hazlewood
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.shiro.util;
+
+/**
+ * A {@code ByteSource} wraps a byte array and provides additional encoding operations.
+ *
+ * @author Les Hazlewood
+ * @since 1.0
+ */
+public interface ByteSource {
+
+    public byte[] getBytes();
+
+    public String toHex();
+
+    public String toBase64();
+}

Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/SimpleByteSource.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/SimpleByteSource.java?rev=935106&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/SimpleByteSource.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/SimpleByteSource.java Sat Apr 17 02:00:40 2010
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2008 Les Hazlewood
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.shiro.util;
+
+import org.apache.shiro.codec.Base64;
+import org.apache.shiro.codec.Hex;
+
+import java.util.Arrays;
+
+/**
+ * TODO - Class JavaDoc
+ *
+ * @author Les Hazlewood
+ * @since Apr 12, 2010 2:35:19 PM
+ */
+public class SimpleByteSource implements ByteSource {
+
+    private final byte[] bytes;
+
+    public SimpleByteSource(byte[] bytes) {
+        this.bytes = bytes;
+    }
+
+    public byte[] getBytes() {
+        return this.bytes;
+    }
+
+    public String toHex() {
+        return Hex.encodeToString(getBytes());
+    }
+
+    public String toBase64() {
+        return Base64.encodeToString(getBytes());
+    }
+
+    public String toString() {
+        return toBase64();
+    }
+
+    public int hashCode() {
+        return toBase64().hashCode();
+    }
+
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (o instanceof SimpleByteSource) {
+            SimpleByteSource bs = (SimpleByteSource) o;
+            return Arrays.equals(getBytes(), bs.getBytes());
+        }
+        return false;
+    }
+}

Added: incubator/shiro/trunk/core/src/test/java/org/apache/shiro/crypto/AesCipherServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/java/org/apache/shiro/crypto/AesCipherServiceTest.java?rev=935106&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/test/java/org/apache/shiro/crypto/AesCipherServiceTest.java (added)
+++ incubator/shiro/trunk/core/src/test/java/org/apache/shiro/crypto/AesCipherServiceTest.java Sat Apr 17 02:00:40 2010
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.crypto;
+
+import org.apache.shiro.codec.CodecSupport;
+import org.apache.shiro.util.ByteSource;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import static junit.framework.Assert.assertTrue;
+
+/**
+ * Test class for the AesCipherService class.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public class AesCipherServiceTest {
+
+    private static final String[] PLAINTEXTS = new String[]{
+            "Hello, this is a test.",
+            "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+    };
+
+    @Test
+    public void testBlockOperations() {
+        AesCipherService aes = new AesCipherService();
+
+        byte[] key = aes.generateNewKey().getEncoded();
+
+        for (String plain : PLAINTEXTS) {
+            byte[] plaintext = CodecSupport.toBytes(plain);
+            ByteSource ciphertext = aes.encrypt(plaintext, key);
+            ByteSource decrypted = aes.decrypt(ciphertext.getBytes(), key);
+            assertTrue(Arrays.equals(plaintext, decrypted.getBytes()));
+        }
+    }
+
+    @Test
+    public void testStreamingOperations() {
+
+        AesCipherService cipher = new AesCipherService();
+        byte[] key = cipher.generateNewKey().getEncoded();
+
+        for (String plain : PLAINTEXTS) {
+            byte[] plaintext = CodecSupport.toBytes(plain);
+            InputStream plainIn = new ByteArrayInputStream(plaintext);
+            ByteArrayOutputStream cipherOut = new ByteArrayOutputStream();
+            cipher.encrypt(plainIn, cipherOut, key);
+
+            byte[] ciphertext = cipherOut.toByteArray();
+            InputStream cipherIn = new ByteArrayInputStream(ciphertext);
+            ByteArrayOutputStream plainOut = new ByteArrayOutputStream();
+            cipher.decrypt(cipherIn, plainOut, key);
+
+            byte[] decrypted = plainOut.toByteArray();
+            assertTrue(Arrays.equals(plaintext, decrypted));
+        }
+    }
+}

Added: incubator/shiro/trunk/core/src/test/java/org/apache/shiro/crypto/BlowfishCipherServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/java/org/apache/shiro/crypto/BlowfishCipherServiceTest.java?rev=935106&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/test/java/org/apache/shiro/crypto/BlowfishCipherServiceTest.java (added)
+++ incubator/shiro/trunk/core/src/test/java/org/apache/shiro/crypto/BlowfishCipherServiceTest.java Sat Apr 17 02:00:40 2010
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.crypto;
+
+import org.apache.shiro.codec.CodecSupport;
+import org.apache.shiro.util.ByteSource;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import static junit.framework.Assert.assertTrue;
+
+/**
+ * Test cases for the {@link BlowfishCipherService} class.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public class BlowfishCipherServiceTest {
+
+    private static final String[] PLAINTEXTS = new String[]{
+            "Hello, this is a test.",
+            "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+    };
+
+    @Test
+    public void testBlockOperations() {
+        BlowfishCipherService blowfish = new BlowfishCipherService();
+
+        byte[] key = blowfish.generateNewKey().getEncoded();
+
+        for (String plain : PLAINTEXTS) {
+            byte[] plaintext = CodecSupport.toBytes(plain);
+            ByteSource ciphertext = blowfish.encrypt(plaintext, key);
+            ByteSource decrypted = blowfish.decrypt(ciphertext.getBytes(), key);
+            assertTrue(Arrays.equals(plaintext, decrypted.getBytes()));
+        }
+    }
+
+    @Test
+    public void testStreamingOperations() {
+
+        BlowfishCipherService cipher = new BlowfishCipherService();
+        byte[] key = cipher.generateNewKey().getEncoded();
+
+        for (String plain : PLAINTEXTS) {
+            byte[] plaintext = CodecSupport.toBytes(plain);
+            InputStream plainIn = new ByteArrayInputStream(plaintext);
+            ByteArrayOutputStream cipherOut = new ByteArrayOutputStream();
+            cipher.encrypt(plainIn, cipherOut, key);
+
+            byte[] ciphertext = cipherOut.toByteArray();
+            InputStream cipherIn = new ByteArrayInputStream(ciphertext);
+            ByteArrayOutputStream plainOut = new ByteArrayOutputStream();
+            cipher.decrypt(cipherIn, plainOut, key);
+
+            byte[] decrypted = plainOut.toByteArray();
+            assertTrue(Arrays.equals(plaintext, decrypted));
+        }
+
+    }
+}

Modified: incubator/shiro/trunk/samples/web/src/main/webapp/logout.jsp
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/samples/web/src/main/webapp/logout.jsp?rev=935106&r1=935105&r2=935106&view=diff
==============================================================================
--- incubator/shiro/trunk/samples/web/src/main/webapp/logout.jsp (original)
+++ incubator/shiro/trunk/samples/web/src/main/webapp/logout.jsp Sat Apr 17 02:00:40 2010
@@ -1,4 +1,3 @@
-<%@ page import="org.apache.shiro.SecurityUtils" %>
 <%--
 ~ Licensed to the Apache Software Foundation (ASF) under one
 ~ or more contributor license agreements.  See the NOTICE file
@@ -30,7 +29,7 @@
 
       When a user logs out, any 'rememberMe' identity
       should always be cleared.  In a web application,
-      Shiro uses a Cipher-encrypted Cookie to
+      Shiro uses a cipher-encrypted Cookie to
       remember a user's identity by default, and it will
       automatically delete the Cookie upon a logout.
 

Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java?rev=935106&r1=935105&r2=935106&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java Sat Apr 17 02:00:40 2010
@@ -21,7 +21,7 @@ package org.apache.shiro.web;
 import org.apache.shiro.authc.AuthenticationInfo;
 import org.apache.shiro.authc.SimpleAuthenticationInfo;
 import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.io.SerializationException;
+import org.apache.shiro.crypto.CryptoException;
 import org.apache.shiro.mgt.SubjectFactory;
 import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.subject.SimplePrincipalCollection;
@@ -72,11 +72,12 @@ public class WebRememberMeManagerTest {
     }
 
     // SHIRO-69
+
     @Test
     public void getRememberedPrincipals() {
         HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
         HttpServletResponse mockResponse = createMock(HttpServletResponse.class);
-        Map<String,Object> context = new HashMap<String,Object>();
+        Map<String, Object> context = new HashMap<String, Object>();
         context.put(SubjectFactory.SERVLET_REQUEST, mockRequest);
         context.put(SubjectFactory.SERVLET_RESPONSE, mockResponse);
 
@@ -84,16 +85,16 @@ public class WebRememberMeManagerTest {
 
         //The following base64 string was determined from the log output of the above 'onSuccessfulLogin' test.
         //This will have to change any time the PrincipalCollection implementation changes:
-        final String userPCBlowfishBase64 = "UwP13UzjVUceLBNWh+sYM01JWOSbBOwc1ZLySIws0Idnkc" +
-                "WeD/yWeH0eIycwHaI8MRKPyenBr77dBdt3S7KTK/6qKqKiW5oLqOgU/ZQLdvIOxlZxmT9RlUvK" +
-                "T6zopnQrSpdsCNaruG/Op/XEoJcdNLI9rJCCyMKN3em5wl8GrWTIzKS4hzHombGBEW4EPS9jv4" +
-                "0HV4mIS2sUFXm5MlOptr99e1A6eKYxlLrldk2/yqw29nWohE0sIjO7tRF9mOAZUeC/Fem6K4S8" +
-                "2LbXAJ6p0oNg3MP7dbFSkeeDF2CwFJvvi5xVrGyF0RnTzjwKZdTcvg4bx9ifQpKyPayQgsjCjd" +
-                "3pucJfBq1kuw/IyiPdSREnzWAEXOQi9o9II4jNvOJik+VI3QkwWdBBekzEKCACn8uvjlLKSiR8" +
-                "tCs9vbycs5N0FrODxMQ5FDvhV+rZLHtPkishP5cm/QEL01IUqqC4RA==";
+        final String userPCAesBase64 = "qk7spFqO1zoNLgq3qArE7bc8+J+Zvm1jz8lDSUmRiRlDQQx7jxG4+" +
+                "QImiRpR7zO0d9oHH+7C3VeN9OvGMdjxtpbInMsLcGz4Q0u3M1fmyErn5Mr61chmNzQ8cLegpIKE3M+xMY" +
+                "5JB1PRw7aEJdRxtHh80kiXZ5jeALvDP3hmFM7OF2CDKLIIa83XuBQvyrKGI9GhsxGTLkmNFknbfRsmN7v" +
+                "NIDorceeaMkAetYf6GxDOw1ZK7yEbsydIHnqVWNHLen6DHC8pLkqMNOoGwXLeBroD6mRpoFf76J0VKBcd" +
+                "C54Mg73S2R7wx9ZzSNJJrCi1KAilmThzm3Rm97EidUnYlWI0TM+zvMzNsLynIK4PoIG6HYQQfEI35qVRI" +
+                "bCdbTlTnjfM/fPf7RWO8s4Z7KzszSQMJE9LgBudcyzrld5ZrWb11cianskNZMI8kzOITezjjqvWn5U4jg" +
+                "Mb9a6qcpaNJcgaxV6NZRmof8cnet54wwE=";
 
         Cookie[] cookies = new Cookie[]{
-                new Cookie(WebRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCBlowfishBase64)
+                new Cookie(WebRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCAesBase64)
         };
 
         expect(mockRequest.getCookies()).andReturn(cookies);
@@ -110,21 +111,22 @@ public class WebRememberMeManagerTest {
     }
 
     // SHIRO-69
+
     @Test
     public void getRememberedPrincipalsDecryptionError() {
         HttpServletRequest mockRequest = createNiceMock(HttpServletRequest.class);
         HttpServletResponse mockResponse = createNiceMock(HttpServletResponse.class);
 
-        Map<String,Object> context = new HashMap<String,Object>();
+        Map<String, Object> context = new HashMap<String, Object>();
         context.put(SubjectFactory.SERVLET_REQUEST, mockRequest);
         context.put(SubjectFactory.SERVLET_RESPONSE, mockResponse);
 
         expect(mockRequest.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY)).andReturn(null);
 
         // Simulate a bad return value here (for example if this was encrypted with a different key
-        final String userPCBlowfishBase64 = "DlJgEjFZVuRRN5lCpInkOsawSaKK4hLwegZK/QgR1Thk380v5wL9pA1NZo7QHr7erlnry1vt2AqIyM8Fj2HBCsl1lierxE9EJ1typI2GpgMeG+HmceNdrlN6KGh4AmjLG3zCUPo8E+QzGVs/EO3PIAGyYYtuYbW++oJDr5xfY9DwK4Omq5GijZSSmdpOHiYelPMa1XLwT0D/kNCUm6EVfG6TKwxViNtGdyzknY7abNU7ucw2UWfjFe24hH0SL0hZMXjPQYtMnPl5J5qfjU4EXX1a/Ijn0IKUEk5BmY+ipc6irMI/Rrmumr46XAIU3uwWMxlbPxDtzyABsmGLbmG1vvqCQ6+cX2PQJ37oNcKqr4mV7ObN2EvWZ1uVbJlUdXeEQgghL3/ayatTs3hWwFGdNhgef8c8iX9wM5bEvxqqY9TMXEyLYLZeA8H6gNvJc6hRd0TQFkzUhjs=";
+        final String userPCAesBase64 = "garbage";
         Cookie[] cookies = new Cookie[]{
-                new Cookie(WebRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCBlowfishBase64)
+                new Cookie(WebRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCAesBase64)
         };
 
         expect(mockRequest.getCookies()).andReturn(cookies).anyTimes();
@@ -133,13 +135,13 @@ public class WebRememberMeManagerTest {
         WebRememberMeManager mgr = new WebRememberMeManager();
         PrincipalCollection collection = null;
 
-        SerializationException se = null;
+        CryptoException ce = null;
         try {
             collection = mgr.getRememberedPrincipals(context);
-        } catch (SerializationException expected) {
-            se = expected;
+        } catch (CryptoException expected) {
+            ce = expected;
         }
-        assertNotNull(se);
+        assertNotNull(ce);
 
         verify(mockRequest);