/*
* Aphelion
* Copyright (c) 2013 Joris van der Wel
*
* This file is part of Aphelion
*
* Aphelion is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* Aphelion is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Aphelion. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, the following supplemental terms apply, based on section 7 of
* the GNU Affero General Public License (version 3):
* a) Preservation of all legal notices and author attributions
* b) Prohibition of misrepresentation of the origin of this material, and
* modified versions are required to be marked in reasonable ways as
* different from the original version (for example by appending a copyright notice).
*
* Linking this library statically or dynamically with other modules is making a
* combined work based on this library. Thus, the terms and conditions of the
* GNU Affero General Public License cover the whole combination.
*
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent modules,
* and to copy and distribute the resulting executable under terms of your
* choice, provided that you also meet, for each linked independent module,
* the terms and conditions of the license of that module. An independent
* module is a module which is not derived from or based on this library.
*/
package aphelion.shared.swissarmyknife;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A wrapper around java.security.SecureRandom which provides some
* functions to easily add seeds (entropy) from various sources.
*
* Entropy can never be decreased by calling one of these functions.
* It is safe to call these functions often, even on user input.
*
* No single user should be able to predict all seeds that are added
* using these functions.
*
* @author Joris
*/
public class MySecureRandom
{
private MySecureRandom() {}
static
{
initialize();
}
private static SecureRandom rand;
private static Charset utf16;
private static void initialize()
{
// http://www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securerandom/
try
{
rand = SecureRandom.getInstance("SHA1PRNG", "SUN");
}
catch (NoSuchAlgorithmException ex)
{
Logger.getLogger(MySecureRandom.class.getName()).log(Level.SEVERE, null, ex);
throw new Error(ex); // should never happen
}
catch (NoSuchProviderException ex)
{
Logger.getLogger(MySecureRandom.class.getName()).log(Level.SEVERE, null, ex);
throw new Error(ex); // should never happen
}
// Call the built in seed
rand.nextBoolean();
utf16 = Charset.forName("UTF-16"); // may throw
}
// A few methods to add entropy:
/** Adds entropy by seeding using the clock */
@ThreadSafe
public static void addTimeSeed()
{
rand.setSeed(System.currentTimeMillis());
rand.setSeed(System.nanoTime());
}
/** Adds entropy by seeding using a hostname
* @param addr An unresolved or resolved hostname. The port is not used
*/
@ThreadSafe
public static void addSeed(InetAddress addr)
{
rand.setSeed( addr.getHostAddress().getBytes(utf16) );
}
/** Adds entropy by seeding using a hostname
* @param addr An unresolved or resolved hostname. The port is not used
*/
@ThreadSafe
public static void addSeed(InetSocketAddress addr)
{
addSeed(addr.getAddress());
}
/** Adds entropy by seeding using an integer.
* For example, from a config file
* @param n
*/
@ThreadSafe
public static void addSeed(long n)
{
rand.setSeed(n);
}
@ThreadSafe
public static void nextBytes(byte[] bytes)
{
rand.nextBytes(bytes);
}
@ThreadSafe
public static long nextLong()
{
return rand.nextLong();
}
}