2

Currently I'm saving an array of AES keys into a keychain as JSON, saved as a text file / SQL text column:

{    
    [
       {
          encryptedAesKey:RsaEncryptedBytesBase64Encoded==,
          signature:RsaSignatureBytesBase64==,
          keyId:0,
       },
       {
          encryptedAesKey:RsaEncryptedBytesBase64Encoded==,
          signature:RsaSignatureBytesBase64==,
          keyId:1,
       }
    ]
    signature:HashAboveKeychainThenRsaSignatureBytesBase64==
}

Only the holder of the private key (say Alice) can decrypt the AES keys. Alice also has her own public key, so she can verify the signature before usage. This protects her against Chuck who might disrupt AES decryption of already encrypted data by creating a random AES key, encrypting it with Alice's public key and writing to where the JSON is saved. But chuck can't sign so Alice won't accidentally use bad data.

The above has been working for many many months but CMS/PKCS#7 seems attractive since it already designed for data security and integrity by defining data envelopes (encrypt) and data signatures (signing).

Question: Apart from interoperability what additional benefits would one have by going the CMS/PKCS#7 route?

DeepSpace101
  • 2,143
  • 3
  • 22
  • 35

2 Answers2

5

Don't roll your own crypto. If you decide to invent your own format, then you are on your own. The history of cryptography is full of people who invented their own format, and failed horribly; and, more to the point, the history of cryptography is not full or people who invented their own format, and got away with it. These things are hard to do correctly, and you cannot test whether you succeeded or not (you can test for functionality, not for security).

CMS (the new name for PKCS#7) has the double benefits of:

  1. having been standardized and deployed in the field for a long time, so its potential pitfalls should have been well understood by now;
  2. being already implemented in a number of framework and libraries. As usual, the software which is easiest to implement correctly is the software which is already implemented correctly.

So, do yourself a favour, use CMS.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • thanks, we aren't exactly rolling our own ciphering algorithms here but I understand where you're coming from even for seemingly benign stuff like format at rest. We've switched to CMS/PKCS7. – DeepSpace101 Feb 09 '13 at 23:33
0

Interoperability does not seem to be high on your requirements list. Unless you have a library supporting CMS with a quality that matches your expectations, CMS/PKCS#7 may easily turn out an overkill given its complexity.

If your application has a secure way to store the root secrets beside the database SQL, you are probably better off encoding all your keys into a blob, and use an established authenticated encryption mode like AES GCM (NIST 800-38D) or AES CCM (NIST 800-38C). The one AES root key is saved in the secure store. You will not be using any public key, but from your description it does not seem you really need it (one application accessing its own data).

  • That was our thought before. However 1) CMS support in .NET is good. 2) Encrypting the (AES256-GCM) keys, individually, inside the JSON structure and then signing the entire structure (=DIY) was much larger than treating the JSON as a CMS blob + encrypting + signing. 3) CMS automatically takes care of embedding the right cert details to enable the reverse process 4) On .NET it makes certificate handling easier (decrypt routines don't require a cert reference separately). Basically, several of the 2nd degree issues come "pre-solved" with CMS. Storage can be PEM (string) format in SQL as before. – DeepSpace101 Feb 10 '13 at 20:34
  • If .NET does all the CMS plumbing for you, you are indeed shielded from CMS complexity and that may be the right solution. Good CMS libraries are not that common though. My point was more than you can encode into a binary blob your unencrypted and unsigned JSON structures (with any keys and any data you want in them), and only *then* encrypt the whole blob with GCM. When you load them from the dataase, you decrypt (and by virtue of GCM also authenticate) the blob which can then be decoded into JSON. – SquareRootOfTwentyThree Feb 10 '13 at 21:25