Search code examples
encryptionrsaaes

Which of the encryption approaches should I use?


I need a system to exchange very secret data (source code that is a trade secret). I will use Crypto++ so practically I can use all encryption algorithms, although I really prefer to use an industry standard.

Currently I'm thinking on these methods:

  1. Have the server generate 2048/4096-bit RSA keys, send the public key over to the client, have the client encrypt the data then send it over to the server.
  2. Use a key exchange method like Diffie-Hellman (Diffie-Hellman-Merkle to be correct) to exchange an AES-256 key.
  3. Initiate a TLS connection and tell the server the AES key directly.

Which approach do you believe I should use? I'm not concerned about performance as long as it's reasonable; security is what matters. If none of them, please suggest another method.

P.S.: I might use chaining on the symmetric algorithm, like AES-Twofish-Serpent.

EDIT: Any recommended software must be in a license that won't restrict proprietary usage. LGPL is as restrictive as it must get. That rules out GPL.


Solution

  • I'd recommend using an existing S/MIME (or CMS) implementation with a solid cryptographic module to encrypt your content.

    S/MIME enveloped data makes a nice format for storage of encrypted data "at rest": the envelope records information about the algorithms and keys used so that the information will be available to authorized recipients later, when it is needed.

    Also, even if it doesn't support the "best" algorithms (like ECDH key agreement), a good library is much less likely to have vulnerabilities than something written by a general programmer. Since it is far, far more likely that security will be breached by an implementation error than cryptanalysis, it makes sense to minimize those errors.


    In legitimate protocols, public keys are signed by one of a small number of trusted issuers, whose public keys are distributed by some secure means "out-of-band". If you already have a secure means to get a public key to the message sender, why bother sending another? And if you don't, you're screwed.

    TLS and S/MIME depend on having a set of well known CA certificates at every client. These are used to sign the server's public key so that a client can detect attempts to substitute keys. The protocol can't bootstrap itself; there must be a secure way to distribute "trust anchors" out-of-band.

    Also note that RSA is incredibly slow compared to symmetric ciphers. Real protocols generate a "content encryption key" for a symmetric algorithm like AES, then use an RSA public key as a "key encryption key" to encrypt the content encryption key for the message recipient(s).


    So, the main problem is getting your public key to the client securely. If you can do that, either option #1 or #2 is good—assuming that you just use that public key, rather than trying to send another one "in-band". In fact, in CMS, Option #1 is called "key transport", and Option #2 is called "key agreement".

    In practice, the "server" could use a certificate issued by a CA that is already well known, or the client can compare a hash of the certificate with one that you tell him over the phone, or carve into the face of a cliff, or whatever. The critical thing is, all of your security depends on the integrity of the certificate. You have to protect it from tampering.

    While Crypto++ is an "industry standard", its security depends on how you use it. Just like Jerry told Kramer, "the door must be… closed!" Using the cryptographic primitives in Crypto++ with in a poorly designed protocol will get you nowhere. That's why I'm stressing the use of CMS (a higher-level protocol) together with a good cryptographic module (cryptographic primitives).