How to Encrypt a Large File in Openssl Using Public Key

How to encrypt a large file in openssl using public key

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.

Encrypting large files with public key

Got to solve the problem by splitting the large 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

Solution based on:

  1. http://linuxconfig.org/easy-way-to-encrypt-and-decrypt-large-files-using-openssl-and-linux
  2. https://unix.stackexchange.com/questions/1588/break-a-large-file-into-smaller-pieces#1589

Faster Encryption of large file public key and three users

It's unclear what you are trying to do. Encrypt a large file, sure. But how? Symmetric with AES, or asymmetric with RSA?

Your first command, openssl genrsa creates a RSA public/private keypair with length 192, which as Ken White notes is a bad idea, not only is it not a power of 2, but also an incredibly short key length; to give you an estimate of how bad this is, 512 bit RSA keys were broken twenty years ago. In fact, my openssl, version 1.1.1b plainly refuses to even create such a keypair:

$ openssl genrsa -aes256 -out foo.key 192
Generating RSA private key, 192 bit long modulus (2 primes)
25769803792:error:04081078:rsa routines:rsa_builtin_keygen:key size too small:crypto/rsa/rsa_gen.c:78:

Your second command then does something completely different. It tries to encrypt Bigfile.txt using AES256 in CBC mode, which is ok, but you don't give the command a 256bit AES key. Instead, you tell it to look in the RSA key file for a passphrase, which is certainly not what you want. Openssl does not accept this either:

$ openssl enc -aes-256-cbc -in BigFile.txt -out cipher.bin -pass File: pubPrivate.key
Extra arguments given.
enc: Use -help for summary.

So let's assume what you want is to encrypt BigFile.txt symmetrically, with AES256 in CBC mode using a key derived from a password. You would then distribute this password to you three recipients. How fast is this? On my laptop, with a 1GB BigFile.txt:

$ time openssl enc -aes-256-cbc -in BigFile.txt -out cipher.bin -pass pass:start123
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.

real 0m3,099s
user 0m1,562s
sys 0m0,968s

So, openssl encrypts around 330MB/sec, and it also tells us that the key derivation is unsafe, and we should use PBKDF2 instead. Let's do this:

$ time openssl enc -aes-256-cbc -in BigFile.txt -out cipher.bin -pbkdf2 -pass pass:start123

real 0m3,202s
user 0m1,656s
sys 0m1,077s

How to use OpenSSL to encrypt/decrypt files?


Security Warning: AES-256-CBC does not provide authenticated encryption and is vulnerable to padding oracle attacks. You should use something like age instead.

Encrypt:

openssl aes-256-cbc -a -salt -pbkdf2 -in secrets.txt -out secrets.txt.enc

Decrypt:

openssl aes-256-cbc -d -a -pbkdf2 -in secrets.txt.enc -out secrets.txt.new

More details on the various flags

How to encrypt large file with RSA?

RSA can only encrypt data smaller than (or equal to) the key length.

The answer is to encrypt the data with a symmetric algorithm such as AES which is designed to encrypt small and large data.

If an RSA public/private key pair are required encrypt the symmetric (AES) key with RSA. This is referred to as hybrid encryption and in essence is how HTTPS encrypts data.

But it is may not necessary to RSA encrypt the symmetric key unless a public/private key pair are required. In the general case one just uses symmetric (AES) and that key. What is the use case for a public/private key pair?

Encrypting (large) files in PHP with openSSL

You could use CBC encryption using Mcrypt and then encrypt a segment of data at a time. Make sure that the segment is x times the block size of the used cipher (e.g. 16 bytes for AES). Encrypt the segment and take the last block of the generated ciphertext and use it as IV for the next segment. The final segment should be PKCS#7 padded (plenty of examples out there including in the mcrypt_encrypt comments).

By chaining the segments together you get a ciphertext indistinguishable from a single encrypt (test your code using this information). Decryption is identical, using the ciphertext as IV. To see how it works, look at the CBC encryption method:

Sample Image


EDIT: if possible you should use the OpenSSL equivalent functionality. That's not (well) documented, but you should be able to do the same using the code found in the link within the comment that Scott mentioned. Note that you should first perform everything without padding, and then for the final segment with padding.



Related Topics



Leave a reply



Submit