I have to do a lab for my computer security class where I am to use gpg and OpenSSL to do secure communication. I am confused about this step:
Use 'openssl enc' command line symmetric cipher routine to generate a
256bit AES key in CBC mode. You should use SHA1 as a message digest
function for generating the key. Save generated secret key, IV, and
salt into file named aes.key. (Use –P opting to print out the key,
salt and IV used then immediately exit, don’t do any encryption at
this step.)
But I am looking through the man pages for openssl enc and I see no options for digests. I know that there is an openssl dgst command but that just computes a hash of the input. Is there a flaw with the question? What does "You should use SHA1 as a message digest function for generating the key" mean? Do I generate a key and then just SHA1(key.aes)?
Any help with this would be appreciated.
Thank you.
From the usage information for openssl enc which you get when giving it an unknown argument such as -h:
-md the next argument is the md to use to create a key
from a passphrase. One of md2, md5, sha or sha1
So you should use -md sha1 to specify SHA1 as hash function used
in key derivation. A complete solution for the step would be:
openssl enc -aes-256-cbc -md sha1 -P
They actually seem to have forgotten to explain -md in the manual page.
Related
I am using 1.0.2p to encrypt the file using the following command.
#openssl aes-128-cbc -e -k 'abcdefghijklmnop' -in my.txt -out myencrypt.txt
My decryption is based out of Crypto.Cipher python module.
Here is my code. However, I am unable to decrypt the text successfully.
I am unsure on what am I missing here?
from Crypto.Cipher import AES
def decrypt(ciphertext, key):
iv = ciphertext[:AES.block_size]
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext[AES.block_size:])
return plaintext.rstrip(b"\0")
def decrypt_file(file_name, key):
with open(file_name, 'rb') as encrypt_file:
ciphertext = encrypt_file.read()
dec = decrypt(ciphertext, key)
with open("plain.txt", "wb") as plain_file:
plain_file.write(dec)
if __name__ == "__main__":
decrypt_file('myencrypt.txt', 'abcdefghijklmnop')
Your issue could be that OpenSSL 1.0.2 still uses MD5 as its hashing algorithm instead of SHA. I am not super familiar with this Python library, but from the docs it looks like the default hashing algorithm is SHA1.
From the parameters section of new():
hashAlgo (hash object) – The hash function to use. This can be a module under Crypto.Hash or an existing hash object created from any of such modules. If not specified, Crypto.Hash.SHA1 is used.
So what I believe is happening is that your encryption line (using OpenSSL 1.0.2) uses MD5 when encrypting, but the Python library is defaulting to SHA1. So you would either need to update your OpenSSL version and/or specify the hashing algorithm in your Python code when calling new().
I believe OpenSSL was updated in 1.1.0 to use a SHA algorithm for hashing. I have actually ran into this problem when trying to decrypt an archive from an older server, using OpenSSL for both encryption and decryption but the versions won't match. If you have any issues decrypting an archive from an older version of OpenSSL, you may have to specify the older hashing algorithm with -md md5, like:
openssl enc -aes256 -d -in your/input/file.encrypt -out your/output/file -md md5
Im trying to decrypt a text, which was encrypted with AES-256-ECB with the given key. To decrypt, Im using the same version of the openssl which was used for encryption (OpenSSL 1.1.1d 10 Sep 2019).
String to decrypt: VAWawVAWawxiyH20dI+t5NPAY9w== (inside file.txt)
Key: 461a966faef244e4808d6b2b8e928d01 (inside key.txt)
I tried those commands:
cat file.txt | base64 -d > file2.txt
openssl enc -AES-256-ECB -d -in file2.txt -out answer.txt --kfile key.txt
And im getting: bad magic number. Whats the problem?
openssl enc will normally use a password to derive a key. So it is the derived key that is used to decrypt the file. The derivation process requires a "salt", and openssl enc during encryption stores that salt at the beginning of the file along with a "magic number" to identify it. If the magic number is missing (usually because the file wasn't encrypted by openssl enc or because the password based key derivation derivation method wasn't used) then you get this error.
The -kfile option tells OpenSSL to read the password from a file and then derive the key from it. Probably want you intended was to not use password derivation at all, but to use the explicit key. In which case you need to use the -K option and supply the key on the command line using hex.
It is a large file to encrypt. I am at the encrypting part. The error is showing:
"Error reading password from Bios"
"Error getting password."
Please let me know what to do. Thanks in advance.
I kind of want to remove cbc mode because it is slow. I read it in an article. Also, the directions say to make it faster since it is needed for three users.
I think this is the problem by using 192 instead of 4096 or higher but I need to lower it to make it go faster speed from the question.
openssl genrsa -aes256 -out pubPrivate.key 192
openssl enc -aes-256-cbc -in BigFile.txt -out cipher.bin -pass File: pubPrivate.key
Also, I read somewhere that there are numbers 0000 in front of the code somewhere causing the error if that matters?
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
When encrypting a file with OpenSSL, it is possible to use -pass pass:mySillyPassword, where mySillyPassword is the password used in encryption. In addition, it is possible to use a salt, where -salt -s (hex string) is used to specify the salt.
Why would someone want to use a password instead of the salt or in conjunction with a salt? Also, I understand just using the -salt command will cause OpenSSL to generate a salt. How is this better than a user-defined salt? If OpenSSL randomly generates a salt, how will the user know what the salt is to decrypt the file in the future?
In OpenSSL, the salt will be prepended to the front of the encrypted data, which will allow it to be decrypted. The purpose of the salt is to prevent dictionary attacks, rainbow tables, etc. The following is from the OpenSSL documentation:
Without the -salt option it is possible to perform efficient
dictionary attacks on the password and to attack stream cipher
encrypted data. The reason for this is that without the salt the same
password always generates the same encryption key. When the salt is
being used the first eight bytes of the encrypted data are reserved
for the salt: it is generated at random when encrypting a file and
read from the encrypted file when it is decrypted.
The documentation suggests that a salt always be used with a password, except if compatibility with earlier versions that do not support a salt is neccessary.
Password and SALT are two different things. You have to have a password with or without salt (password is mandatory while salt is optional but recommended).
The actual key which is used for encryption is driven from the password and the SALT, if provided. Hence, even if the same password used to encrypt two files, if SALT is used, then the key will be different and the ciphertext of course.
The password is never appended or encoded into the ciphertext. In contrast, the salt is added to the beginning of the ciphertext. But it can't be used to decrypt the ciphertext without the password.
Why SALT is important? Imagine you are using the same password without SALT to encrypt ten files. An adversary can generate keys dictionary for potential passwords then once one key successfully decrypt one file, it can decrypt all files. With SALT he has to create ten different dictionaries one for each SALT, which make things more expensive for him and secure for us.
Let's do practical things, I will use openssl 1.1.1:
Password without SALT:
echo "secret data in my file" > plaintext.txt
openssl enc -aes-128-cbc -nosalt -k "mySecretPassword" -in plaintext.txt -out enc1.nosalt.bin
openssl enc -aes-128-cbc -nosalt -k "mySecretPassword" -in plaintext.txt -out enc2.nosalt.bin
Both ciphertexts should be the same because the encryption key only depends on the password which is the same in both cases.
xxd enc1.nosalt.bin
00000000: 576e a82c 0dac 92d8 5e45 5ef4 3f6f db6a Wn.,....^E^.?o.j
00000010: 5630 554f 3f28 a0de ae96 91d9 1024 d5ca V0UO?(.......$..
xxd enc2.nosalt.bin
00000000: 576e a82c 0dac 92d8 5e45 5ef4 3f6f db6a Wn.,....^E^.?o.j
00000010: 5630 554f 3f28 a0de ae96 91d9 1024 d5ca V0UO?(.......$..
Password and SALT:
openssl enc -aes-128-cbc -k "mySecretPassword" -in plaintext.txt -out enc2.salted.bin
openssl enc -aes-128-cbc -k "mySecretPassword" -in plaintext.txt -out enc1.salted.bin
The ciphertext should be different due to the SALT, even though we use the same password. Note that the Salt is appended to the beginning of the ciphertext.
xxd enc2.salted.bin
00000000: 5361 6c74 6564 5f5f 9cfe 2d62 a2d4 70b8 Salted__..-b..p.
00000010: aee4 afb5 85c9 76a2 cb04 7e1d 27d9 94d4 ......v...~.'...
00000020: a1b3 c4d6 39b8 f5a8 c300 81b5 b6ed 4cca ....9.........L.
xxd enc1.salted.bin
00000000: 5361 6c74 6564 5f5f e73c ee5b 701b bba8 Salted__.<.[p...
00000010: fa25 c54e befa 26dc ddb1 3a2d 2bd7 a95b .%.N..&...:-+..[
00000020: bda9 56f0 4445 f229 3398 4076 1044 dad6 ..V.DE.)3.#v.D..
The SALT is important against adversaries who don´t use openssl/GPG to decrypt your ciphertext.
When matching the password (not the key), a dictionary atack using openssl will decrypt all the files encrypted with this password, agree?
The adversary´s main goal here is to know the encryption standard (aes, des, etc.).
With SALT, it can only little bit increase the security: if a hacker can find the password for one encrypted file, and if the user is using the same password for all the files, no matter whether a SALT is used, the hacker will be able to decrypt all the files, no matter they have different SALTs or not.
I want to encrypt and decrypt one file using one password.
How can I use OpenSSL to do that?
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
Better Alternative: GPG
Though you have specifically asked about OpenSSL you might want to consider using GPG instead for the purpose of encryption based on this article OpenSSL vs GPG for encrypting off-site backups?
To use GPG to do the same you would use the following commands:
To Encrypt:
gpg --output encrypted.data --symmetric --cipher-algo AES256 un_encrypted.data
To Decrypt:
gpg --output un_encrypted.data --decrypt encrypted.data
Note: You will be prompted for a password when encrypting or decrypt. And use --no-symkey-cache flag for no cache.
RE: OpenSSL - Short Answer
You likely want to use gpg instead of openssl so see "Additional Notes" at the end of this answer. But to answer the question using openssl:
To Encrypt:
openssl enc -aes-256-cbc -in un_encrypted.data -out encrypted.data
To Decrypt:
openssl enc -d -aes-256-cbc -in encrypted.data -out un_encrypted.data
Note: You will be prompted for a password when encrypting or decrypt.
RE: OpenSSL - Long Answer
Your best source of information for openssl enc would probably be: https://www.openssl.org/docs/man1.1.1/man1/enc.html
Command line:
openssl enc takes the following form:
openssl enc -ciphername [-in filename] [-out filename] [-pass arg]
[-e] [-d] [-a/-base64] [-A] [-k password] [-kfile filename]
[-K key] [-iv IV] [-S salt] [-salt] [-nosalt] [-z] [-md] [-p] [-P]
[-bufsize number] [-nopad] [-debug] [-none] [-engine id]
Explanation of most useful parameters with regards to your question:
-e
Encrypt the input data: this is the default.
-d
Decrypt the input data.
-k <password>
Only use this if you want to pass the password as an argument.
Usually you can leave this out and you will be prompted for a
password. The password is used to derive the actual key which
is used to encrypt your data. Using this parameter is typically
not considered secure because your password appears in
plain-text on the command line and will likely be recorded in
bash history.
-kfile <filename>
Read the password from the first line of <filename> instead of
from the command line as above.
-a
base64 process the data. This means that if encryption is taking
place the data is base64 encoded after encryption. If decryption
is set then the input data is base64 decoded before being
decrypted.
You likely DON'T need to use this. This will likely increase the
file size for non-text data. Only use this if you need to send
data in the form of text format via email etc.
-salt
To use a salt (randomly generated) when encrypting. You always
want to use a salt while encrypting. This parameter is actually
redundant because a salt is used whether you use this or not
which is why it was not used in the "Short Answer" above!
-K key
The actual key to use: this must be represented as a string
comprised only of hex digits. If only the key is specified, the
IV must additionally be specified using the -iv option. When
both a key and a password are specified, the key given with the
-K option will be used and the IV generated from the password
will be taken. It probably does not make much sense to specify
both key and password.
-iv IV
The actual IV to use: this must be represented as a string
comprised only of hex digits. When only the key is specified
using the -K option, the IV must explicitly be defined. When a
password is being specified using one of the other options, the
IV is generated from this password.
-md digest
Use the specified digest to create the key from the passphrase.
The default algorithm as of this writing is sha-256. But this
has changed over time. It was md5 in the past. So you might want
to specify this parameter every time to alleviate problems when
moving your encrypted data from one system to another or when
updating openssl to a newer version.
Encrypt:
openssl enc -in infile.txt -out encrypted.dat -e -aes256 -k symmetrickey
Decrypt:
openssl enc -in encrypted.dat -out outfile.txt -d -aes256 -k symmetrickey
For details, see the openssl(1) docs.
DO NOT USE OPENSSL DEFAULT KEY DERIVATION.
Currently the accepted answer makes use of it and it's no longer recommended and secure.
It is very feasible for an attacker to simply brute force the key.
https://www.ietf.org/rfc/rfc2898.txt
PBKDF1 applies a hash function, which shall be MD2 [6], MD5 [19] or
SHA-1 [18], to derive keys. The length of the derived key is bounded
by the length of the hash function output, which is 16 octets for MD2
and MD5 and 20 octets for SHA-1. PBKDF1 is compatible with the key
derivation process in PKCS #5 v1.5. PBKDF1 is recommended only for compatibility with existing
applications since the keys it produces may not be large enough for
some applications.
PBKDF2 applies a pseudorandom function (see Appendix B.1 for an
example) to derive keys. The length of the derived key is essentially
unbounded. (However, the maximum effective search space for the derived key may be limited by the structure of the underlying
pseudorandom function. See Appendix B.1 for further discussion.)
PBKDF2 is recommended for new applications.
Do this:
openssl enc -aes-256-cbc -pbkdf2 -iter 20000 -in hello -out hello.enc -k meow
openssl enc -d -aes-256-cbc -pbkdf2 -iter 20000 -in hello.enc -out hello.out
Note: Iterations in decryption have to be the same as iterations in encryption.
Iterations have to be a minimum of 10000.
Here is a good answer on the number of iterations: https://security.stackexchange.com/a/3993
Also... we've got enough people here recommending GPG. Read the damn question.
As mentioned in the other answers, previous versions of openssl used a weak key derivation function to derive an AES encryption key from the password. However, openssl v1.1.1 supports a stronger key derivation function, where the key is derived from the password using pbkdf2 with a randomly generated salt, and multiple iterations of sha256 hashing (10,000 by default).
To encrypt a file:
openssl aes-256-cbc -e -salt -pbkdf2 -iter 10000 -in plaintextfilename -out encryptedfilename
To decrypt a file:
openssl aes-256-cbc -d -salt -pbkdf2 -iter 10000 -in encryptedfilename -out plaintextfilename
Note: An equivalent/compatible implementation in javascript (using the web crypto api) can be found at https://github.com/meixler/web-browser-based-file-encryption-decryption.
Update using a random generated public key.
Encypt:
openssl enc -aes-256-cbc -a -salt -in {raw data} -out {encrypted data} -pass file:{random key}
Decrypt:
openssl enc -d -aes-256-cbc -in {ciphered data} -out {raw data}
To Encrypt:
$ openssl bf < arquivo.txt > arquivo.txt.bf
To Decrypt:
$ openssl bf -d < arquivo.txt.bf > arquivo.txt
bf === Blowfish in CBC mode
There is an open source program that I find online it uses openssl to encrypt and decrypt files. It does this with a single password. The great thing about this open source script is that it deletes the original unencrypted file by shredding the file. But the dangerous thing about is once the original unencrypted file is gone you have to make sure you remember your password otherwise they be no other way to decrypt your file.
Here the link it is on github
https://github.com/EgbieAnderson1/linux_file_encryptor/blob/master/file_encrypt.py
Note that the OpenSSL CLI uses a weak non-standard algorithm to convert the passphrase to a key, and installing GPG results in various files added to your home directory and a gpg-agent background process running. If you want maximum portability and control with existing tools, you can use PHP or Python to access the lower-level APIs and directly pass in a full AES Key and IV.
Example PHP invocation via Bash:
IV='c2FtcGxlLWFlcy1pdjEyMw=='
KEY='Twsn8eh2w2HbVCF5zKArlY+Mv5ZwVyaGlk5QkeoSlmc='
INPUT=123456789023456
ENCRYPTED=$(php -r "print(openssl_encrypt('$INPUT','aes-256-ctr',base64_decode('$KEY'),OPENSSL_ZERO_PADDING,base64_decode('$IV')));")
echo '$ENCRYPTED='$ENCRYPTED
DECRYPTED=$(php -r "print(openssl_decrypt('$ENCRYPTED','aes-256-ctr',base64_decode('$KEY'),OPENSSL_ZERO_PADDING,base64_decode('$IV')));")
echo '$DECRYPTED='$DECRYPTED
This outputs:
$ENCRYPTED=nzRi252dayEsGXZOTPXW
$DECRYPTED=123456789023456
You could also use PHP's openssl_pbkdf2 function to convert a passphrase to a key securely.