Это легко достижимо без каких-либо внешних библиотек.
Сначала вам нужен криптографический PRNG. Java имеет SecureRandom
, для которого обычно используется лучший источник энтропии на машине (например, /dev/random
). Подробнее читайте здесь.
SecureRandom rnd = new SecureRandom();
byte[] token = new byte[byteLength];
rnd.nextBytes(token);
Примечание: SecureRandom
- самый медленный, но наиболее безопасный способ в Java генерации случайных байтов. Тем не менее, я рекомендую НЕ рассматривать производительность здесь, поскольку она обычно не оказывает реального влияния на ваше приложение, если вам не нужно генерировать миллионы токенов в секунду.
Затем вам нужно решить, «как уникально» ваш токен. Целая и единственная точка рассмотрения энтропии заключается в том, чтобы убедиться, что система может противостоять атакам с использованием грубой силы: пространство возможных значений должно быть настолько большим, чтобы любой атакующий мог только попробовать незначительную долю значений в непухотное время 1 [/ д2]. Уникальные идентификаторы, такие как случайные UUID
, имеют 122 бит энтропии (т. Е. 2 ^ 122 = 5.3x10 ^ 36) - вероятность столкновения равна «* (...), чтобы существовала одна в миллиардной вероятности дублирования необходимо создать 103 триллиона версий UUID 2 ". Мы выберем 128 бит, так как он точно соответствует 16 байтам и считается достаточно высоким для того, чтобы быть уникальным для всех, но наиболее экстремальных, используемых случаев, и вам не нужно думать о дубликатах. Вот простая таблица сравнения энтропии, включая простой анализ проблемы рождения .
Для простых требований 8 или 12 длина байта может быть достаточной, но с 16 байтами вы находитесь на «безопасной стороне».
И это в основном это. Последнее стоит подумать о кодировании, чтобы его можно было представить в виде печатного текста (read, a String
).
Типичные кодировки включают в себя:
Base64
каждый символ кодирует 6 бит, создавая 33% служебных данных. К сожалению, стандартная реализация в JDK ( 7 и ниже отсутствует] - в Android и Java 8 + ). Но существует множество библиотек , которые добавляют это. Недостатком является то, что стандарт Base64
небезопасен, например. URL-адреса и имя файла в большинстве файловых систем, требующих дополнительного кодирования (например, url-кодирование ) или URL-адрес безопасной версии Base64 используется . Пример кодирования 16 байтов с заполнением: XfJhfv3C0P6ag7y9VQxSbw==
Base32
каждый символ кодирует 5 бит, создавая 40% служебных данных. Это будет использовать A-Z
и 2-7
, что делает его разумным пространственно эффективным, нечувствительным к регистру буквенно-цифровым. Стандартная реализация в JDK отсутствует. Пример кодирования 16 байтов без заполнения: WUPIL5DQTZGMF4D3NX5L7LNFOY
Base16
(шестнадцатеричный) каждый символ кодирует 4 бит, требующий 2 символа на каждый байт (т. Е. 16 байт создает строку длиной 32 ). Поэтому hex меньше пространства, чем Base32
, но безопасен для использования в большинстве случаев (url), поскольку он использует только 0-9
и A
- F
. Пример кодирования 16 байтов: 4fa3dd0f57cb3bf331441ed285b27735
. См. обсуждение SO о преобразовании в hex здесь. Дополнительные кодировки, такие как Base85 и экзотический Base122 существуют с лучшей / меньшей эффективностью пространства. Вы можете создать свою собственную кодировку (которая в основном отвечает большинству ответов в этом потоке), но я бы посоветовал это сделать, если у вас нет особых требований. См. больше схем кодирования в статье Википедии.
SecureRandom
hex
или base32
, если вам нужно, чтобы оно было буквенно-цифровым) Не
public static String generateRandomHexToken(int byteLength) {
SecureRandom secureRandom = new SecureRandom();
byte[] token = new byte[byteLength];
secureRandom.nextBytes(token);
return new BigInteger(1, token).toString(16); //hex encoding
}
//generateRandomHexToken(16) -> 2189df7475e96aa3982dbeab266497cd
Если вы хотите готовый к использованию инструмент cli, вы можете использовать кости: https://github.com/patrickfav/dice
jvmArgs('someValues')
Перейдите к «edit configurations». Убедитесь, что вы выбрали «приложение».
Проверьте флаги запуска. Удалите их все>: D
Дайте мне знать, как это делается