Proper asymmetric file encryption in Go - encryption

I need a way to allow multiple people encrypting various files but only one party been able to read them all. I wrote a program in Go by following various online examples but at some point I got the following error:
Error from encryption: crypto/rsa: message too long for RSA public key size
Is RSA the wrong way to go? Is it ok if I break the file into multiple chunks and encrypt them? Is there an asymmetric block cipher that I can easily use?
I read the discussion here and it is said that RSA is not the proper way to go.
Can you also provide with an example?

If you need public key asymmetric encryption for data larger than the key size you need to use hybrid encryption. Essentially this is how HTTPS works.
Hybrid encryption is where the data is encrypted with symmetric key encryption such as AES and that key is encrypted with asymmetric key encryption such as RSA or EC (Elliptic Curve) Cryptography.
Do not break the file into multiple chunks and encrypt them.

So I ended up using GPG and my service has one unique private key and I share the public one with my users.

Related

How to encrypt and use a symmetric key with an asymmetric key pair

I have messages I need to be able to encrypt when being sent. They should only be able to be decrypted by the receiver.
Initially, I had a structure where the message is encrypted using the receiver's public key, and the receiver then uses their private key to decrypt their messages. However, since I was using RSA, the size of the message was quite limited.
I'm imagining two potential solutions, but am not quite sure how to implement the better one (option 2).
(Easy) just split up each message into many smaller parts, encrypt and store those. This would only change the query structure of my app but not the encryption structure.
I could encrypt the messages with symmetric keys, which is faster and works on any size. However, I would then need to encrypt that symmetric key with an asymmetric one. The problem then becomes that I can only decrypt the symmetric key when the asymmetric private one is provided, ie when the receiver wants to read their messages. So in that case, how would I actually encrypt the messages? Since I don't want the sender to be able to access a key used for decryption as well.
The problem then becomes that I can only decrypt the symmetric key when the asymmetric private one is provided, ie when the receiver wants to read their messages. So in that case, how would I actually encrypt the messages?
That's simple, you use an ephemeral, message specific, fully random symmetric key for data encryption before you encrypt it with the public key. Preferably you should explicitly destroy the symmetric key after that. You can prefix the wrapped (encrypted) symmetric key before the ciphertext of the message, as it will always have the same size in bytes as the modulus (i.e. the RSA key size in bytes).
The system you are thinking about, which is much better than splitting up messages for RSA, is called a hybrid cryptosystem. There are various other ways to accomplish the same thing such as RSA-KEM and - for elliptic curves - ECIES. Both are not often present in crypto-libraries though.
If you decide to use RSA/AES for sending cryptograms then I would advice you to use OAEP and e.g. AES-CTR rather than AES-CBC as RSA PKCS#1 v1.5 padding and CBC padding are both vulnerable to padding oracle attacks.
It is highly recommended to sign the messages, otherwise an adversary can encrypt fake messages. Encryption is only used to achieve message confidentiality, not message integrity & authenticity. An adversary may even try plaintext oracle attacks if any message can be send. If you are not allowing a set of private keys that you control then you should sign-then-encrypt, not encrypt-then-sign.
And as always, prefer TLS or other explicit secure transport protocols if that's an option for transport security.

RSA Encryption - Public Key Encryption

I would like to use RSA encryption on a large file (>25 MB).
Is it possible or are there limitations using a Public Key/Private Key for a large app?
I am exposing a public key to clients and not allowing anyone but the recipient to view the contents with the private key. So the business case makes sense although it will be slower than symmetrical encryption.
Thanks,
RSA cannot encrypt a payload larger than its key size (minus some overhead for padding). To bypass this limitation you'll need to generate a symmetric key, use that to encrypt the larger file, then encrypt the symmetric key itself with RSA (with OAEP or PKCS1v1.5 padding).
Cryptographic Message Syntax (CMS) and PKCS7 (CMS's predecessor) support this use case already so there's no need to invent your own protocol.

RSACryptoServiceProvider and Web.config encryption

I am new to cryptography. I want to encrypt the connection string section and some other section in the web.config. I know this can be accomplished using RSACryptoServiceProvider.
But I am not sure about the Key which is being used by the default RSACryptoServiceProvider and the key size.
As per our organization security policy the key size should be 196 bit and we have to share the Key with security team which is used for encryption.
When we use the default encryption what will be key used internally by asp.net for encryption/decryption and the key size?
In-order to use a custom key which can be shared with security team do we need to create a custom class by inhering RSACryptoServiceProvider?
Also RSA Key Container is bit confusing. Is it a container for the Key or the Key itself
Please advice.
RSA key container files which are exported from aspnet_regiis.exe are indeed containers for the key. They are XML files. Actually, as RSA is public key crypto, the key container holds both the public key and private key (if you export both).
When you perform web.config or app.config encryption via aspnet_regiis.exe, and you do not specify a provider, it will use the value of "defaultProvider". See http://msdn.microsoft.com/en-us/library/zhhddkxy(v=vs.100).aspx. The encrypted output will list the provider name (so that you know how to decrypt it). It appears the default name of the default provider is "RsaProtectedConfigurationProvider". That crypto provider uses a key. The default key has a default name of "NetFrameworkConfigurationKey" (see http://blogs.msdn.com/b/mosharaf/archive/2005/11/17/protectedconfiguration.aspx). The key with that name will have a different value on every machine and is generated when .NET is installed.
A key length of 196 bits sounds like your security team expects you to be performing symmetric key encryption (not asymmetric PKC) of some sort. For example, people brag about their AES key lengths being 256 bits. The .NET 4.0 aspnet_regiis.exe command for creating a custom RSA crypto provider and key use a key size of 2048 bits (although 1024 is not uncommon from days of yore). I imagine the default RSA provider and default key use default values for key lengths. But to be sure, you might want to export the default key, and inspect it yourself. The -pc and -px switches and their associated options (like -size) are documented at http://msdn.microsoft.com/en-us/library/vstudio/k6h9cz8h(v=vs.100).aspx.
If you need to be very specific about a private key, which would be durable beyond a machine reimaging, and would be used by many nodes in a server farm, and which needs to be held in escrow by the security team, you probably want to invest the time in creating a non-default crypto provider of the RsaProtectedConfigurationProvider type (not inventing your own CSP class as an alternative to RsaProtectedConfigurationProvider).
One last thing to note, web.config XML encryption is performed in a multi step process. First, the encryption process generates a random symmetric key (which is short in comparison to an RSA key) which will be used to encrypt a plaintext corpus. The plaintext is encrypted with the symmetric key (after the corpus is normalized for whitespace, etc). Then, the symmetric key (which is short compared to the corpus) is encrypted using an RSA public key. If the whole plaintext corpus was encrypted with an RSA public key, it would take a long time to decrypt. So when you look at a block of encrypted XML in a web.config encrypted you will really see two things: an encrypted key section, and an encrypted data section. To decrypt the ciphertext, ASP.NET needs to first decrypt the encrypted symmetric key, and then use the decrypted key to decrypt the stuff you actually want as plaintext.
There is an example of the two-levels of encryption at "Problem with decrypting xml document". What is apparent (and perhaps troubling), is that the RSA crypto provider uses Triple DES in CBC mode for the symmetric crypto algorithm underlying the RSA PKC which you think is really providing the encryption. See this person's frustration around trying to change the symmetric algorithm to AES, for example, Change Microsoft Config File Encryption Method From TripleDES. Triple DES is only recommended for use until 2030 in very ideal scenarios (see http://en.wikipedia.org/wiki/Triple_DES#Security) by the algorithm's endorsers (NIST). NIST had a bake-off years ago for a replacement symmetric algorithm suite, which they have chosen and endorsed as AES (http://en.wikipedia.org/wiki/Advanced_Encryption_Standard). So to use AES-192 or AES-256, you would need to invent your own CSP class as an alternative to RsaProtectedConfigurationProvider, then make it available for creating providers and performing encrypt/decrypt operations from ASP.NET.
Here is another stack-overflow article which is relevant: ASP.NET Encryption - aspnet_regiis - Farm.
Here is a guide to creating/exporting RSA crypto providers and keys for spreading around in a farm, for example: http://msdn.microsoft.com/en-us/library/2w117ede(v=vs.100).aspx

AES/Rijndael: search on encrypted data - static salt and IV

I want to do searching on encrypted data. Which means that there is the need to have the same ciphertext every time I encrypt the same plaintext. I.e. think of a list of encrypted names and I want to find all "Kevin"'s in it. I would now encrypt "Kevin" and search the database for the encrypted text. All hits will be "Kevin"'s — but still only the one who has the password knows.
Now my question: What about security if I use the same salt and IV (to get the effect described above) all the time? Is the encryption still secure? Or is there any other method to do searching on encrypted data?
If you want to do a deterministic encryption then you should use an encryption mode
that has been designed for deterministic encryption (and not modify an encryption mode designed for something else).
One possibility is the SIV encryption mode described in
RFC 5297.
(Of course, deterministic encryption has its drawbacks, but discussing this is not part of this question.)

How to communicate AES initialization Vector to client for hybrid cryptosystem

I need to implemented security for client-server communication. I have implemented the following hybrid cryptosystem
To encrypt a message addressed to Alice in a hybrid cryptosystem, Bob does the following:
Obtains Alice's public key.
Generates a fresh symmetric key for the data encapsulation scheme.
Encrypts the message under the data encapsulation scheme, using the symmetric key just generated.
Encrypt the symmetric key under the key encapsulation scheme, using Alice's public key.
Send both of these encryptions to Alice.
To decrypt this hybrid ciphertext, Alice does the following:
uses her private key to decrypt the symmetric key contained in the key encapsulation segment.
uses this symmetric key to decrypt the message contained in the data encapsulation segment.
I am using RSA For a public-key cryptosystem, and AES for symmetric-key cryptosystem. Every thing works fine, but I am not sure how to handle AES initialization vector. Currently, I am concatenating the AES key and initialization vector encrypting it with the public key and sending that to server.
I just wanted to get some opinions about this approach. How this problem is solved by other communication protocols SSL etc.
Thanks.
You don't encrypt the IV. Bundle it with the encrypted key and send it (in the clear) to the recipient.
Standards for this do exist. This scheme is called "KeyTransRecipientInfo" in CMS (upon which S/MIME is based), and PGP offers a similar mode. TLS also includes the initialization vector as a parameter in the key encryption algorithm identifier, using the same ASN.1 syntax as CMS. A robust, open-source library to perform this operation is available for many, many platforms.
At the very least, studying the CMS specification might help avoid some of the many pitfalls in a home-brew implementation. See §6.1 and §6.2.1 of RFC 3369.
I've done the same thing, and I handled it the same way - concatenate the AES key with the IV and encrypt them both.
You could also just send the key and use the key itself to generate an IV - for example by using the first 128 bits of a hash of the key as the IV. That should be OK security-wise as long as you are generating a new AES key for each session and not re-using the same AES key over and over with the same IV.
There is no reason to encrypt the IV - you can send that in the clear. Just make sure you pick a new one each time (the same way you do the AES key).
That said, it is often convenient to package the AES key and IV together. Encryption of 16 bytes ain't that expensive.

Resources