Paragon Initiative Enterprises Blog

The latest information from the team that develops cryptographically secure PHP software.

Do-It-Yourself Hand-Crafted, Boutique, Artisinal Cryptosystems

Let's not mince words: Rolling your own cryptography is almost always a mistake. Almost always, the correct answer is DON'T DO IT.

If you roll your own crypto, you do so at your own risk.

If you're writing your own cryptography code for educational purposes or you're a cryptographer, you can sometimes get away with discarding this advice. However, most developers simply ignore it and proceed to design their own broken cryptography protocols.

If you're going to throw all caution to the wind, be prepared for disastrous outcomes. If proceeding down this perilous path is necessary, it's important to take every precaution possible.

How to Safely Roll Your Own Cryptography

What Problem Are You Trying to Solve?

Before you dive off the deep end, it's important to have an idea of where you'd like to land. Adobe famously eschewed this step and encrypted their user's passwords (with 3DES in ECB mode).

Some questions to consider:

  • What information am I trying to protect?
  • What's an appropriate threat model to adopt?
  • What's the simplest use-case that our solution should address?
  • What is the minimum access our application needs to this information to solve our business needs?

It helps to be intimately familiar with cryptography terms and concepts. You don't want to specify "encrypted passwords" when you should be using a password hashing function to store passwords instead.

One (uncommon but not particularly rare) use case for a custom cryptography protocol is allowing database look-ups on encrypted records. We'll examine this in detail in a later section.

Be the Right Kind of Lazy

If you were to implement secure public key encryption in a vanilla PHP 7 application, these are the steps you would need to take:

  1. Generate two random 256-bit keys from random_bytes().
  2. Generate a random 128-bit nonce from random_bytes().
  3. Encrypt the message with openssl_encrypt() in AES-256-CTR mode, using one 256-bit key and the nonce.
  4. MAC the nonce (step 2) and ciphertext (step 3), using HMAC-SHA-256 with the other 256-bit key.
  5. Encrypt both 256-bit keys with openssl_public_encrypt() and the recipient's RSA public key, taking care to specify OPENSSL_PKCS1_OAEP_PADDING.
  6. Concatenate and send the output of steps 2, 3, 4, and 5.

Decryption would involve:

  1. Split the message into constituent components.
  2. Decrypt the AES and HMAC keys using openssl_private_decrypt() with OPENSSL_PKCS1_OAEP_PADDING.
  3. Recalculate the HMAC of the ciphertext, compare to the MAC contained in the message using hash_equals().
  4. If step 3 succeeds, decrypt the ciphertext, using the AES key and nonce.

This is a lot of work and involves a lot of moving parts. Alternatively, you could use libsodium and your protocol simplifies to:


// Encryption
$ciphertext = \Sodium\crypto_box_seal($message, $recipient_public_key);

// Decryption
$plaintext = \Sodium\crypto_box_seal_open($ciphertext, $recipient_keypair);

Rule of thumb: If you're building a high-level protocol, use secure implementations of lower-level protocols from a well-studied library.

Avoid the Obvious Pitfalls

Generally, if you're using a secure library (in the spirit of laziness), this will be taken care of for you. A great deal of caution is still warranted.

Get Your Design and Implementation Reviewed by Experts

Disclaimer: This is a service that Paragon Initiative Enterprises, LLC offers.

Before you deploy your solution in a production environment, or share it in such a way that encourages others to deploy it, you must get cryptography and security experts to review your work. Get in touch today if you'd like us to review your work.

If you don't have the security talent on-staff, nor the budget to hire cryptographers, to review your solution, then you shouldn't be deploying your own cryptography in the first place.

High-Level Protocol Design Examples

What follows are some problems that developers (whom will not be named herein) have encountered that prompted them to consider writing their own cryptography, and possible solutions.

There is currently only one example, but we may revisit this article and add more as time goes on.

Encrypt a Database Column, But Still Be Able to Query It

Problem: You need to store social security numbers in your database. Regulations dictate that they must be encrypted at rest. Complication: Your software needs to be able to perform an exact-match lookup on the database to determine if a SSN is present in a given table.

There are a lot of unsafe ways to solve this problem, including:

But those are bad ideas. Don't do them. A safer solution is to use a blind index:

  1. Use secure encryption, such as what Halite and defuse/php-encryption provide.
  2. In a separate column (ssn_idx), store the output of hmac_hash('sha256', $socialSecurity, $someSecretKey).
  3. Use the column in step 2 in your SELECT queries.

As long as the HMAC key isn't stored in the database and the database server sits on separate hardware (e.g. Amazon RDS) from the webserver (e.g. Amazon EC2), an attacker capable of stealing database records will be unable to obtain real social security numbers. However, since your application has the key, it can still query for the presence/absence of a given social security number.

This is an optimal trade-off between security and usability.


I hope you'll strongly consider not designing and implementing your own cryptography to solve business problems; but if you do, you'll follow the guidelines on this page:

  • Identify your use case, specific requirements, and threat model.
    • If you stop after this step and hire security experts to design and implement a solution, you'll be much happier.
  • Understand the nuances of basic cryptography terms and concepts. (e.g. Encryption vs Authentication)
  • Use an existing, well-audited library for as much as you can.
  • Get your solution audited by experts.

(If you read this far and were still wondering: Yes, the title is tongue-in-cheek. I really should've included "military grade" but it disrupts the flow.)

About the Author

Scott Arciszewski

Chief Development Officer

With 15 years of software development, application security, and system administration experience, Scott aspires to help others attain a happier work-life balance by solving difficult problems and automating trivial tasks. He is mostly known in the community for his open source software security research and strong progressive positions on providing tools and frameworks that are secure by default. @CiPHPerCoder

Need Technology Consultants?

Will tomorrow bring costly and embarrassing data breaches? Or will it bring growth, success, and peace of mind?

Our team of technology consultants have extensive knowledge and experience with application security and web/application development.

We specialize in cryptography and secure PHP development.

Let's Work Together Towards Success

Our Security Newsletters

Want the latest from Paragon Initiative Enterprises delivered straight to your inbox? We have two newsletters to choose from.

The first mails quarterly and often showcases our behind-the-scenes projects.

The other is unscheduled and gives you a direct feed into the findings of our open source security research initiatives.

Quarterly Newsletter   Security Announcements