/*
 * Copyright 2011 the original author or authors.
 *
 * 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.springframework.security.crypto.password;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

/**
 * Helper for working with the MessageDigest API.
 *
 * Performs the configured number of iterations of the hashing algorithm per digest to aid
 * in protecting against brute force attacks.
 *
 * @author Keith Donald
 * @author Luke Taylor
 */
final class Digester {

	private final MessageDigest messageDigest;

	private final int iterations;

	/**
	 * Create a new Digester.
	 * @param algorithm the digest algorithm; for example, "SHA-1" or "SHA-256".
	 * @param iterations the number of times to apply the digest algorithm to the input
	 */
	public Digester(String algorithm, int iterations) {
		try {
			messageDigest = MessageDigest.getInstance(algorithm);
		}
		catch (NoSuchAlgorithmException e) {
			throw new IllegalStateException("No such hashing algorithm", e);
		}

		this.iterations = iterations;
	}

	public byte[] digest(byte[] value) {
		synchronized (messageDigest) {
			for (int i = 0; i < iterations; i++) {
				value = messageDigest.digest(value);
			}
			return value;
		}
	}
}

@@ -750,54 +750,8 @@
 ion;
-%0Aimport java.security.NoSuchProviderException;
 %0A%0A/*
@@ -1039,35 +1039,24 @@
 nal 
-MessageDigest messageDigest
+String algorithm
 ;%0A%0A%09
@@ -1345,186 +1345,98 @@
 %7B%0A%09%09
-try %7B%0A%09%09%09messageDigest = MessageDigest.getInstance(algorithm);%0A%09%09%7D%0A%09%09catch (NoSuchAlgorithmException e) %7B%0A%09%09%09throw new IllegalStateException(%22No such hashing algorithm%22, e);%0A%09%09%7D%0A
+// eagerly validate the algorithm%0A%09%09createDigest(algorithm);%0A%09%09this.algorithm = algorithm;
 %0A%09%09t
@@ -1512,40 +1512,63 @@
 %7B%0A%09%09
-synchronized (messageDigest) %7B%0A%09
+MessageDigest messageDigest = createDigest(algorithm);%0A
 %09%09fo
@@ -1607,17 +1607,16 @@
 +) %7B%0A%09%09%09
-%09
 value = 
@@ -1650,26 +1650,258 @@
 ;%0A%09%09
-%09%7D%0A%09%09%09return value
+%7D%0A%09%09return value;%0A%09%7D%0A%0A%09private static MessageDigest createDigest(String algorithm) %7B%0A%09%09try %7B%0A%09%09%09return MessageDigest.getInstance(algorithm);%0A%09%09%7D%0A%09%09catch (NoSuchAlgorithmException e) %7B%0A%09%09%09throw new IllegalStateException(%22No such hashing algorithm%22, e)
 ;%0A%09%09

Improve StandardPasswordEncoder performance