How can I encrypt a large file with a public key so that no one other than who has the private key be able to decrypt it?
I can make RSA public and private keys but
To safely encrypt large files (>600MB) with openssl smime
you'll have to split each file into small chunks:
# Splits large file into 500MB pieces
split -b 500M -d -a 4 INPUT_FILE_NAME input.part.
# Encrypts each piece
find -maxdepth 1 -type f -name 'input.part.*' | sort | xargs -I % openssl smime -encrypt -binary -aes-256-cbc -in % -out %.enc -outform DER PUBLIC_PEM_FILE
For the sake of information, here is how to decrypt and put all pieces together:
# Decrypts each piece
find -maxdepth 1 -type f -name 'input.part.*.enc' | sort | xargs -I % openssl smime -decrypt -in % -binary -inform DEM -inkey PRIVATE_PEM_FILE -out %.dec
# Puts all together again
find -maxdepth 1 -type f -name 'input.part.*.dec' | sort | xargs cat > RESTORED_FILE_NAME
Maybe you should check out the accepted answer to this (How to encrypt data in php using Public/Private keys?) question.
Instead of manually working around the message size limitation (or perhaps a trait) of RSA, it shows how to use the S/mime feature of OpenSSL to do the same thing and not needing to juggle with the symmetric key manually.
Solution for safe and high secured encode anyone file in OpenSSL and command-line:
You should have ready some X.509 certificate for encrypt files in PEM format.
Encrypt file:
openssl smime -encrypt -binary -aes-256-cbc -in plainfile.zip -out encrypted.zip.enc -outform DER yourSslCertificate.pem
What is what:
That command can very effectively a strongly encrypt big files regardless of its format.
Known issue:
Something wrong happens when you try encrypt huge file (>600MB). No error thrown, but encrypted file will be corrupted. Always verify each file! (or use PGP - that has bigger support for files encryption with public key)
Decrypt file:
openssl smime -decrypt -binary -in encrypted.zip.enc -inform DER -out decrypted.zip -inkey private.key -passin pass:your_password
What is what:
You can't directly encrypt a large file using rsautl
. instead, do something like the following:
openssl rand
, eg. openssl rand 32 -out keyfile
openssl rsautl
openssl enc
, using the generated key from step 1.Public-key crypto is not for encrypting arbitrarily long files. One uses a symmetric cipher (say AES) to do the normal encryption. Each time a new random symmetric key is generated, used, and then encrypted with the RSA cipher (public key). The ciphertext together with the encrypted symmetric key is transferred to the recipient. The recipient decrypts the symmetric key using his private key, and then uses the symmetric key to decrypt the message.
The private key is never shared, only the public key is used to encrypt the random symmetric cipher.
I found the instructions at http://www.czeskis.com/random/openssl-encrypt-file.html useful.
To paraphrase the linked site with filenames from your example:
Generate a symmetric key because you can encrypt large files with it
openssl rand -base64 32 > key.bin
Encrypt the large file using the symmetric key
openssl enc -aes-256-cbc -salt -in myLargeFile.xml \ -out myLargeFile.xml.enc -pass file:./key.bin
Encrypt the symmetric key so you can safely send it to the other person
openssl rsautl -encrypt -inkey public.pem -pubin -in key.bin -out key.bin.enc
Destroy the un-encrypted symmetric key so nobody finds it
shred -u key.bin
At this point, you send the encrypted symmetric key (
key.bin.enc
) and the encrypted large file (myLargeFile.xml.enc
) to the other personThe other person can then decrypt the symmetric key with their private key using
openssl rsautl -decrypt -inkey private.pem -in key.bin.enc -out key.bin
Now they can use the symmetric key to decrypt the file
openssl enc -d -aes-256-cbc -in myLargeFile.xml.enc \ -out myLargeFile.xml -pass file:./key.bin
And you're done. The other person has the decrypted file and it was safely sent.