This question already has answers here:
Creating a unique alphanumeric 10-character string
(7 answers)
Closed 8 years ago.
I need to create alphanumeric unique IDs of length 7 or 10. Similar to the shorter version of Git commit IDs (7a471b2).
I tried UUID, but the generated unique ID is longer than I need.
Is there a built-in method / code snippet in Java that can help here?
If you want to generate random values you should use SecureRandom
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[15];
random.nextBytes(bytes);
To get the proper key length you may want to convert that into your expected from. The characters are also number, so you can generate longer random value and afterward just encode it. You may want to use Base64 or hext for that. In Java you use DatatypeConverter
String key = DatatypeConverter.printBase64Binary(random);
our use Apache
org.apache.commons.codec.binary.Base64
String key = new String(Base64.encodeBase64(random));
There is not Java class that support generation of random values in that form.
You did not mention whether you need the number to be generated in a state-less manner. You only need this if you have many sources generating IDs whereas each source is independent and does not know of any state of any other sources. For such a case UUID allows to generate ID's that yre still very unlikely to collide.
If you are the only source generating ID's, then you can make use of state. As an example, in a database you often simply use a sequence to generate IDs (the state being the nextval of the sequence). These numbers are perfectly unique too. If you need it to "look" random, there are algorithms to shuffle the number space by mapping each sequential number onto a random-looking number.
A second example of "state" is the set of all IDs already in use. You can use this by generating a "random" number in an arbitrarily primitive way and then matching it against all your existing numbers. If it collides, generate another one.
Try Apache lang RandomStringUtils class
This is not as simple as it looks like. First of all UUID is not 100% unique.
It can only produce 2^128 unique numbers (I might be wrong about the 128 number. But you get the idea).
Making it shorter will only increase the probability of repetition.
The best way I could think of right now is to take the UUID and use some base64 encoder over it.
[EDIT] Alternatively, use Random.nextInt and increment by one each time you need a new ID.
Related
I am trying to implement code that generates FHIR message from some type of input message. When I create each FHIR resources, I would need to create resource logical id that are unique and repeatedly generated.
From Microsoft's FHIR-Converter github repository, I found that they use SHA256 to hash the input string value to generate some type of 64 character id. I used the same approach to generate UUID in java. Here is code from Microsoft FHIR-Converter in .NET:
public static string GenerateUUID(string input)
{
if (string.IsNullOrWhiteSpace(input))
{
return null;
}
var bytes = Encoding.UTF8.GetBytes(input);
var algorithm = SHA256.Create();
var hash = algorithm.ComputeHash(bytes);
var guid = new byte[16];
Array.Copy(hash, 0, guid, 0, 16);
return new Guid(guid).ToString();
}
It generates uuid like this: e40b96a6-e62e-a67e-3ac7-69a099830e1c
My questions are:
In order to repeatedly generate the same id, does the string input MUST be same as well? Meaning, if I have an input of 123, it will generate e40b96a6-e62e-a67e-3ac7-69a099830e1c all the time?
If I HAVE to use unique id in order to generate this uuid, what is the advantage of using this extra step? If my input always have unique id for each resources, can I just assign id to be (Resource name)-(id)?
Is there a way to generate id without having unique id? I have some resources that do not have something unique. Are there other techniques where I can generate a unique input that can be repeated in different platforms? I don't see how I can do this without providing unique id from input..
A given string will always generate the same id. A different string should generate a different id, though there's a very slim chance of two strings generating the same hash.
There are rules for the format of the id (only certain characters permitted, maximum length allowed), but other than that, no obvious benefit I can see. It's fine to use your 'native' identifier as the resource id. (That said, resource ids generally shouldn't be real-world identifiers like social security numbers, license numbers, etc. as that can leak protected information.)
The expectation in FHIR is that a unique resource id corresponds to a unique real-world object. If you don't have a real identifier on the object, there's a possibility you could have multiple instances that correspond to distinct real-world objects. E.g. multiple Practitioner instances where all you have is a name of "A. Smith" would not be appropriate to presume are always the same instance. If you have no 'identity', you might be better off using the 'contained' mechanism rather than generating an id just from the content.
I have a Java service that generates a 16 digit unique number using current time in the format yymmddhhmmssmsms. And it handles multiple calls on the same mili-second using Atomic Long.
But now the problem is that I need this service on multiple cloud machines. How can I handle calls at the same microsecond on different servers and generate a unique number for each of this calls.
And I dont want to use database for this.
EDIT:
I understand UUID can be a solution. But UUID generates a random no. everytime, not unique, though the chances of collision are very low.
A think, you can try to use UUID.randomUUID() object
The UUID v4 is the right choice for distributed systems.
The UUID v4 implementation uses random numbers as the source. The Java
implementation is SecureRandom – which uses an unpredictable value as
the seed to generate random numbers to reduce the chance of
collisions.
Source: https://www.baeldung.com/java-uuid
Secure Random: This class provides a cryptographically strong random number generator (RNG). Source: https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html
Example how to use the UUID:
UUID uuid = UUID.randomUUID();
Using a random number alone (such as a random UUID) should only be done if—
you have a way to check the number for uniqueness across all calls, or
you can tolerate the risk of generating the same number for different calls.
If you find it appropriate, try assigning each server a unique number (e.g., by requesting a unique number from a central database). Then each server can generate a unique ID for each call it makes by appending a random number to that unique number; this may work well because the server can now more easily check the IDs it then generates for uniqueness, as no further contact with a central database or other servers is required.
See also my section on generating unique random identifiers.
I need to make a servlet service that does following things
when user request the service, servlet generates a unique 5 letter string that has never been generated. (combination of 0~9 and a~Z)
if user accepts it, save user's info using the unique string(that #1 generated) as a primary key
First thing popped in my head was using static class variable that increments by 1 as requests hit servlet, but searching here and google says this is really really bad idea, as if multiple users hit the service at the same time, it will break...
and now I am clueless what to look into.
What would be the best and the safetest approach to generate a unique string incrementally?
Add a field sequence no in table and when ever a new request comes get the highest sequence number from database and then add one ie plus 1 and save it
According to this site, your highest number (ZZZZZ) is 426088025. In the database world you'd want to used a sequence but, because of your 5 character restriction, you need to make sure that it doesn't go over this number (hopefully you're storing less than 426M records).
To create a sequence you'll do something like:
create sequence your_sequence maxvalue 426088025 no cycle
That is the PostgreSQL syntax - your database may vary.
Then, in your code you can do a
select nextval('your_sequence')
to get your value and then Base64 encode this value. In PostgreSQL the "no cycle" means that if you get to the max it will throw an error.
In Java 8, Base64 is included:
import java.util.Base64;
...
String userNumber = Base64.getEncoder().encodeToString(Integer.toString(integerFromSequenceSelect));
Otherwise, if you're stuck with an old version of Java, use Apache Commons Codec and run:
import org.apache.commons.codec.binary.Base64;
...
String userNumber = Base64.encodeBase64String(Integer.toString(integerFromSequenceSelect));
I am looking for mechanism to generate random unique alpha numeric key for resetting user password.
I've goggled a lot in this direction, but looks like this thing is not obvious thing.
I've tried something like that:
new String(encodeBase64URLSafe(UUID.randomUUID()));
But after reading the following article: Is UUID.randomUUID() suitable for use as a one-time password? looks like that this way is not fully correct.
It would be really appreciate if you answer on the following questions:
Which is secure way to generate such token using UUID?
Do we need to convert UUID string to base64 in order to have safe URLs or it would be enough to remove dashes from generated string?
Would be it correct to use mechanism from this link in such purpouses How to generate a random alpha-numeric string?, why?
Using an UUID is safe and secure. The linked article just says that an UUID is maybe a little too much for this kind of security. But well ... if you are "too" secure, no one will blame you.
An UUID is just alpha numeric characters and dashes. So if you need to put it in a query string or an URL, you have nothing to escape. You can remove the dashes to save some space if you want. But it is not required.
This mechanism is secure too. Both (UUID and this one) will works.
For this kind of security, all you have to do is to ensure that your token is randomly generated (even partially).
Reading document, I saw there are four types of uuid. I am wondering how to generate type 1(timestamp based) and type2 (DCE security based) uuid. Any idea?
You can also implement your own if for whatever reason you don't want to use JUG (as suggested above).
For this check the class UUID. You need to use System.nanoTime() and ensure successive calls return increasing values (so if you get two times the same time value, then return the greatest returned value so far plus 1).
The layout of the UUID type 1 can be found in: http://www.ietf.org/rfc/rfc4122.txt