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();
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());
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());
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();
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();
090 }
091
092 private static long _reload() {
093 if (_reloadingFlag.compareAndSet(false, true)) {
094 _random.nextBytes(_bytes);
095
096 _index.set(0);
097
098 _reloadingFlag.set(false);
099 }
100
101 int offset = _index.get() % (_BUFFER_SIZE - 7);
102
103 long l = BigEndianCodec.getLong(_bytes, offset) ^ _gapSeed;
104
105 _gapSeed = l;
106
107 return l;
108 }
109
110 private static final int _BUFFER_SIZE;
111
112 private static final int _MIN_BUFFER_SIZE = 1024;
113
114 private static final byte[] _bytes;
115 private static final AtomicInteger _index = new AtomicInteger();
116 private static final Random _random = new SecureRandom();
117 private static final AtomicBoolean _reloadingFlag = new AtomicBoolean();
118
119 static {
120 int bufferSize = GetterUtil.getInteger(
121 System.getProperty(
122 SecureRandomUtil.class.getName() + ".buffer.size"));
123
124 if (bufferSize < _MIN_BUFFER_SIZE) {
125 bufferSize = _MIN_BUFFER_SIZE;
126 }
127
128 _BUFFER_SIZE = bufferSize;
129
130 _bytes = new byte[_BUFFER_SIZE];
131
132 _random.nextBytes(_bytes);
133
134 _gapSeed = _random.nextLong();
135 }
136
137 private static long _gapSeed;
138
139 }