6

Why am I asking?

I am very new to cryptography (so please be patient with me...) and I want to avoid making unnecessary mistakes. I did a lot of research, but - other than with most other programming related questions - I had a hard time finding enough information to make me confident, that I do now understand how to do things right.

What is the context?

I am working on a webshop using PHP (> 7.2) and MySQL. I need to store some personal information. However, this will not contain critical data (like payment details) - only names, adresses and contact information. Nevertheless, I want to encrypt this data - not least to gain some exprerience. This data will be entered and read by the php application, without input from an admin.

I am hosting this site on World4You, an Austrian provider. I am not sure of the proper word for this (English isn't my native language), but I think you'd call this shared hosting. However, I've read of shared hosting, where other users have access to my files - this is not the case here.

In your answers please consider these circumstances as invariant. I am well aware, that there is quite a bit of room for security-related improvement when it comes to hosting. And I am, of course, happy about every suggestion in regard to this. But please also help me find the best solution given these circumstances.

Why secretbox?

According to my research, there are stronger encryption alternatives to secretbox. However, this added security can easily be undermined through poor implementation - escpecially if you are an amateur like me. Secretbox is still pretty secure, but much easier to use and therefore the best choice in my case. Correct?

Also, libsodium now comes as a part of PHP (in versions 7.2 and later).

My questions

Thanks to the libsodium e-book I now know how to generate a key and a nonce and how to encrypt and decrypt data using these. However, I am not sure about how to store the key and the nonce.

Where do I store the key?

The "best" solution (considering my circumstances), that I found so far, is to store the key in a php-file, that lives outside the document root. Is this an acceptable way of going about things? Are there better options, that don't require significant changes to my setup?

Where do I store the nonces?

In my understanding, nonces do not have to be kept secret. So, where do I keep my nonces?

e.g.: If I want to encrypt the strings for the table-columns "name", "address" and "email", I'd use 3 nonces, right? So, would I just store these 3 nonces in three additional columns of this same table (this somehow intuitively "feels" wrong)? Or would I store them somewhere else?

What column type should I use?

From what I've gathered, I should store the encrypted data in a column of some binary type. So would a BLOB be the right choice?

Also, what column type should I use to store nonces (if I do actually store them in a table)?

Thank You very much!

1

I am not an expert nor have I ever done anything with crypto before. I AM AN AMATEUR!!! Please do not take what I have to say as any knowledge or wisdom in this subject matter. Use at your own risk.

I actually have the same question. Much of the documentation and F.U.D. leave someone learning this stuff in a daze. I'm pretty sure this in intentional to help with security via obscurity and confusion.

Ok, jokes aside, I did want to expand on some concepts you outlined that I've discovered in my own journey down the same path. First off the plate is that the use of encryption and how you implement it is directly dependent on the use case. For example if you wish to address data at rest it will have a very different solution then exchanging secret messages over the wire. They all use the same algorithms and tools but the actual implementation for your app will differ.

Next, the key (in secretbox) is your life blood. It must be saved securely and hidden away. It is also permanent in the case of storing data at rest. In your example saving it outside the document root or possibly in a database behind a firewall might be best. Also many implementations will also encrypt the key with a passphrase (this is what GPG/PGP does) You could do this before writing it to disk and save the passphrase (randombytes_buf) in an environment variable.

The nonce is unique per encryption ...err... per ciphertext created. So in your case above I would serialize all three fields into one string and encrypt that with one nonce. Now to decrypt (read) you need to know the nonce. This is where the docs and blog posts get funny. I've only seen one example (libsodium-wrappers) where they concatenated nonce buffer with the ciphertext buffer making one large buffer with the nonce as a prefix.

I am presuming that another method would be to serialize both in a form parse-able by the reader. This is my question for the crypto world. Which is a better transport method?

One string/binary payload:

nonce
vvvvvv
bada55123456789abcdf
      ^^^^^^^^^^^^^^
      ciphertext

OR separate the two when serializing:

{
  "nonce": "bada55",
  "ciphertext": "123456789abcdef"
}
1

Paragon created a library that hides the complexity of libsodium for non-experts.

Beginners should probably start with this library: https://github.com/paragonie/halite

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.