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 "XML Encryption Syntax and Processing" 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);