I've been looking for a simple Java algorithm to generate a pseudo-random alpha-numeric string. In my situation it would be used as a unique session/key identifier that would "likely" be unique over 500K+ generation (my needs don't really require anything much more sophisticated). Ideally, I would be able to specify a length depending on my uniqueness needs. For example, a generated string of length 12 might look something like "AEYGF7K0DM1X"
.
相关问题
- Delete Messages from a Topic in Apache Kafka
- Jackson Deserialization not calling deserialize on
- How to maintain order of key-value in DataFrame sa
- StackExchange API - Deserialize Date in JSON Respo
- Difference between Types.INTEGER and Types.NULL in
This is easily achievable without any external libraries.
1. Cryptographic Pseudo Random Data Generation
First you need a cryptographic PRNG. Java has
SecureRandom
for that typically uses the best entropy source on the machine (e.g./dev/random
) . Read more here.Note:
SecureRandom
is the slowest, but most secure way in Java of generating random bytes. I do however recommend NOT considering performance here since it usually has no real impact on your application unless you have to generate millions of tokens per second.2. Required Space of Possible Values
Next you have to decide "how unique" your token needs to be. The whole and only point of considering entropy is to make sure that the system can resist brute force attacks: the space of possible values must be so large that any attacker could only try a negligible proportion of the values in non-ludicrous time1. Unique identifiers such as random
UUID
have 122bit of entropy (ie. 2^122 = 5.3x10^36) - the chance of collision is "*(...) for there to be a one in a billion chance of duplication, 103 trillion version 4 UUIDs must be generated2". We will choose 128 bit since it fits exactly into 16 bytes and is seen as highly sufficient for being unique for basically every, but the most extreme, use cases and you don't have to think about duplicates. Here is a simple comparison table of entropy including simple analysis of the birthday problem.For simple requirements 8 or 12 byte length might suffice, but with 16 bytes you are on the "safe side".
And that's basically it. Last thing is to think about encoding so it can be represented as a printable text (read, a
String
).3. Binary to Text Encoding
Typical encodings include:
Base64
every character encodes 6bit creating a 33% overhead. Unfortunatly there is no standard implementation in the JDK (7 and below - there is in Android and Java 8+). But numerous libraries exist that add this. The downside is, that standardBase64
is not safe for eg. urls and as filename in most file systems requiring additional encoding (e.g. url encoding) or the URL safe version of Base64 is used. Example encoding 16 bytes with padding:XfJhfv3C0P6ag7y9VQxSbw==
Base32
every character encodes 5bit creating a 40% overhead. This will useA-Z
and2-7
making it reasonably space efficient while being case-insensitive alpha-numeric. There is no standard implementation in the JDK. Example encoding 16 bytes without padding:WUPIL5DQTZGMF4D3NX5L7LNFOY
Base16
(hex) every character encodes 4bit requiring 2 characters per byte (ie. 16 byte create a string of length 32). Therefore hex is less space efficient thanBase32
but is safe to use in most cases (url) since it only uses0-9
andA
toF
. Example encoding 16 bytes:4fa3dd0f57cb3bf331441ed285b27735
. See a SO discussion about converting to hex here.Additional encodings like Base85 and the exotic Base122 exist with better/worse space efficiency. You can create your own encoding (which basically most answers in this thread do) but I would advise against it, if you don't have very specific requirements. See more encoding schemes in the Wikipedia article.
4. Summary and Example
SecureRandom
hex
orbase32
if you need it to be alpha-numeric)Don't
Example: Hex Token Generator
Example: Tool
If you want a ready-to-use cli tool you may use dice: https://github.com/patrickfav/dice
I found this solution that generates a random hex encoded string. The provided unit test seems to hold up to my primary use case. Although, it is slightly more complex than some of the other answers provided.
Here is the one line code by AbacusUtil
Random doesn't mean it must be unique. to get unique strings, using:
If you're happy to use Apache classes, you could use
org.apache.commons.text.RandomStringGenerator
(commons-text).Example:
Since commons-lang 3.6,
RandomStringUtils
is deprecated.A short and easy solution, but uses only lowercase and numerics:
The size is about 12 digits to base 36 and can't be improved further, that way. Of course you can append multiple instances.
An alternative in Java 8 is: