NodeJS: Secure Encrypting Data without needing public and private keys.

1_cP7MHHa7OZUcE7K9Jw0M2g.png

BY: Ramiro Alves

RightSource Developer

There are many situations in which embedded or software-bind encryption is not secure enough if we are paranoid enough. How many times we have read in the past years that databases that were supposed to be a safe vault because of its manager’s own features, and it turns out they are victims of their own, henceforth we decide to add some extra layer of security.

Normally it will require a public/private keys pair, ideally we should be using a pair emitted by a Trusted Certificate Authority but coming to the size and stage of the project might not be needed or considered, yet you would love to still encrypt your data to some degree, so it’s time to come back to the basics, using a Salt+Password combo.

And I understand that you know by osmosis what a password is, it comes in the intuitive preface of Turn on your mobile or computing device, but what’s certain is that if you are somewhat new into this world, you might not know what is a Salt, maybe we skipped that part or it was taken for granted at some point knowing that there are many different security layers, either found in a third-party package or a common used software in your architecture.

A Salt is just that, that flavoured mineral we love adding to our food, or code-talking, that random sequence of bytes that we’ll use to flavour our data. In the encryption world it will work as an encryption key that we’ll use to hash passwords using our one-way favorite encryption algorithm. 

So, the way this works is similar to the myth of the Coke original recipe, remember that years ago people started saying that the recipe was split in two? so if by accident one of those parts get lost, the recipe will never be complete and therefore be useless? That’s what we are trying to achieve here. In a way is the same principle, your password is never gonna be centralized, and if somehow your data storage gets in the wrong hands, you’ll have for sure that at least your password is not gonna be cracked (in theory) because one part is on the database, and the other one is on your brain. 

Analogies aside, what we do is pretty simple, we start from the point of having to generate one random salt, attach it to your password (via your preferred mixing method or concatenating strings), process that mix through an one-way encryption algorithm (let’s say SHA-256) and it will give you an encrypted version of this last part; at the end, just having your Encrypted Password and Salt will be enough to authenticate any user on the system, and Plaintext or Non-Salted Hashed Passwords will remain secret to its owner user.



Implementation

As a simple example using NodeJS we might observe it the following way

code-02.png
DATA SALT_Mesa de trabajo 1.png

Now a little bit of theory...

How did we complicated things to the wrong people?

First of all we would have to consider a single password file that contains thousands of usernames and hashed passwords (for example, if we would use normal encryption MySQL password column type), without Salt, an attacker could compute any database hash iterating n times using n attempts to find a matching password by using brute force mechanisms, and then compare the result against the thousand records in the above mentioned single password file. If Salts were present, the attacker would have to compute any database hash using Snattempts where n is the amount of initial expected attempts, and S the number of expected attempts for Salts. This mechanism defeats reusing hashes in attempts to crack multiple passwords.

I can’t encourage highly enough to use a different Salt for every record or hashed stored data.

The implementation of Salts use, also fights the use of hash tables and rainbow tables for cracking passwords. What we know for hash table is a large list of precomputed hashes for commonly used passwords, so if somebody on the unethical side of security matters would be able to use this mechanisms, the use of salted passwords will oblige them to modify it’s normal hash and rainbow tables to contain a pre-hashed combination of salt and password records, and things get easier here, because if the Salt is long enough and sufficiently random, this form of attack is pretty unlikely to succeed.

Remember when we were talking about not storing plaintext or non-hashed passwords, this is because unsalted passwords chosen by humans tend to be vulnerable to dictionary attacks since they have to be both short and meaningful enough to be memorized, that way even a small dictionary or a hash table is significant help cracking the most commonly used passwords. So, since Salts do not have to be memorized by humans, they can make the size of the records on dictionary or tables for a successful attack prohibitively large without placing a burden on the users.

On paper, we are extending the length and potentially the complexity of the password. If any of the table elements used for hackers do not have passwords matching your protection protocols (i.e. 8-byte password, and 2-byte salt, is effectively a 10-byte password) and complexity (non-alphanumeric salt increases the complexity of strictly alphanumeric passwords) of the salted password, then the password will not be found, and if found, one will have to remove the salt from the password before it can be used. In this particular case, depending also the mixing between the plaintext password and generated random salt.

The modern shadow password system, in which password hashes and other security data are  stored in a non-public file, somewhat mitigates these concerns. However, they remain relevant in multi-server installations which use centralized password management systems to push passwords or password hashes to multiple systems. In such installations, the root account on each individual system may be treated as less trusted than the administrators of the centralized password system, so it remains worthwhile to ensure that the security of the password hashing algorithm, including the generation of unique salt values, is adequate.

As mentioned, Salts also make dictionary attacks and brute-force attacks for cracking large numbers of passwords much slower (but not in the case of cracking just one password). Without salts, an attacker who is cracking many passwords at the same time only needs to hash each password guess once, and compare it to all the hashes. However, with salts, each password will likely have a different salt; so each guess would have to be hashed separately and compared for each salt, which is considerably slower than comparing the same single hash to every password.

Another (lesser) benefit of a salt is as follows: two users might choose the same string as their password, or the same user might choose to use the same password on two machines. Without a salt, this password would be stored as the same hash string in the password file. This would disclose the fact that the two accounts have the same password, allowing anyone who knows one of the account's passwords to access the other account. By salting the passwords with two random characters, even if two accounts use the same password, no one can discover this just by reading hashes.

Do NOTs!

  • Never reuse a Salt, this will cause that users with the same password will have the same salted hash, and this makes it easier to attack multiple users by cracking only one hash.

  • Never use a salt that is too short, it will be easy for an attacker to create a rainbow table consisting of every possible salt appended to every likely password. Using a long salt ensures that a rainbow table for a database would be prohibitively large as mentioned above in this article.


Ramiro Alves