/*
* Copyright 2012 JBoss, by Red Hat, Inc
*
* 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.jboss.pitbull.internal.nio.websocket.impl.oio.internal.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
* @author Mike Brock
*/
public final class Hash
{
private Hash()
{
}
final static String secureRandomAlgorithm = "SHA1PRNG";
final static String hashAlgorithm = "SHA1";
private final static ThreadLocal<SecureRandom> random = new ThreadLocal<SecureRandom>();
private static SecureRandom createRandom()
{
try
{
SecureRandom random = SecureRandom.getInstance(secureRandomAlgorithm);
random.setSeed(SecureRandom.getInstance(secureRandomAlgorithm).generateSeed(64));
return random;
}
catch (NoSuchAlgorithmException e)
{
throw new RuntimeException("runtime does not support secure random algorithm: " + secureRandomAlgorithm);
}
}
private static SecureRandom getRandom()
{
SecureRandom r = random.get();
if (r == null)
{
r = createRandom();
random.set(r);
}
return r;
}
public static int nextInt(int max)
{
return getRandom().nextInt(max);
}
public static void getRandomBytes(byte[] bytes)
{
getRandom().nextBytes(bytes);
}
public static String newUniqueHash()
{
return nextSecureHash(hashAlgorithm, SecureRandom.getSeed(128));
}
private static String nextSecureHash(final String algorithm, final byte[] additionalSeed)
{
try
{
final MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(String.valueOf(System.nanoTime()).getBytes());
if (additionalSeed != null)
{
md.update(additionalSeed);
}
byte[] randBytes = new byte[64];
getRandom().nextBytes(randBytes);
// 1,000 rounds.
for (int i = 0; i < 1000; i++)
{
md.update(md.digest());
}
return hashToHexString(md.digest());
}
catch (Exception e)
{
throw new RuntimeException("failed to generate session id hash", e);
}
}
private static String hashToHexString(byte[] hash)
{
final StringBuilder hexString = new StringBuilder(hash.length);
for (byte mdbyte : hash)
{
hexString.append(Integer.toHexString(0xFF & mdbyte));
}
return hexString.toString();
}
}