Is there a way/algorithm/method to generate a new Guid (x) using our old GUid (y) and then get y back whenever we want from x?
Something similar to below answer but it shows a way to old Guid(I can consider it as a string) to convert to Guid but not a way back.
https://stackoverflow.com/a/9386095/5887074
How can I generate a GUID for a string?
P.S.: This is not related to anything security. The two Guids will just be used to find records from the table. We can convert Guid to string in this conversion if required.
There are thousands of ways: a guid is 128 bits, so you could flip one bit which would make it simple to translate back and forth. Or you could do modulo 42 and make it look as if you made something unpredictable. Or you could reverse the order of the bits, do a NOT operation on all of them or rearrange the bits by some predefined pattern.
But I suspect that you have a use case which you do not define. Please tell a bit more about the problem you want to solve. Your request sounds a little bit dangerous as it sounds as if you want to enable some kind of tracking between seemingly unrelated entities. If there is some security issues involved you are very likely to get it wrong if both cleartext (guid pre translation) and cipher (guid after translation) are public. Perhaps simple AES encryption would suffice as a translation function, but I think you need to specify you problems in much more details to get a useful answer.
Related
I'm looking at using a Guid as a random anonymous visitor identifier for a website (stored both as a cookie client-size, and in a db server-side), and I wanted a cryptographically strong way of generating Guids (so as to minimize the chance of collisions).
For the record, there are 16 bytes (or 128 bits) in a Guid.
This is what I have in mind:
/// <summary>
/// Generate a cryptographically strong Guid
/// </summary>
/// <returns>a random Guid</returns>
private Guid GenerateNewGuid()
{
byte[] guidBytes = new byte[16]; // Guids are 16 bytes long
RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
random.GetBytes(guidBytes);
return new Guid(guidBytes);
}
Is there a better way to do this?
Edit:
This will be used for two purposes, a unique Id for a visitor, and a transaction Id for purchases (which will briefly be the token needed for viewing/updating sensitive information).
In answer to the OP's actual question whether this is cryptographically strong, the answer is yes since it is created directly from RNGCryptoServiceProvider. However the currently accepted answer provides a solution that is most definitely not cryptographically secure as per this SO answer:
Is Microsoft's GUID generator cryptographically secure.
Whether this is the correct approach architecturally due to theoretical lack of uniqueness (easily checked with a db lookup) is another concern.
So, what you're building is not technically a GUID. A GUID is a Globally Unique Identifier. You're building a random string of 128 bits. I suggest, like the previous answerer, that you use the built-in GUID generation methods. This method has a (albeit tremendously small) chance of generating duplicate GUID's.
There are a few advantages to using the built-in functionality, including cross-machine uniqueness [partially due to the MAC Address being referenced in the guid, see here: http://en.wikipedia.org/wiki/Globally_Unique_Identifier.
Regardless of whether you use the built in methods, I suggest that you not expose the Purchase GUID to the customer. The standard method used by Microsoft code is to expose a Session GUID that identifies the customer and expires comparatively quickly. Cookies track customer username and saved passwords for session creation. Thus your 'short term purchase ID' is never actually passed to (or, more importantly, received from) the client and there is a more durable wall between your customers' personal information and the Interwebs at large.
Collisions are theoretically impossible (it's not Globally Unique for nothing), but predictability is a whole other question. As Christopher Stevenson correctly points out, given a few previously generated GUIDs it actually becomes possible to start predicting a pattern within a much smaller keyspace than you'd think. GUIDs guarantee uniqueness, not predictability. Most algorithms take it into account, but you should never count on it, especially not as transaction Id for purchases, however briefly. You're creating an open door for brute force session hijacking attacks.
To create a proper unique ID, take some random stuff from your system, append some visitor specific information, and append a string only you know on the server, and then put a good hash algorithm over the whole thing. Hashes are meant to be unpredictable and unreversable, unlike GUIDs.
To simplify: if uniqueness is all you care about, why not just give all your visitors sequential integers, from 1 to infinity. Guaranteed to be unique, just terribly predictable that when you just purchased item 684 you can start hacking away at 685 until it appears.
To avoid collisions:
If you can't keep a global count, then use Guid.NewGuid().
Otherwise, increment some integer and use 1, 2, 3, 4...
"But isn't that ridiculously easy to guess?"
Yes, but accidental and deliberate collisions are different problems with different solutions, best solved separately, note least because predictability helps prevent accidental collision while simultaneously making deliberate collision easier.
If you can increment globally, then number 2 guarantees no collisions. UUIDs were invented as a means to approximate that without the ability to globally track.
Let's say we use incrementing integers. Let's say the ID we have in a given case is 123.
We can then do something like:
private static string GetProtectedID(int id)
{
using(var sha = System.Security.Cryptography.SHA1.Create())
{
return string.Join("", sha.ComputeHash(Encoding.UTF8.GetBytes(hashString)).Select(b => b.ToString("X2"))) + id.ToString();
}
}
Which produces 09C495910319E4BED2A64EA16149521C51791D8E123. To decode it back to the id we do:
private static int GetIDFromProtectedID(string str)
{
int chkID;
if(int.TryParse(str.Substring(40), out chkID))
{
string chkHash = chkID.ToString() + "this is my secret seed kjٵتשڪᴻᴌḶḇᶄ™∞ﮟﻑfasdfj90213";
using(var sha = System.Security.Cryptography.SHA1.Create())
{
if(string.Join("", sha.ComputeHash(Encoding.UTF8.GetBytes(hashString)).Select(b => b.ToString("X2"))) == str.Substring(0, 40))
return chkID;
}
}
return 0;//or perhaps raise an exception here.
}
Even if someone guessed from that they were given number 123, it wouldn't let them deduce that the id for 122 was B96594E536C9F10ED964EEB4E3D407F183FDA043122.
Alternatively, the two could be given as separate tokens, and so on.
I generally just use Guid.NewGuid();
http://msdn.microsoft.com/en-us/library/system.guid.newguid(v=vs.110).aspx
I'm looking to generate unique ids for identifying some data in my system. I'm using an elaborate system which concatenates some (non unique, relevant) meta-data with System.Guid.NewGuid()s. Are there any drawbacks to this approach, or am I in the clear?
I'm looking to generate unique ids for identifying some data in my system.
I'd recommend a GUID then, since they are by definition globally unique identifiers.
I'm using an elaborate system which concatenates some (non unique, relevant) meta-data with System.Guid.NewGuid(). Are there any drawbacks to this approach, or am I in the clear?
Well, since we do not know what you would consider a drawback, it is hard to say. A number of possible drawbacks come to mind:
GUIDs are big: 128 bits is a lot of bits.
GUIDs are not guaranteed to have any particular distribution; it is perfectly legal for GUIDs to be generated sequentially, and it is perfectly legal for the to be distributed uniformly over their 124 bit space (128 bits minus the four bits that are the version number of course.) This can have serious impacts on database performance if the GUID is being used as a primary key on a database that is indexed into sorted order by the GUID; insertions are much more efficient if the new row always goes at the end. A uniformly distributed GUID will almost never be at the end.
Version 4 GUIDs are not necessarily cryptographically random; if GUIDs are generated by a non-crypto-random generator, an attacker could in theory predict what your GUIDs are when given a representative sample of them. An attacker could in theory determine the probability that two GUIDs were generated in the same session. Version one GUIDs are of course barely random at all, and can tell the sophisticated reader when and where they were generated.
And so on.
I am planning a series of articles about these and other characteristics of GUIDs in the next couple of weeks; watch my blog for details.
UPDATE: https://ericlippert.com/2012/04/24/guid-guide-part-one/
When you use System.Guid.NewGuid(), you may still want to check that the guid doesn't already exist in your system.
While a guid is so complex as to be virtually unique, there is nothing to guarantee that it doesn't already exist except probability. It's just incredibly statistically unlikely, to the point that in almost any case it's the same as being unique.
Generating to identical guids is like winning the lottery twice - there's nothing to actually prevent it, it's just so unlikely it might as well be impossible.
Most of the time you could probably get away with not checking for existing matches, but in a very extreme case with lots of generation going on, or where the system absolutely must not fail, it could be worth checking.
EDIT
Let me clarify a little more. It is highly, highly unlikely that you would ever see a duplicate guid. That's the point. It's "globally unique", meaning there's such an infinitesimally chance of a duplicate that you can assume it will be unique. However, if we are talking about code that keeps an aircraft in the sky, monitors a nuclear reactor, or handles life support on the International Space Station, I, personally, would still check for a duplicate, just because it would really be terrible to hit that edge case. If you're just writing a blog engine, on the other hand, go ahead, use it without checking.
Feel free to use NewGuid(). There is no problem with its uniqueness.
There is too low probability that it will generate the same guid twice; a nice example can be found here: Simple proof that GUID is not unique
var bigHeapOGuids = new Dictionary<Guid, Guid>();
try
{
do
{
Guid guid = Guid.NewGuid();
bigHeapOGuids.Add(guid ,guid );
} while (true);
}
catch (OutOfMemoryException)
{
}
At some point it just crashed on OutOfMemory and not on duplicated key conflict.
I am working on a short URL app, where the token must identify 2 values: the link ID and the user ID. Ideally this token should be short.
For example, considering the URL http://sho.rt/15qq6, the token "15qq6" must identify the link and user ID.
I guess one option is to insert both values in a table and use the auto-generated ID as a token, but I would rather not. I would prefer a solution involving encryption.
How could I use the .NET encryption classes for such purpose, if possible? Many thanks for your help.
I'm not clear on how short you want your code. I posted some code online to encrypt any number of query arguments.
The result could be shortened by base64-encoding the result. That might still not be short enough for you though. (Note that I didn't base64-encode it because I had some concerns about base64 encoding is case-sensitive.)
Another approach would be to come up with a code that consists of an ID into your database and some sort of checksum. If the user tries modifying the ID, you could detect this. However, this approach may not be that secure since it might not be that hard to figure out how to create your own checksums.
Short answer is "You can't", at least, not easily.
Encryption typically doesn't change the length of the data being encrypted. So if you take the URL and UserId that you want to encode and encrypt them you'll end up with a token that's the same total length.
You could try compressing the data before encryption, but there's not a lot of redundancy in a single URL, and this won't buy you much.
You culd hash the data to give you a shorter result, but there's no way to reverse this process to get your URL and userId back.
If it's a short token you need then the only real option I can think of is a lookup table on the server, using the token as the key.
I don't think you understand exactly how Encryption works.
Encryption is just a technique for making it difficult to decode the response, without knowing the original encryption key.
The encrypted data is at least as long as the original data, if not larger.
There is no viable way of encoding a URL into a smaller amount of data, that's still valid in a URL.
Use a database for this, that's what they're for.
Edit: D'oh, Andrew beat me to it with a better response after editing.
You could use something like the RNGCryptoServiceProvider to generate a unique set of characters. Use a few constants strings holding a range of characters like "a" to "z", "A" to "Z", and "1" to "9". Save the randomly mixed case alphanumeric string with the original URL and UserID.
Generate random token and save link and user id in db for this token. It is security enough.
If you don't need encryption, than simple combination of Convert.ToBase64String and BitConverter.GetBytes will give you reasonable string. Note that Base64 uses some non-url cahnracters, so consider replacing them in result WikiPedia Base64, or using Base32 encoding.
int first =1234;
int second =789;
var encoded = Convert.ToBase64String(
BitConverter.GetBytes (((ulong)first<<32)+(ulong)second));
I'm working on a mobile app and i want to optimise the data that it's receiving from the server (as JSON).
There are 3 lists returned (each containing its own class of objects, the approximate list sizes are 50, 100 and 170). Each object has a Guid id and there is some relation data for each object. E.g.:
o = { Id = "8f088552-5b24-4ba4-a6e5-8958c4353581",
RelatedIds = ["19d2e562-0874-473f-8e05-7052e8defd9a", "615b4c47-199a-4f7d-8268-08ed43d9c891", ... ] }
Is there a way to compress these Guids to something sorter without storing an identity map? Perhaps using a hash function?
You can convert the 16-byte representation of a GUID into a Base 64 string. However you didn't mention a programming language so we can't help further.
A hash function is not recommended here because hash functions are generally lossy.
No. One of the attributes of (non-cryptographic) hashes is that they collide: hash(a) == hash(b) but a != b. They are a performance optimization in the case where you are doing a lot of equality checks and you expect many false results (because if hash(a) != hash(b) then a != b). A GUID->counter map is probably the best way to get smaller ids here.
You can convert hex (base16) to base64, and remove all the punctuation. You should save 25% for using base64, and another 4 bytes for punctuation.
Thinking about it some more i've realized that HTTP compression (if enabled) is probably going to compress that data well enough anyway, so it's not really worth the effort to compress data manually.
hey guys i want to generate unique base62 hashes - something similar to what tinyurl and bit.ly do using c#. this would be based on an auto increment field ID of type bigint (like most of these sites)
min chars would be 1 and max chars would be 6... if you had to write the fastest code (least amount of cpu usage) in c# for this hash how would you write it?
Please see my answer to another Stack Overflow question which is similar, here:
Need a smaller alternative to GUID for DB ID but still unique and random for URL
I posted a C# class called "ShortCodes", that does exactly what you're looking for, i.e. generate a unique baseX (where X is anything you like!) hash based upon a integer/long number, and also to convert back again.
I actually wrote this little class precisely to mimic the short code/hash generation of sites like TinyUrl.com and Bit.ly for my own purposes.
I can't say if this is the absolute fastest way of achieving this, but it's not exactly slow either! :)
Eric Lippert suggested lookup tables in a similar earlier question. His answer is perfect for your purposes as well.