/* * Copyright 2016 gitblit.com * * 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 com.gitblit.utils; /** * Wrapper class for java.security.SecureRandom, which will periodically reseed * the PRNG in case an instance of the class has been running for a long time. * * @author Florian Zschocke */ public class SecureRandom { /** Period (in ms) after which a new SecureRandom will be created in order to get a fresh random seed. */ private static final long RESEED_PERIOD = 24 * 60 * 60 * 1000; /* 24 hours */ private long last; private java.security.SecureRandom random; public SecureRandom() { // Make sure the SecureRandom is seeded right from the start. // This also lets any blocks during seeding occur at creation // and prevents it from happening when getting next random bytes. seed(); } public byte[] randomBytes(int num) { byte[] bytes = new byte[num]; nextBytes(bytes); return bytes; } public void nextBytes(byte[] bytes) { random.nextBytes(bytes); reseed(false); } void reseed(boolean forced) { long ts = System.currentTimeMillis(); if (forced || (ts - last) > RESEED_PERIOD) { last = ts; runReseed(); } } private void seed() { random = new java.security.SecureRandom(); random.nextBytes(new byte[0]); last = System.currentTimeMillis(); } private void runReseed() { // Have some other thread hit the penalty potentially incurred by reseeding, // so that we can immediately return and not block the operation in progress. new Thread() { public void run() { seed(); } }.start(); } }