would there be any reason to hash a GUID? - hash

would there be any reason to hash a GUID?

To make it fit into a 32-bit int? That's what many hash-table implementations work with.

The only possible use of it if you use those GUIDs as security tokens or something like passwords. If your DB was broken hackers will not be able to use tokens because they are hashed.

Related

Storing keys - Should I store private keys in PEM or JWK JSON format?

Which is more conventional?
For cross-platform; it is ok to store and use JWK in the JSON format?
Do I need to encrypt them before storing it in a database?
Not sure about the format, but I'd strongly recommend against storing private keys as much as you can. These are considered secret.
However, it seems like JWK is about the public keys (as opposed to the private keys) - and these are okay to store. I'd just make sure they can't be replaced by anyone without proper permissions
Should I store private keys in PEM or JWK JSON format?
The main reason for choosing one format or the other mainly depends on the application/library needs.
In general, you want to avoid unnecessary conversion on runtime and serve directly on the required format.
For cross-platform; it is ok to store and use JWK in the JSON format?
Can you elaborate more on this use case?
Do I need to encrypt them before storing it in a database?
Not necessarily. As you tagged this question with [jwe], I understand that the private key is used to decrypt the token you receive.
If this is is stored on a backend server, the risk of key leak is low and if you encrypt it you will undoubtedly need to store the decryption key somewhere that you should also store securely. This has no benefit and you will be required to decrypt it each time you want to use it and thus use CPU time for nothing.
Note that storing private keys in a database is not recommended. It should be stored as a file on the server or set as an env var.
If the private key is stored on a roaming device (smartphone, PC...), it is highly recommended to encrypt it has those devices are considered less secured because of physical attacks. They usually provide convenient ways to encrypt such keys (Android keystore, IOS Keychain, Windows keystore and certificate...).

I want to use bcrypt.compare together with mongoose/mongo enginee search

Consider this code:
const hashPassword = function(plainText) {
return crypto
.createHmac(process.env.Secret_hash_Password, "secret key")
.update(plainText)
.digest("hex");
};
As you may have noticed, this is a simple hashing function using crypto.
Now consider this code excerpt:
bcrypt.compare(password, user.password, (err, isMatch) => {....}
As you may have noticed, this is a simple comparing hashing function using bcryptjs.
As I believe everyone will agree, the second is most secure.
Now consider the problem:
I have a key to store on mongo, and this key is a sensitive information, as so, I have decided to hash it as so no one can decrypt it. This key is used to make mongo searches, this an information that just the user has, a sort of password.
Solution: use the first code, as so nonetheless you cannot decrypt, you can get the same result of hashing if the input is the same.
Problem: my solution is using a tecnique that is well-known to be easily hacked, someone that somehow had access to the server just need to enter several inputs and once they get the same output, they got it! this is a well-known flaw of my solution.
Desired solution: use the second code with mongo.
Discussion: I could simply get all the database information with find({}), and apply say ForEach and bcrypt.compare, nonetheless, I know from my studies that mongo is optimized for search, e.g. they use indexes. It would be nice to be able to pass the bcrypt.compare as a customized function to mongo search enginee.
It was suggested "Increase the bcrypt salt rounds.": I cannot use salt since that would change the key and whenever I will need to compare, it will change. bcrypt.compareexists to overcome that, but mongo/mongoose queries does not have such internal enginee.
What I have in my head, in pseudocode:
Model.findOne({bcrypt.compare (internalID, internalID')}) //return when true
Where: bcrypt.compare (internalID, internalID') would be a sort of callback function, on each search, mongo would use this function with internalID', the current internalID under comparison, and return the document that produces true.
Any suggestion, comment, or anything?
PS. I am using mongoose.
From what i understand, you don't ever want anyone to know the patient ids (non -discover-able from real life patient-ids), even the database admin (and of course hackers).
I think you design is a bit messed up.
Firstly - indexes use B tree data structure for faster lookup so you have to provide exact string for lookup and by your condition of un-hash-able ids, indexes won't work. So you'll have to iterate over every patient id by that doctor and compare to get true result, which is pretty compute- extensive and frankly bad design.
There are multiple ways to approach to approaching this problem- depending upon your level of trust and paranoia.
I think using cryptojs is the correct solution. Now you have to add some randomness to the key/solution. Basically you hash the id with cryptojs, but instead of supplying the key yourself, you could take the secret key from doctor itself then hash every id with that key. Now you will have to unhash and hash every patient id everytime doctor changes secret key (using some sort of message queue).
You could also hash the secret key entered by doctor before saving and will have to unhash everytime (twice!) doctor wants to lookup by patientId.
Depending upon the number of users you expect your application to serve, if number is low enough- my solution would work. But too many users, you'd have to increase compute resources and probably invest in some security measures instead of my overkill solution. Why'd you be losing secret key to hackers anyway?
Good luck.

How to expose URL friendly UUIDs?

Hello Internet Denizens,
I was reading through a nice database design article and the final determination on how to properly generate DB primary keys was ...
So, in reality, the right solution is probably: use UUIDs for keys,
and don’t ever expose them. The external/internal thing is probably
best left to things like friendly-url treatments, and then (as Medium
does) with a hashed value tacked on the end.
That is, use UUIDs for internal purposes like db joins, but use a friendly-url for external purposes (like a REST API).
My question is ... how do you make uniquely identifiable (and friendly) keys for external purposes?
I've used several APIs: Stripe, QuickBooks, Amazon, etc. and it seems like they use straight up sequential IDs for things like customers, report IDs, etc for retrieving information. It makes me wonder if exposing UUIDs as a security risk is a little overblown b/c in theory you should be able to append a where clause to your queries.
SELECT * FROM products where UUID = <supplied uuid> AND owner/role/group/etc = <logged in user>
The follow-up question is: If you expose a primary key, how do people efficiently restrict access to that resource in a database environment? Assign an owner to a db row?
Interested in the design responses.
Potential Relevant Posts for Further Reading:
Should I use UUIDs for resources in my public API?
It is not a good idea to expose your internal ids to the outside. You should either encode them (with some algorithm) or have a look up table.
Also, do not append parameters provided by user (or URL) to your SQL query (UUIDS or not), this is prone to SQL injection. Use parameterized SQL queries for that.

Is there an alternative to MD5 hashing when the input is public?

I have a database of similar integers by the fact that they all share the same first 3 numbers:
7537463746
7536735325
7538236775
7538273826
...
Each one is associated to a user, and they are all almost exposed to the public, meaning they are sent as a sort of peer discovery, but not directly shared. I don't want the bare integer to be accessible, so I thought about hashing them with a one-way hashing function like MD5.
Since the output is not reversible like encryption or compression algorithm do, it looks great. But there's a problem; Getting the integer database is easy and inevitable, so looping through them, hashing the loop results and comparing all the hashes to the ones sent through peer communication is going to be a trivial job for malicious users.
The schema is something like this:
user1[hash(integer1),hash(integer2)...] -> |server hash database| ->
↓
↓
hash(integer1) = user8
hash(integer2) = user40
A malicious user will get user1 integers data by social engineering or other means and hash all of them to see if they're in the database by adding them to his peers data.
Now, is there any hashing algorithm to avoid this type of situation? I need the peers to communicate without giving out their integers data but still both mutually associate the same integer to a unique hash. In alternative, is key signing the only solution? I would like to avoid it since it will make the whole system slower.
Have you thought about salting your MD5? What that means is that you have some sort of secret key that only your application knows. This is actually always a good practice. So rather than doing this...
md5($userId)
You would append the "salt" inside of the MD5 like this...
md5($userId . 'this is a secret shhh!')
Now they can't get the integer from the MD5.

How to re-hash Laravel passwords?

I'm making a forget password feature in my web app, problem is I store user's password using:
Hash::make('_their_password_')
Is there any way to re-hash it back or any recommended approach for this?
The point of hashing a password is that it's (supposed to be) an irreversible operation. If your database is compromised, the attacker will gain access to the hashes, but not to the passwords. That way the attacker can't log in with the users' passwords on other sites.
Make a "we'll reset your password" feature instead of a "we'll send you your password" feature.
Note that there are also other best practices you absolutely should be following regarding password hashing, to make sure the "supposed to be" above actually holds, and to further minimize the impact if your site is compromised. Laravel's Hash class seems to already be using the password-appropriate hash function Bcrypt. However, make sure you're using a salt when you're hashing your password.
The Laravel's Hash method cannot be reversed.
One way encryption is the best way to store user passwords, or other sensitive data.
One way means that your data can be converted into an encrypted string, but due to a complex algorithm with painful maths, reversing the process is not possible. This makes storing passwords a doddle! Your customers don't have to worry about you knowing their passwords, but you are still able to compare them (by hashing the password they provide) or change the password if needed.
If you need to reverse, you can use Crypter class.
$secret = Crypter::encrypt('I actually like Hello Kitty');
$decrypted_secret = Crypter::decrypt($secret);
Read more about encryption here http://codehappy.daylerees.com/encryption
If you want to verify the content of password with other value use the following.
return Hash::check($value, auth()->user()->password);