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:
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.
Use a key exchange method like Diffie-Hellman (Diffie-Hellman-Merkle to be correct) to exchange an AES-256 key.
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.
Don't develop your own key exchange and/or key provisioning protocol(s). This is what historically breaks most products and, unless you are a cryoptographer (not a programmer with crypto experience), you'll likely get it wrong.
Use off-the-shelf protocols like SSL/TLS. Eg. TLS initialized with RSA keypairs for mutual authentication and AES session keys sounds appropiate for what you describe
Updated
Bruce Schneier:
"A colleague once told me that the world was full of bad security
systems designed by people who read
Applied Cryptography"
erickson in his post has already give you plenty of evidence why designing your own key provisioning and management protocol is flawed. I just want to drive the point home why Mallory is alive and doing quite well, thanks to overconfident developers:
You design the scheme you propose where the client encrypts with a public key and sends the document back to you. Things work great, but 1 year down the road the certificate is approaching expiration. You send an email out to your clients with the new certificate containing the public key you want your users to sign encrypts the documents with for you. Unknown to you is that over the past 4 months your ISP admin has received a bribe to route all your IP traffic through a remote machine. Your email is intercepted before distribution and your attached certificate is replaced with another one. All your clients are now sending their ultra secret documents encryted for someone else's private key. An application decrypts each one, stores it, then encrypts it with your public key and forwards the traffic to you. You won't even know is happening, untill by accident during a visit to a client's site you notice that the certificate he uses is not the one you distributed.
You mention in your post as an option to chain algorithms. Nobody is going to brute force you. Your weakness will be key management, and the attack will take some form of social engineering to fool someone is using the wrong key, or reveling the private key (again, bribes go a long way). Industry agreed protocols have steps to prevent man-in-the-middle attacks, they may rely on PKI infrastructure that recognizes designated key use and trusted authorities, they add certificate revocation list check steps to the validation etc etc. Just 'I encrypt with public key, you decrypt with private' does not make a secret safe.
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).
What about ssh ? (rsync on ssh for example) ?
Related
All,
I am trying to mount a NAS drive to a Linux VM.
I have a requirement to encrypt the data in transit, i.e. I want data to be encrypted when
its written from the Linux to the NAS dribe
https://www.dellemc.com/hu-hu/collaterals/unauth/technical-guides-support-information/products/storage/docu88304.pdf
As per the above link krb5p provides encryption of data.
krb5p: Kerberos authentication, data integrity, and data privacy by encrypting the data before sending it over the network. Data encryption requires additional
https://www.varonis.com/blog/kerberos-authentication-explained/
I understand how Kerberos mutual-authentication works but once access is granted to the service (in my case the NAS drive) how does the data transferred to the NAS gets encrypted.
Can someone provide additional details or documentation on how "encryption" works with krb5p?
I am unable to find any additional details.
As per:
https://whyistheinternetbroken.wordpress.com/tag/krb5p/
when using krb5p:
NFS packets will be encrypted with the enctype specified in the Kerberos configuration.
But what are the available enctype that can be specified?
I have attached a diagram that tries to explain the flow of messages b/w Server-KDC-Client
Kerberos allows mutual authentication between a client and a KDC, the KDC and a service, and a client and a service. This happens by way of key agreement between each party.
Client and KDC prove knowledge of a shared key, KDC and service prove knowledge of a different shared key, so client and service can generate yet another random key and agree with one another.
In other words when the client sends the ticket to the service it contains a secret key that both parties can use to encrypt data after authentication has succeeded. In this case that key is what is used to protect NFS traffic.
What enctype is selected is somewhat undefined. It's up to all three parties to agree on one, and each has an opportunity to change it. In practice it's up to the service to make the final decision though. It should be whatever it thinks the strongest algorithm the client can handle. This usually means RC4, AES128, or AES256.
Kerberos just provides the encryption key, but it doesn't magically perform the encryption itself – that has to be done by the NFS client and NFS server themselves. They are aware that krb5p was negotiated, and will call the corresponding encryption/decryption functions when needed. (More specifically, it happens in the SunRPC layer, which NFS is built on.)
When the Kerberos KDC issues you a ticket for "nfs/yourserver.example.com", that ticket includes two copies of a randomly generated session key: one copy decryptable by you, and the other copy decryptable by that server.
The KDC will mark this session key with the best enctype that is common between what was indicated in your ticket request, and what long-term keys are held by the server's principal. Usually this will be AES256-CTS, though it can be RC4 (arcfour) if the service key hasn't been changed in a very long time.
For example,
The "nfs/yourserver.example.com" principal has long-term keys for aes256-cts-sha1-96, aes128-cts-sha1-96, arcfour-hmac, des3-cbc.
Your client making the AS_REQ indicates support for aes256-cts-sha384, aes128-cts-sha256, aes256-cts-sha1-96, aes128-cts-sha1-96.
The KDC chooses aes256-cts-sha1-96 as the best enctype for the session key.
This indication is stored in the ticket itself. If the client is using MIT Krb5 software, you can use kvno to manually request a service ticket (if you don't have one yet) and then klist -e to see the enctypes set for that ticket – "skey" indicates the enctype that the session key is meant to be used with.
So after receiving the ticket from the KDC, you send it to the NFS server as part of the RPCSEC_GSS authentication process, and now both you and the server have copies of the session key. (The same session key remains in use for as long as the service ticket is valid – usually 10 hours.)
The set of possible enctypes is:
aes256-cts-hmac-sha384-192, aes128-cts-hmac-sha256-128: New, not supported by most implementations yet (and most services won't have keys of that type yet, either).
aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha1-96: Widely supported by all Kerberos implementations.
camellia256-cts-cmac, camellia128-cts-cmac: Decent alternatives to AES, but rarely used in practice.
arcfour-hmac (RC4): Deprecated, but still occassionally used. Gone from Linux 5.10.
des3-cbc-sha1: Deprecated, but still implemented.
des-cbc-md5, des-cbc-crc: Completely obsolete. Hope you'll never see those.
(Don't believe webpages saying that Linux NFS client only supports DES – that was fixed in 2010 for v2.6.35, and AES is fully supported now.)
I'm thinking of creating a mobile app that uses Libsodium's crypto_box_easyfor encrypting and decrypting chat messages.
However, after reading a lot on the net, I found that one of the major flaws of public-private-key algorithms is that recorded data can be decrypted as soon as the recipients private key is leaked.
To avoid that, the use of Perfect Forward Secrecy (PFS) is suggested and I'm wondering, if Libsodium is already supporting PFS in the former mentioned function as individual nonces are used for each encryption.
Maybe someone can guide me on the difference between PFS and Libsodiums functions (if there are some) or help me by clarifying the relationship of nonces and PFS.
There is no forward secrecy.
crypto_box_seal() is slightly better, as the sender uses ephemeral keys. These messages can be signed using a long-term secret key in order to check that they come from the expected party, but that key being compromised will not allow decryption of previous messages.
However, if the recipient's secret key get compromised, recorded messages can still be decrypted.
For these reasons, the box construction doesn't exist in libhydrogen. Instead, there are Noise-based protocol implementations for secure key exchange, all with forward secrecy. These APIs will be backported to libsodium at some point.
But secure chat applications are far from trivial to build. The signal library is a much better starting point, even though the license may not be compatible with your expectations.
I want to create an application, where multiple people should be able to communicate with each other securely (think of a decentral group chat) - sounds easy, but here is my problem:
As far as I understood, with asymmetrical encryption you have a public key and a private key. Everyone who wants to send a message to someone has to encrypt it with the public key and the recipient can decrypt it with the private key.
But if there are more than two people that should be able to read all messages, I don´t know how this should work...
Either everyone has the public and the private key - which I think is a bad idea - or everyone has to have everybodys public key and has to send a seperate message to each recipient.
Also, I want to make a 100% sure, that the one who sends a message really is who he pretends to be. (so nobody is able to "fake" messages)
Is there an encryption algorithm that solves my problem?
Controlling the extend of the recipient group
In a comment to Richard Schwartz' good answer, you ask
Is it possible with this algorithm to ensure that only one is able to invite others? As far as I understood, everybody could distribute the decrypted session key.
When applying the protocol in a group chat scenario, don't let the term "session key" mislead you. Rather, think of the key for symmetric encryption as a "message key": Each time someone sends a message to the group, they should generate a new random symmetric key, encrypt it with every legit receiver's public key separately and prepend all these cryptograms to the symmetrically encrypted message. This way, each sender decides independently whom they consider a part of the legit recipients group of their own sent messages.
This will give the protocol some more transmission overhead, but this probably won't matter in practice. What could matter is the 'cost' of getting larger amounts of 'good' randomness (entropy) to generate sufficiently unpredictable message keys. So an acceptable optimization might be that, if the group of legit recipients has remained the same, a sender might re-use the session key of their own previously sent message. Never though should they re-purpose a sessions key received from another group member for sending messages of their own.
Off course, even if each sender decides independently whom they consider a legit recipient of their message, you can't keep any legit recipient from compromising messages they received: They can simply forward the messages unencrypted (or encrypted for someone not in the original recipient group) to whomever they want.
Ensuring authenticity
In an edit to your original question, you added
Also, I want to make a 100% sure, that the one who sends a message really is who he pretends to be. (so nobody is able to "fake" messages)
Encryption can't do that, but cryptography has another way to make sure that
the message actually comes from whom claimed to have sent it
the message hasn't been tampered with since
And the way of ensuring these things is signatures, which also are something that public-private-key cryptography enables. Let senders sign their messages with their private key. (Which usually means 'encrypting' a cryptographically secure hash of the message with the private key.) And let receivers verify the signatures (by 'decrypting' the signature with the sender's public key and comparing the result with a hash of the message they computed themselves.)
Don't roll your own anything (except when you should)
Richard's answers advices you to not roll your own (pseudo) random number generator. For anything you plan to use in production, I'd extend this to anything encryption:
Don't invent your own protocols
Don't invent your own cyphers, signatures or hash functions
Don't invent your own way of gathering entropy
Don't roll your own implementations of any of the above, even if invented by others
Instead, use well-established cryptography libraries. These are written and reviewed by experts in both cryptographic theory and in the practices of writing secure software. And while even these libraries are often enough found to have (sometimes embarrassing) security issues, nothing you'll come up with yourself will be nearly as secure as them.
Though, for learning, implementing any or all of the listed stuff (including pseudo random number generators) is great exercise and helps you understand at least some aspects of the underlying cryptography. And this understanding is important, as it's often difficult enough to correctly and securely use the well-established libraries, even when you do have some knowledge of the concepts they reveal through their interfaces.
And of course for innovating within cryptography, inventing new stuff (and getting it scrutinizingly reviewed by the community of experts in the field) is necessary, too. That new stuff just shouldn't be used for anything serious before it has passed that review successfully.
I assume you mean asymmetric encryption, not asynchronous encryption.
In most cases, we don't actually use an asymmetric cipher to encrypt the content of messages. That's because messages can be large, and asymmetric ciphers are slow in comparison to symmetric ciphers. It's also because of the issue you are contending with here: in a multi-party commmunicaiton, you'd like to be able to just send the message once and have everybody be able to read it. So the trick is that we combine asymmetric and symmetric techniques into a protocol that solves the problem.
First, we generate a random symmetric key which we can call the "session key". We're going to distribute this session key to all recipients, but we need to do this securely. Here's where we're actually going to use asymmetric encryption. We encrypt the session key once for each recipient using each of their public keys and an asymmetric cipher (such as RSA), and we send the encrypted session key to each recipeint. We can send it to each recipient separately, or we can just build a structure that looks like this:
"recip1|recip1EncryptedSessionKey|recip2|recip2EncryptesSessionKey..."
and send the whole thing out to all recipients, each of whom will be able to parse it and decrypt their own encrypted copy of the session key. (This is generally how it's done in encrypted email: the list of all encrypted versions of the session key for all recipients is enclosed with the message, and everyone gets the exact same email.)
Once we've securely distributed the session key to all recipients, we can use the session key to encrypt each message just once with a symmetric cipher (such as AES), and send the same encrypted message to all recipients. Since they all have received a copy of the session key, they can all read it and act on it.
Note that as in all things having to do with encryption, it is crucial that the session key is really random. Don't just rely on a plain vanilla random number generator for it, and for heavens sake don't roll your own. Make sure that you use a cryptographically secure pseudorandom number generator.
A real chat system would likely be quite a bit more complicated, probably with a mechanism for re-establishing a new session key periodically, and the details of a secure protocol can be quite intricate. I.e., consider how you would protect against a bad-guy stepping in and fooling everyone into using a session key of his choosing! But the basics are as above.
*Clarification: My question relates to setting up a "secure" communication channel between two parties where a key (read passphrase) has been agreed upon in the real world. Only using RSA allows for MITM-attacks (if I'm not misstaken), so I was thinking encrypting the public keys with AES (the key that both have agreed upon) before sending them to respective parties *
I'm currently trying to build two applications that talks with eachother. To secure the exchanged messages I was thinking on using RSA where each application has it's own set of keys.
Before communication is started between the two applications they do need to exchange keys. That shouldn't be a problem but I was thinking on using AES to encrypt the public keys before sending them over the internet.
I know what the word public (as in public key) means but I was thinking that this would see to that the right application/computer gets the key and no one else.
So I want to exchange keys and to protect them from MITM attacks.
If anybody could give a better suggestion (I'm using the LibCrypto library btw), I'm all ears.
Thank you.
Best regards
/Tomas Gustavsson
This question shows many misconceptions from your part.
I know what the word public (as in public key) means but I was
thinking that this would see to that the right application/computer
gets the key and no one else.
I think this is the real problem you have and ask.
Which I think is: How can you know that you are using the public key of the entity you actually want to communicate with and not the public key of a malicious entity claiming to be the who you want to communicate with?
This problem is solved in a typical installation by certificates signed by a trusted authority and issued to the specific entity i.e. IP or DNS name.
In your case you haven't given any details of your certificates.
You could just as well manually pre-install them and use them for your secure connections.
If you follow some other plan e.g. symmetric encryption then your would start asking other questions e.g. how do you securely share the secret key etc
I have made a small program that will allow me to send licenses in encrypted form to users.
At the moment I have
An RSA private key that encrypts my AES key
A single AES/CBC key that encrypts the data
An RSA public key
Both the AES and public key are hard coded onto the device.
How should I deal with the IV when a license is requested, should I create a static one on the device or send a new one with every new license I create?
If I understand what you are trying to do then, like most licensing schemes, it is basically a DRM scheme. I'll only address the cryptography problem, but there is also of course the problem of playing hide-and-seek from the hackers. You should know that no DRM scheme offers any measurable security (unless perhaps security hardware is involved) in the cryptographic sense, but they are still common and some developers are comfortable with the logic behind them.
What you want to do is generate your license data and include some information that prevents a user from simply copying a valid license file from a legitimate user. Examples might be mac address, phone number, etc. Then you sign this data. The license then consists of the unencrypted license and the signature bytes. On the user side, your installation software will verify the signature using the hard-coded public key, and perform any other checks (mac address matches, phone number matches, etc).
This would be the core of your scheme, and is enough for most developers. You can take this core and further obfuscate it using ad-hoc including encryption, splitting, etc., depending on how far you want to go with the hide-and-seek game.
EDIT:
If I may make a suggestion, I think the book Beginning Cryptography With Java would be a wise investment. It includes examples that using the Bouncycastle library. You can donwload the examples for free from the same website.
Isn't this proposal totally silly?
You should encrypt with RSA public keys not with a private key. If you encrypt with a private key as you propose then everyone with access to the public key will learn the AES key and will be able to decrypt or forge anything. Of course for the same reason you should also not use the same AES key for distinct receivers.
And to answer the question, you should use a new random IV for each AES/CBC encryption.