A practical cryptography guide for developers

A practical cryptography guide for developers
Devsecurely Avatar

In the year 58 B.C., Julius Cesar was preparing to invade independent Gaul. His army in the north-east border was waiting for his orders to launch an attack. This would distract the enemy forces, allowing him to come in from the south and invade the land. He had sent a messenger explaining his plan to his general, and instructing the army to launch the attack. But, the enemy forces intercepted and searched his messenger. They opened the piece of parchment containing the order, but could not understand the content. The message was encrypted. They released the messenger, and the conquest went according to plan. That was practical cryptography in action.

From ancient times when Romans used the Caesar Cipher to modern-day encrypted messaging apps, we use cryptography to secure our communication. Online threats keep increasing and hacking techniques keep improving. Thus, understanding cryptography is no longer a luxury—it’s a necessity.

For the uninitiated, cryptography can seem complex and intimidating. This practical cryptography guide will teach you you need to know about cryptography. You will have an understanding of how you can use cryptography in your projects. You will also learn what cryptographic function to use for what scenario.

Fundamentals

Cryptography aims to secure communications in the presence of malicious actors. To start, we need to define some concepts:

  • Encryption: Encryption is the process of transforming an information. If someone intercepts it, he would not be able to understand it. To encrypt data, we need an encryption key.
  • Decryption: Decryption reverses the encryption process. i.e., retrieves the original information from the transformed form. To decrypt data, we need a decryption key.
  • Plaintext and Ciphertext: We call plaintext the original, unencrypted data. Ciphertext is the scrambled, encrypted data.
  • Keys and Algorithms: We use keys for encryption and decryption. An encryption algorithm is the mathematical rules that make the transformation (encryption/decryption).
  • Public & Private Keys: Encryption keys can either be public or private. We can publish public keys without breaking the security of the encryption process. Private keys need to remain a secret for the encryption process to be secure.

Types of Encryption Algorithms

There are 2 types of encryption algorithms:

Symmetric Cryptography

In symmetric encryption, we use the same key for both encryption and decryption. You give the encryption algorithm a message and a private key as an input. As output, it produces a ciphertext. If an attacker retrieves the ciphertext, he wouldn’t be able to retrieve the cleartext message. He would need the private key to do that.

But, since you know the private key, you can retrieve the cleartext message. You give the ciphertext and the private key to the decryption algorithm as input. You will then get the original cleartext message as an output.

The most popular and secure symmetric encryption algorithm is Advanced Encryption Standard (AES). You can find an implementation for this encryption algorithm in most cryptographic libraries. 

Triple-DES (3DES/TDEA) is another well known symmetric encryption algorithm. But, this algorithm is not considered secure anymore. So, whenever possible, choose AES over 3DES for data encryption.

Usage

You can use symmetric encryption for:

  • Data at Rest: Encrypting files and data stored on your device.
  • Data in Transit: Secure communication between two parties who already share a secret key.

Encryption modes

Some algorithms only know how to encrypt a block of a defined size. For example, AES —the algorithm we discussed earlier—only encrypts a block of 128 bits. That’s the equivalent of a 16 character sentence.

To encrypt a larger message—like for instance, a whole file—the message is cut into blocks of the same size. The blocks are then encrypted according to a strategy. The strategy is what we referred to as encryption mode in the literature. Different encryption modes have different advantages and disadvantages; We are not going to discuss the details in this article.

To be practical, you should be fine using the mode called GCM with the encryption algorithm AES. But, each time you encrypt a message, you need to generate a random “Initialization Vector”. The GCM mode has the added benefit of being immune to padding-oracle attacks.

Key generation

When using a strong encryption algorithm, like AES, the only weak link in the encryption process could be the strength of your password. If you use a password that anyone can guess, then attackers can decrypt your message.

It is best to generate a cryptographically secure and random encryption key. You can find a secure random generator on all programming languages and frameworks. For AES, this key should have the length of 256 bits (32 bytes).

Asymmetric Cryptography

Asymmetric encryption uses a pair of keys: a public key for encryption and a private key for decryption. You give the encryption algorithm a message and a public key as an input. As output, it produces a ciphertext.

If an attacker retrieves the ciphertext, he wouldn’t be able to retrieve the cleartext message. He would need the private key to do that. The owner of the private key is the only one that can decrypt the ciphertext.

Common asymmetric algorithms include RSA and Elliptic Curve Cryptography (ECC). To encrypt messages using an asymmetric key, you can use one of the following configurations:

  • RSA, with a key length of at least 3072 bits. If you want the simple and secure road, choose RSA over Elliptic Curve Algorithms
  • The following Elliptic Curves are recommended and considered to be secure:

Curve familyCurve name
BrainpoolP256r1
P384r1
P512r1
NISTP-256
P-384
P-521
IETFCurve25519
Curve448

Usage

Asymmetric cryptography is perfect for exchanging keys. You can encrypt a secret key using the recipient’s public key, and send the encrypted key to the recipient. Because he has the private key, he recipient is the only one that can decrypt the message. So he can retrieve the secret key. The sender and recipient then use this secret key to encrypt data using AES.

This is a common practice to communicate securely between two parties:

  1. Generate a random AES key K
  2. Encrypt the message m with AES using the key k ( E = AES_encrypt(m, k) )
  3. The key k is encrypted with RSA using the public key of the recipient Ek = RSA(k, pubkey)
  4. Both encrypted message E and encrypted key Ek are sent to the recipient
  5. Only the recipient can decrypt the key Ek using his private RSA key K=RSA(Ek, private_key)
  6. He can then decrypt the message E using RSA, with the decrypted key K: m = AES_decrypt(E,k)

This is the process used by TLS when you communicate with a website using HTTPS.

Asymmetric cryptography is also used for Digital Signatures. This allows us to Verify the authenticity and integrity of data. More on that later

Key generation

Asymmetric keys should be generated using specialized software. For instance, to generate an RSA private key, you can use the following command:

openssl genrsa -out private-key.pem 3072

Hash Functions

Hash functions are one-way mathematical operations. They take data as input, and produce a fixed-size string of characters, known as a hash. This function has 2 main properties:

  • Whatever the size of the input data, big or small, the hash—result of the hash function—is always of the same size.
  • If you pass the same message to a hashing function multiple times, you will always get the same hash.

For password hashing, we recommend using the algorithm Argon2id. You can see our guide on secure password storage here for more details.

For other use cases, use the algorithm sha-256.

Usage

They’re used for:

  • Data Integrity: To check if data has been tampered with. Since any change in data will result in a change of the computed hash, you can detect changes by calculating the hash of the data and comparing it to the hash calculated initially.
  • Password Hashing: To securely store user passwords. You should never store user passwords in plaintext in the database. The compromise of the database would lead to the compromise of user’s passwords. Also, it could lead to further damages on users if they use the same password on other platforms. We have a complete guide on secure password storage here.

Message Signing

Message signing is a process that uses asymmetric cryptography to verify the authenticity and integrity of data. Here’s how it works:

  • A sender uses their private key to create a digital signature for the message:
    1. The sender hashes the message to have a better control over the size of the part to be signed.This is especially useful when signing big files of data.
    2. The sender encrypts the hash with his private key. Usually, if you recall from earlier, we should use public keys to encrypt messages. But in this special case, we want everyone to be able to decrypt this part. Hence we use the private key to encrypt so that everyone can decrypt using the public key. We call this encrypted hash the digital signature of the message.
  • The recipient uses the sender’s public key to verify the signature:
    1. The recipient calculates the hash of the original messages
    2. The recipient decrypts the signature using the sender’s public key. This will get him the hash that the sender calculated.
    3. The recipient compares the hash he calculated, with the hash that the sender calculated. If the two values match, it means that the sender is the one that generated that message. Thus, the message has not been tampered with.

This operation is useful when trying to prove a message came from a certain source. For instance, software editors use it to sign their install files. The Windows operating system then checks this signature to make sure the install files came from legitimate sources. It prevents the user from installing software that the hackers tampered with.

Practical cryptography Key Management

Key management is often an overlooked aspect of cryptography. It involves generating, distributing, and protecting encryption keys. Best practices include:

Use Hardware Security Modules (HSMs) whenever possible

Hardware Security Modules are physical devices that provide secure key management and cryptographic operations. They are designed to resist physical tampering and attacks. Think of it as a black box, you give it a message as an input, and it gives you the encrypted message as an output. You never access the signing key.

Leverage Secure Key Storage Services

If you use cloud services, take advantage of their key management systems (e.g., AWS KMS, Azure Key Vault, Google Cloud KMS). These services often provide hardware-backed security (HSMs). They also provide management settings (define who can encrypt/decrypt/sign data). They also store detailed access log (who encrypted/decrypted/signed a message and when).

Key Rotation

Rotate encryption keys frequently. This helps reduce the risk in case hackers compromise a key. That is because the compromised key will no longer work to encrypt/decrypt/sign messages. We already replaced it with a new one. Key rotation can be a complex subject. Make sure you have a way to decrypt old encrypted messages if needed since you will be discarding the encryption key when you rotate the keys.

Access Control

Strictly control who has access to the encryption keys. Put in place least privilege access policies. This means only the user/person who needs to encrypt/decrypt/sign a message can do that.

In cloud services (AWS KMS, Azure Key Vault, Google Cloud KMS) this means only giving a certain role access to these features (this might be the Virtual machine that hosts your web application).

If you don’t use an HSM service, and instead you store your secret keys on the server, make sure that access control lists to the secret key file. For example, on an apache server, only the user www-data can access the secret key, in read only mode. Other Linux users have no permissions on the file.

Key Backups

Regularly backup your encryption keys but ensure that these backups are as secure as the primary keys.

Implement Key Usage Policies

In your team, define and enforce policies for how and when keys can be used. This includes defining the algorithms, encryption modes and key lengths.

Monitor and Audit

Continuously monitor the use of encryption keys and conduct regular audits. Look for any unauthorized access or anomalies and investigate them.

Incident Response Plan

Have a plan in place for how to respond if you suspect that an encryption key has been compromised. This would include emergency key rotation and communication with affected parties.

Secure Key Destruction

When keys are no longer needed, ensure they are securely destroyed and cannot be recovered.

Don’t roll your own cryptography

A fundamental rule in cryptography is to never implement your own encryption algorithms. Instead, use established cryptographic libraries and tools like OpenSSL and Bouncy Castle to ensure security and reliability.

Devsecurely Avatar

Leave a Reply

Your email address will not be published. Required fields are marked *