What is the difference between encryption, hashing and salting?
There are several security concepts and techniques, but each one has its purpose and I will introduce their concepts and practices in this article.
Introduction
When we discuss about user authentication in an application, consequently, we already think about information security and how user data will be used and stored in the application.
Some security concepts and techniques are used such as encryption, hashing and salting to obtain a higher level of security, but each one has its purpose and I will introduce the concepts, differences and how it is used in practice in this article.
But what is the difference and when to apply each one?
Concept
The concepts and techniques are different so I will explain each one so you can use it in your application.
Encryption
Encryption is the process of converting data using an access key with the possibility of recovering it. Encryption is a two-way (bidirectional) process, that is, it is possible to encrypt data and decrypt the same data using the same access key. There are some types of encryption known like AES (Advanced Encryption Standard), RSA (Rivest-Shamir-Adleman), among others.
Hashing
Hashing is the process of converting data without needing to retrieve it, and hash types have the same length regardless of the converted data. Hashing is a one-way (unidirectional) process, that is, data can be encrypted but not decrypted. There are some types of hashing known like MD5, SHA1, SHA256, SHA512, among others.
Salting
Salting is the process of adding random data when converting data using hashing. There are some types of salting known as scrypt, bcrypt, Argon2, among others. This process is often used when storing passwords in the database.
Practice
The examples used in practice will be developed using Node.js and the crypto module.
Encryption
A practical example of encryption use is in the communication between two applications where the application A encrypts the data and sends this encrypted data to the application B, where this communication can be done by a database or by an HTTP request, and the application B decrypts the data for use. In this example, the access key must be in applications A and B.
There are two classes in the crypto module called Cipher and Decipher that we are going to use in the example.
1. Create the application folder.
mkdir nodejs-encryption
cd nodejs-encryption
2. Create the file package.json
. The option -y
allows the file to be created without the questions, such as application name, version, among others.
npm init -y
3. Create the folder src
and create the file index.js
inside the folder src
.
mkdir src
touch src/index.js
4. Add the content below in the file src/index.js
.
const { createCipheriv, createDecipheriv } = require('crypto');
const algorithm = 'aes-256-cbc';
const key = 'REtgV24bDB7xQYoMuypiBASMEaJbc59n';
const iv = '8d2bc3f0f69426fc';
const encrypt = (data) => {
const cipher = createCipheriv(algorithm, key, iv);
let crypted = cipher.update(data, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
};
const decrypt = (data) => {
const decipher = createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update(data, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
};
const data = 'Some data plain';
const dataEncrypt = encrypt(data);
const dataDecrypt = decrypt(dataEncrypt);
console.log(`Data=[${data}]`);
console.log(`Data encrypted=[${dataEncrypt}]`);
console.log(`Data decrypted=[${dataDecrypt}]`);
Notes:
createCipheriv
: This method creates and returns an object of type Cipher. The arguments are:algorithm
: AES (Advanced Encryption Standard) algorithm type of encryption.key
: Access key. The length of the key depends on the type of algorithm that will be used.iv
(initialization vector): Any value that is used once on the sender and receiver side. The length of the iv depends on the type of algorithm that will be used.
createDecipheriv
: This method creates and returns an object of type Decipher. The arguments are:algorithm
: AES (Advanced Encryption Standard) algorithm type of decryption.key
: Access key. The length of the key depends on the type of algorithm that will be used.iv
(initialization vector): Any value that is used once on the sender and receiver side. The length of the iv depends on the type of algorithm that will be used.
update
: This method updates the encryption or decryption with the data. The arguments are:data
: Data that will be encrypted or decrypted.inputEncoding
: Data input encoding.outputEncoding
: Data output encoding.
final
: This method returns encrypted or decrypted data. A string is returned when informed the encoding, otherwise, a Buffer will be returned.
5. Run the application with the command below.
node src/index.js
Data=[Some data plain]
Data crypted=[4ee8b9fd43c94019edebafc2d6374c82]
Data decrypted=[Some data plain]
Notes:
- The Some data plain data was passed to the
encrypt
method and this method encrypted the data generating the value4ee8b9fd43c94019edebafc2d6374c82
. - The value
4ee8b9fd43c94019edebafc2d6374c82
was passed to thedecrypt
method and this method decrypted the value generating the data Some data plain.
6. Ready! We created an example of data encryption and decryption.
The application repository is available at https://github.com/rodrigokamada/nodejs-encryption.
Hashing
A practical example of hashing use is storing a user's password in a database by applying a hash type. Whenever the user enters the password on the sign in page, the password hash is compared to the hash stored in the database.
There is a class in the crypto module called Hash that we are going to use in the example.
1. Create the application folder.
mkdir nodejs-hashing
cd nodejs-hashing
2. Create the file package.json
. The option -y
allows the file to be created without the questions, such as application name, version, among others.
npm init -y
3. Create the folder src
and create the file index.js
inside the folder src
.
mkdir src
touch src/index.js
4. Add the content below in the file src/index.js
.
const { createHash } = require('crypto');
const crypt = (data) => {
const hash = createHash('sha256');
hash.update(data);
return hash.digest('hex');
};
const data = 'Some data plain';
const dataCrypt = crypt(data);
console.log(`Data=[${data}]`);
console.log(`Data crypted=[${dataCrypt}]`);
Notes:
createHash
: This method creates and returns an object of type Hash. The arguments are:algorithm
: Algorithm type supported by the OpenSSL version.
update
: This method updates the hash with the data. The arguments are:data
: Data that will be converted to hash.
digest
: This method returns data converted to hash. A string is returned when informed the encoding, otherwise, a Buffer will be returned.
5. Run the application with the command below.
node src/index.js
Data=[Some data plain]
Data crypted=[039ee8ef355ee07c345fe6feaa22d6c1bf34ac91eb45abb80602c59deb5d34e7]
Note:
- The Some data plain data was passed to the
crypt
method and this method converted the data generating the value039ee8ef355ee07c345fe6feaa22d6c1bf34ac91eb45abb80602c59deb5d34e7
.
6. Ready! We created an example to convert the data to hash.
The application repository is available at https://github.com/rodrigokamada/nodejs-hashing.
Salting
A practical example of salting use is in storing the user's password in a database where random data is added with the password and then a type of hash is applied.
There is a method in the crypto module called scrypt that we are going to use in the example.
1. Create the application folder.
mkdir nodejs-salting
cd nodejs-salting
2. Create the file package.json
. The option -y
allows the file to be created without the questions, such as application name, version, among others.
npm init -y
3. Create the folder src
and create the file index.js
inside the folder src
.
mkdir src
touch src/index.js
4. Add the content below in the file src/index.js
.
const { scryptSync } = require('crypto');
const salt = 'some-salt';
const keyLength = 64;
const crypt = (data) => {
const derivedKey = scryptSync(data, salt, keyLength);
return derivedKey.toString('hex');
};
const data = 'Some data plain';
const dataCrypt = crypt(data);
console.log(`Data=[${data}]`);
console.log(`Data crypted=[${dataCrypt}]`);
Notes:
scryptSync
: This method converts the data to hash. The arguments are:data
: Data that will be converted to hash.salt
: A random data.keyLength
: Key length.
toString
: This method converts the type from Buffer to string.
5. Run the application with the command below.
node src/index.js
Data=[Some data plain]
Data crypted=[2b57498b290aa7d31741dc71b60f59f9b5f59431c842500502704f0d7e7b8204293b13bcb8ee54ef2f4f8c99711f27c42144d1c46d5c44362bd5a6748bf7a1bc]
Note:
- The Some data plain data was passed to the
crypt
method and this method converted the data generating the value2b57498b290aa7d31741dc71b60f59f9b5f59431c842500502704f0d7e7b8204293b13bcb8ee54ef2f4f8c99711f27c42144d1c46d5c44362bd5a6748bf7a1bc
.
6. Ready! We created an example to convert the data to hash using a salt.
The application repository is available at https://github.com/rodrigokamada/nodejs-salting.
Conclusion
After presenting the concepts and the use in the practice of encryption, hashing and salting, even if everything is related to security, each one has its purpose and to reinforce all this:
Encryption is a two-way process making it possible to encrypt and decrypt data used in the communication between two applications.
Hashing is a one-way process making it possible the authenticity and integrity of the data used in storing the user's password.
Salting is the process of adding random data to the hashing also used in storing the user's password.
Understanding the security concepts and implementing the security techniques are very important to keep your application or system secure.
This tutorial was posted on my blog in portuguese.