How Long Should I Make My API Key?
blog.learnphoenix.io
blog.learnphoenix.io
If we're talking about an API key, then the issue isn't collision and there's no relationship with hashing or uuids except the recommended final length.
A key should be a random 128-bit string (or 192, or 256 if you need additional security).
If you need to generate a key from a passphrase, use a key expansion function, not an hash just because the length is the same.
I don't know if there's any proof of randomness for uuid, the risk (in absence of a proof) is that to provide uniqueness the bit distribution is uneven, which could leak some information to an attacker, thus reducing the real bit strength of the key.
Python for example uses os.urandom for random UUID generation (uuid4), as can be seen in the source: https://github.com/python/cpython/blob/3.5/Lib/uuid.py#L603
The standard library guarantees that os.urandom is "[...] suitable for cryptographic use." (https://docs.python.org/3.5/library/os.html#os.urandom)
I'm not sure about other languages, so it might always be a good idea to look it up in the source code.
http://ruby-doc.org/stdlib-2.3.1/libdoc/securerandom/rdoc/in...
1) If you are generating API keys, those are presumably used to make API calls, and every such call has to verify that the API key exists so it can deny or allow the request, which means that doing a lookup on any API key has to be an extremely cheap operation.
So do the lookup after generating each and check for collisions. If you hit the jackpot and actually managed to randomly create a duplicate, generate another. Problem solved, and you don't have to worry about the collision frequency of your hash algorithm as a weird workaround for skipping a single extra lookup at API key creation.
2) Use GUIDs. It's what they're for. It's in the name. Globally Unique Identifier. This is the problem they solve.
That's what UUID4 is -- all but six bits (that's 122 bits) are completely random. Checking for UUID4 collisions is the height of paranoia. It's basically checking whether your PRNG broke.
So your second recommendation is basically the same as the article's, and contrary to the first. Comparing UUIDs is not that expensive, but as expensive as it has to be for a key that will never collide.
This is a good article that helped me understand and mitigate the vulnerability: https://codahale.com/a-lesson-in-timing-attacks/
UUID = Universally Unique Identifier, RFC 4122 (https://tools.ietf.org/html/rfc4122.html)
GUID = Globally Unique Identifier, the (mostly) Microsoft flavored version of UUIDs, used in partition tables as well
Both of them consist of 128 bits, and both use 6 bits to denote the way the ID was generated, e.g. using the NIC MAC or timestamps.
An overview over the different RFC 4122 UUID flavors can be found here: https://en.wikipedia.org/wiki/Universally_unique_identifier#...
Doing that securely and protecting against replay attacks is non-trivial though.
Regardless, there are many possible cases where you wouldn't be able to use TLS for whatever reason, though it's very rare.
Version 1 had a serious flaw [0] related to how the string to be HMAC'd was constructed. It used an appropriate and well-studied cryptographic building block (HMAC-SHA1) and is an excellent case study in why using the right building blocks isn't sufficient to have a secure protocol.
Version 2 fixed the issues with version 1, but it in turn has been superseded by v4 [1] (no idea what happened to v3). A v4 signature uses a derived key for the HMAC, and included in the derivation is the current date as well as the AWS region you're making the call to. Beyond time-based replay attacks, this also prevents an attacker from capturing a valid request to eg US-EAST-1 and replaying that request in a different AWS region.
0: http://www.daemonology.net/blog/2008-12-18-AWS-signature-ver...
1: https://docs.aws.amazon.com/general/latest/gr/sigv4_changes....
For GUIDs, on the other hand, I'd probably just use a good standard cryptographic hash function like SHA3 rather than assuming that there will be no more than n "clients". But it depends on the purpose, of course.
One would assume that public keys are always easy to guess, because they are public? Hopefully they are not used for any sort of public authentication protocol...?
Some (few?) solutions allow for communication without TLS. In that scenario the API key is usually paired with a shared secret used for signing all messages, so the user is under no obligation to prevent the API key from becoming known to others.
Edit: Parent is asking "What are we hashing?", but the article says "Every language has a decent crypto package for generating random hashes".
If the generation of those keys uses pseudo random data, time, etc, the risk of collision goes up.
Read 16 bytes from /dev/urandom and stuff them into base64encode and you have a pretty good random API key in readable ASCII.
If you encode fewer bits per character, you get a longer key but no more security.)
Raw binary: 16 bytes Base64: 22 bytes Base32: 26 bytes Base16: 32 bytes
The only reason to use base 32 is codes that a human may enter (promo, verification, serial) to remove case and O/0 ambiguities.
The only reason to use base 16 is laziness (some APIs generate this for you.)
API keys are presumably copied from the generation page and pasted into the local app config file.
This is significantly longer than what you need to avoid a collision. The idea of having a three-character key is just crazy.