ipfs / notes

IPFS Collaborative Notebook for Research

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How-To Crypto

Stebalien opened this issue · comments

How-To Crypto

This issue is intended for discussing and formulating rules about how to correctly and securely use crypto. If you notice any suboptimal, insecure, or incorrect use of crypto:

  1. Fix it.
  2. Document the correct way to do it here so that we avoid that mistake in the future.

Rules of Thumb for Signatures

Suggestions

  1. Put everything into the signature.
  2. Always include field separators. Otherwise, sign([][]bytes{"first", "second"}) == sign([][]bytes{"firstsecond", ""}).
  3. If possible, name fields; this helps with forwards compatibility as fields are removed/added. The alternative is to use separators and never remove fields (just blank out non-included ones).
  4. Put in some form of scheme-specific ID (e.g., a protocol ID). Otherwise, an attacker can steal a signature from one protocol and use it elsewhere. Basically, the signed data should describe in what context the signature is valid. Note: the preferred solution is to avoid re-using a single key in multiple contexts. However, that's not always possible.

Golden Rules

Without the random oracle assumption (hashes):

You should be able to reconstruct your data-structure (type included) from the signed data.

With the random oracle assumption:

Given a random oracle (a cryptographic hashing algorithm) and a way to invert hashes (go from a hash back to the hashed data), you should be able to reconstruct your data-structure (type included) from the signed data.

Basically, if you can't parse the data you shove into the signing algorithm back into the datastructure you're trying to sign, you're probably doing something wrong.

Encryption Versus Authentication

  • Encryption hides content.
  • Authentication authenticates content.

Not all crypto is authenticated.

As a matter of fact, most (all?) stream ciphers are not authenticated by default because adding a MAC (message authentication code) per block (often 256bits or 32 bytes) is a lot of overhead, you generally want one per packet, not one per block.

How-To Authenticated Crypto

Encrypt then MAC. That is, encrypt the data, then MAC it. There's a really nice StackExchange answer explaining why.

One thing you need to remember is what's being authenticated. In this case, you're authenticating the ciphertext. That means that the ciphertext is was "signed" (MACed) by a party knowing the shared key. However, this does not mean that the ciphertext is, e.g., the next ciphertext in the stream, or that you haven't already seen the cipher text, or even that the cipher text came from this particular stream.

Added "Encryption Versus Authentication" section.

In case we turn this into a larger guide or course, we may want to add that newer modes of encryption like GCM and its successors do authenticated encryption automatically, while avoiding a lot of the subtle mistakes that are possible with older modes like CBC.

I would go so far as to recommend an AE(AD) mode as a default starting point; only fall back to CBC with a MAC if there is a compelling reason to do so, and document what that reason is.

One thing you need to remember is what's being authenticated....

Great succinct explanation of a common source of confusion.