Encrypt a String Using Openssl Command Line

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 a small text using openssl with a given public Key

The output of the openssl rsautl command that you posted is raw bytes, not text. That's why the output looks garbled when you open it in notepad.

If you want the output of openssl rsautl to be displayable text, you can encode the output using base64 encoding, then write the base64 encoded ciphertext to a file. This can be done by stringing a few commands together on the command line, like so:

openssl rsautl -encrypt -pubin -inkey pub.key -in plaintext.txt | base64 > encrypted.txt

You should be able to open encrypted.txt in notepad, or view it on the command line, and see the base64 encoded ciphertext.

To decrypt the base64 encoded ciphertext, you would to the following:

cat encrypted.txt | base64 -d | openssl rsautl -decrypt -inkey priv.key

How to provide string IV and Key to openssl decrypt command?

The openssl enc command by default uses a randomly generated salt value when encrypting. It starts the output with that value, preceded by a "magic number" that represents the characters Salted__. Taking the enc version of your command, you can see that illustrated here:

$ printf 1234567890123456 | openssl enc -aes-256-cbc -iv 0123456789012345 -k 01234567890123456789012345678901 | hexdump -C
00000000 53 61 6c 74 65 64 5f 5f ed 6c b5 aa e2 92 4a 00 |Salted__.l....J.|
00000010 68 f7 b2 40 d2 44 44 8b fa 4c 05 95 99 cf 76 32 |h..@.DD..L....v2|
00000020 4e 15 37 65 93 00 d6 b2 ff 4d 1b 6c af 46 64 f6 |N.7e.....M.l.Fd.|
00000030

When decrypting, this same magic number is expected. Your file does not contain it, hence the error. This is an OpenSSL proprietary thing.

It is possible (but not recommended) to avoid the salting, using the -nosalt option:

$ printf 1234567890123456 | openssl enc -aes-256-cbc  -iv 0123456789012345 -k 01234567890123456789012345678901 -nosalt | hexdump -C
00000000 54 05 6a fb c3 60 a9 32 3d 2e e0 4c 2a 21 4a a1 |T.j..`.2=..L*!J.|
00000010 3c a7 34 f3 8f c4 15 33 99 dd 08 f7 e5 ef ea 57 |<.4....3.......W|
00000020

Using that same -nosalt option on your decryption command, you should no longer get that bad magic number. You may still run into other issues, depending on what kind of padding (if any) you used when encrypting your data, but you did not give enough information to draw any conclusions on that.


Like mentioned in the comments, there is a difference between -k lowercase and -K uppercase. It is relevant for your situation and you are probably using the wrong one. Check out the openssl enc man page for more info, and to read more about the -nosalt option as well.

Decrypt String with OpenSSL Issue Output

From the (limited) description of what you are doing, two flaws can be identified.

First, the website that you are using does apply padding when encrypting data. The plaintext that you provided consists of 48 bytes:

$ echo -n 'e679932d-12b2-48a2-8ef7-301cdb9ab57b289YH3ITIXRH' | wc -c
48

This is a multiple of 16. But the ciphertext is 64 bytes long. This can be seen by base64 decoding the ciphertext string before feeding it into wc:

$ echo -n 'AjL4iV8YSGnNOCQYOJXIP97GjCAYp2k0QLm56XxJN0p/yu5xQh5uitX3UmfP3bzZaXDd2u6hMwp6cxO3cNL1cg==' | openssl base64 -A -d | wc -c
64

The fact that 16 bytes are added to the ciphertext even though your plaintext was a multiple of 16 bytes long means that padding is applied. So in your openssl command, you should not use the -nopad option.

Secondly, your openssl command provides the secret key as a passphrase, whereas the website does not interpret the 'Secret Key' input field as a passphrase. In stead of using -pass in your openssl command(s), you should be using -K, which gives the key as an actual sequence of byte values.

As an example, the following openssl commands can be successfully reproduced in the website form:

$ echo -n '1234567890123456' | openssl enc -aes-128-ecb -K 6162636465666768696a6b6c6d6e6f70 -nosalt -base64 -A -out string.txt
$ cat string.txt
M3q3c85LGdEj9k8iep/J145kzoc/F027JCP82BRYDhU=

for encryption and

$ cat string.txt | openssl enc -d -aes-128-ecb -K 6162636465666768696a6b6c6d6e6f70 -nosalt -base64 -A
1234567890123456

for decryption.

To achieve the same results in the website, the string to be used in the plaintext input field is 1234567890123456 and the string to be used in the Secret Key input field is abcdefghijklmnop. The contents of the field "AES Encrypted Output" will be the same as the contents of string.txt, and that is what you need to enter into the field "text to be Decrypted" as well.

(The -n flag for echo and the -A flag for openssl enc are used to avoid newlines being added at the end).

Decrypt a text with OpenSSL using key and salt only

@Wasif and I spent some time debugging in chat and in the end believe it's most likely a compatbility issue between OpenSSL 1.1.1.d on Windows and OpenSSL 1.1.1.b on macOS.

We went through a number of tests and permutations, using (Key, IV) tuples in hex, using passwords, with and without salts, and ultimately our testing came down to a simple check.

Using openssl enc -a -aes-256-cbc -pass pass:MYPASSWORD -p -in input.txt on Windows we got:

salt=E70092FEBA619144 
key=29631452F8C259DFE6FD8E9372EC4B20392395F36B7A0B11769CEBEA987E90A0
iv =93BF2E94462A43B23EF585C0F4B3F1A8
U2FsdGVkX1/nAJL+umGRRGi3ybIPFXf7qrgov7SyXnI=

Using openssl aes-256-cbc -d -a -pass pass:MYPASSWORD -in cipherText.txt (which contains 'U2FsdGVkX1/nAJL+umGRRGi3ybIPFXf7qrgov7SyXnI=' on the Mac we got:

4593573484:error:06FFF064:digital envelope routines:CRYPTO_internal:bad decrypt

Despite this simple test failing, the Mac and Windows boxes successfully encrypted and decrypted locally.

Weird, but this looks like version incompatibility.

openssl-encrypt, PHP vs commandline - how to make IVs same

This works for me

  <?php
// encrypt/decrypt string
$output = false;
$encrypt_method = "AES-256-CBC";
$key = hex2bin('905E17D5F5E4939D48BD04FF47F9DE906375B87B67068B2CE5D1BBBBC8DCA291');
$iv = hex2bin('905E17D5F5E4939D0000000000000000');
$string = "123456789ABCDEFG123456789ABCDEFG123456789ABCDEFG";

$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);

echo $output;
?>

and in the CLI

echo -n "123456789ABCDEFG123456789ABCDEFG123456789ABCDEFG" |openssl aes-256-cbc -a -K 905e17d5f5e4939d48bd04ff47f9de906375b87b67068b2ce5d1bbbbc8dca291 -iv 905E17D5F5E4939D0000000000000000 -nosalt 

The differences are

  1. I removed the line break in the CLI with echo -n "foo" instead of echo "foo"
    (Otherwise you encrypt a different string ten in the PHP code).
  2. The CLI uses a hexadecimal string,Therefore also in PHP the key string needs to be converted to hex with hex2bin().


Related Topics



Leave a reply



Submit