001
014
015 package com.liferay.portal.kernel.security;
016
017 import com.liferay.portal.kernel.io.BigEndianCodec;
018 import com.liferay.portal.kernel.util.GetterUtil;
019
020 import java.security.SecureRandom;
021
022 import java.util.Random;
023 import java.util.concurrent.atomic.AtomicBoolean;
024 import java.util.concurrent.atomic.AtomicInteger;
025
026
029 public class SecureRandomUtil {
030
031 public static boolean nextBoolean() {
032 byte b = nextByte();
033
034 if (b < 0) {
035 return false;
036 }
037 else {
038 return true;
039 }
040 }
041
042 public static byte nextByte() {
043 int index = _index.getAndIncrement();
044
045 if (index < _BUFFER_SIZE) {
046 return _bytes[index];
047 }
048
049 return (byte)_reload(index);
050 }
051
052 public static double nextDouble() {
053 int index = _index.getAndAdd(8);
054
055 if ((index + 7) < _BUFFER_SIZE) {
056 return BigEndianCodec.getDouble(_bytes, index);
057 }
058
059 return Double.longBitsToDouble(_reload(index));
060 }
061
062 public static float nextFloat() {
063 int index = _index.getAndAdd(4);
064
065 if ((index + 3) < _BUFFER_SIZE) {
066 return BigEndianCodec.getFloat(_bytes, index);
067 }
068
069 return Float.intBitsToFloat((int)_reload(index));
070 }
071
072 public static int nextInt() {
073 int index = _index.getAndAdd(4);
074
075 if ((index + 3) < _BUFFER_SIZE) {
076 return BigEndianCodec.getInt(_bytes, index);
077 }
078
079 return (int)_reload(index);
080 }
081
082 public static long nextLong() {
083 int index = _index.getAndAdd(8);
084
085 if ((index + 7) < _BUFFER_SIZE) {
086 return BigEndianCodec.getLong(_bytes, index);
087 }
088
089 return _reload(index);
090 }
091
092 private static long _reload(int index) {
093 if (_reloadingFlag.compareAndSet(false, true)) {
094 _random.nextBytes(_bytes);
095
096 _gapRandom.setSeed(_random.nextLong());
097
098 _index.set(0);
099
100 _reloadingFlag.set(false);
101 }
102
103 return _gapRandom.nextLong() ^
104 BigEndianCodec.getLong(
105 _bytes, Math.abs(index % (_BUFFER_SIZE - 7)));
106 }
107
108 private static final int _BUFFER_SIZE;
109
110 private static final int _MIN_BUFFER_SIZE = 1024;
111
112 private static final byte[] _bytes;
113 private static final Random _gapRandom = new Random();
114 private static final AtomicInteger _index = new AtomicInteger();
115 private static final Random _random = new SecureRandom();
116 private static final AtomicBoolean _reloadingFlag = new AtomicBoolean();
117
118 static {
119 int bufferSize = GetterUtil.getInteger(
120 System.getProperty(
121 SecureRandomUtil.class.getName() + ".buffer.size"));
122
123 if (bufferSize < _MIN_BUFFER_SIZE) {
124 bufferSize = _MIN_BUFFER_SIZE;
125 }
126
127 _BUFFER_SIZE = bufferSize;
128
129 _bytes = new byte[_BUFFER_SIZE];
130
131 _random.nextBytes(_bytes);
132
133 _gapRandom.setSeed(_random.nextLong());
134 }
135
136 }