| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
| MessageDigestPasswordEncoder |
|
| 1.8333333333333333;1.833 |
| 1 | package org.acegisecurity.providers.encoding; |
|
| 2 | ||
| 3 | import org.apache.commons.codec.binary.Base64; |
|
| 4 | import org.apache.commons.codec.binary.Hex; |
|
| 5 | ||
| 6 | import java.security.MessageDigest; |
|
| 7 | import java.security.NoSuchAlgorithmException; |
|
| 8 | ||
| 9 | /** |
|
| 10 | * Base for digest password encoders. |
|
| 11 | * <p>This class can be used stand-alone, or one of the subclasses can be used for compatiblity and convenience. |
|
| 12 | * When using this class directly you must specify a |
|
| 13 | * <a href="http://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html#AppA"> |
|
| 14 | * Message Digest Algorithm</a> to use as a constructor arg</p> |
|
| 15 | * |
|
| 16 | * <p>The encoded password hash is normally returned as Hex (32 char) version of the hash bytes. |
|
| 17 | * Setting the <tt>encodeHashAsBase64</tt> property to <tt>true</tt> will cause the encoded pass to be returned |
|
| 18 | * as Base64 text, which will consume 24 characters. |
|
| 19 | * See {@link BaseDigestPasswordEncoder#setEncodeHashAsBase64(boolean)} |
|
| 20 | * </p> |
|
| 21 | * <p> |
|
| 22 | * This PasswordEncoder can be used directly as in the following example:<br/> |
|
| 23 | * <pre> |
|
| 24 | * <bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.MessageDigestPasswordEncoder"> |
|
| 25 | * <constructor-arg value="MD5"/> |
|
| 26 | * </bean> |
|
| 27 | * </pre> |
|
| 28 | * </p> |
|
| 29 | * |
|
| 30 | * @author Ray Krueger |
|
| 31 | * @since 1.0.1 |
|
| 32 | */ |
|
| 33 | public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder { |
|
| 34 | ||
| 35 | private final String algorithm; |
|
| 36 | ||
| 37 | /** |
|
| 38 | * The digest algorithm to use |
|
| 39 | * Supports the named <a href="http://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html#AppA"> |
|
| 40 | * Message Digest Algorithms</a> in the Java environment. |
|
| 41 | * |
|
| 42 | * @param algorithm |
|
| 43 | */ |
|
| 44 | public MessageDigestPasswordEncoder(String algorithm) { |
|
| 45 | 7 | this(algorithm, false); |
| 46 | 6 | } |
| 47 | ||
| 48 | /** |
|
| 49 | * Convenience constructor for specifying the algorithm and whether or not to enable base64 encoding |
|
| 50 | * |
|
| 51 | * @param algorithm |
|
| 52 | * @param encodeHashAsBase64 |
|
| 53 | * @throws IllegalArgumentException if an unknown |
|
| 54 | */ |
|
| 55 | 7 | public MessageDigestPasswordEncoder(String algorithm, boolean encodeHashAsBase64) throws IllegalArgumentException { |
| 56 | 7 | this.algorithm = algorithm; |
| 57 | 7 | setEncodeHashAsBase64(encodeHashAsBase64); |
| 58 | //Validity Check |
|
| 59 | 7 | getMessageDigest(); |
| 60 | 6 | } |
| 61 | ||
| 62 | /** |
|
| 63 | * Encodes the rawPass using a MessageDigest. |
|
| 64 | * If a salt is specified it will be merged with the password before encoding. |
|
| 65 | * |
|
| 66 | * @param rawPass The plain text password |
|
| 67 | * @param salt The salt to sprinkle |
|
| 68 | * @return Hex string of password digest (or base64 encoded string if encodeHashAsBase64 is enabled. |
|
| 69 | */ |
|
| 70 | public String encodePassword(String rawPass, Object salt) { |
|
| 71 | 14 | String saltedPass = mergePasswordAndSalt(rawPass, salt, false); |
| 72 | ||
| 73 | 14 | MessageDigest messageDigest = getMessageDigest(); |
| 74 | ||
| 75 | 14 | byte[] digest = messageDigest.digest(saltedPass.getBytes()); |
| 76 | ||
| 77 | 14 | if (getEncodeHashAsBase64()) { |
| 78 | 6 | return new String(Base64.encodeBase64(digest)); |
| 79 | } else { |
|
| 80 | 8 | return new String(Hex.encodeHex(digest)); |
| 81 | } |
|
| 82 | } |
|
| 83 | ||
| 84 | /** |
|
| 85 | * Get a MessageDigest instance for the given algorithm. |
|
| 86 | * Throws an IllegalArgumentException if <i>algorithm</i> is unknown |
|
| 87 | * |
|
| 88 | * @return MessageDigest instance |
|
| 89 | * @throws IllegalArgumentException if NoSuchAlgorithmException is thrown |
|
| 90 | */ |
|
| 91 | protected final MessageDigest getMessageDigest() throws IllegalArgumentException { |
|
| 92 | try { |
|
| 93 | 21 | return MessageDigest.getInstance(algorithm); |
| 94 | 1 | } catch (NoSuchAlgorithmException e) { |
| 95 | 1 | throw new IllegalArgumentException("No such algorithm [" + algorithm + "]"); |
| 96 | } |
|
| 97 | } |
|
| 98 | ||
| 99 | /** |
|
| 100 | * Takes a previously encoded password and compares it with a rawpassword after mixing in the salt and |
|
| 101 | * encoding that value |
|
| 102 | * |
|
| 103 | * @param encPass previously encoded password |
|
| 104 | * @param rawPass plain text password |
|
| 105 | * @param salt salt to mix into password |
|
| 106 | * @return true or false |
|
| 107 | */ |
|
| 108 | public boolean isPasswordValid(String encPass, String rawPass, Object salt) { |
|
| 109 | 8 | String pass1 = "" + encPass; |
| 110 | 8 | String pass2 = encodePassword(rawPass, salt); |
| 111 | ||
| 112 | 8 | return pass1.equals(pass2); |
| 113 | } |
|
| 114 | ||
| 115 | public String getAlgorithm() { |
|
| 116 | 1 | return algorithm; |
| 117 | } |
|
| 118 | } |