1

I have following PowerShell commands

$a = 'MySecret'
$b = 'MySecretKey4Test'
$c = ConvertTo-SecureString $a -AsPlainText -Force | ConvertFrom-SecureString -Key ($b.ToCharArray() | % {[byte]$_})

Briefly, I am encrypting $a using $b as key. How can I decrypt resulting string $c under Linux, for example using openssl?

I tried these things

$b | out-file 'b.txt' -enc ascii
$c | out-file 'c.txt' -enc ascii

Then in same folder, I tried

openssl enc -d -aes128 -in c.txt -kfile b.txt

But it fails with "bad magic number" :(

1

1 Answer 1

2

I know this question is 4 years old, but it still came up at the top of my search results when I went looking for the same thing, and with no answer.

Here's the answer.

First use your script to create an encrypted string:

$a = 'MySecret'
$b = 'MySecretKey4Test'
$c = ConvertTo-SecureString $a -AsPlainText -Force | ConvertFrom-SecureString -Key ($b.ToCharArray() | % {[byte]$_})

Let's get our b (key) and c (encrypted string) into bash to begin with:

b="MySecretKey4Test"
c="76492d1116743f0423413b16050a5345MgB8ADkATgB4AEgAMQBZAHAAdABYAGgASgBJAGoAWABIAFMARgBoAHEANABhAHcAPQA9AHwAOABhADYANgBkAGUAZQBhAGIAMQBiADcANAA4ADMAZgA5AGUAYwA2ADEAZQBiADYAZAA5AGYAMgBmAGMAYgBmAGEANQBhADgAOAA4AGEAYgBhAGIAMgBiADAAYQA4AGYAMwBhAGYANwAyADUAYgA1AGMANgA4ADQAZQBjADgAMAA="

We need to convert the key to hexadecimal, being careful not to get a newline at the end.

read -r b < <(echo -n "$b"|xxd -p -c 9999)

We need to remove a fixed header from the beginning of the encrypted string. The fixed header is always 76492d1116743f0423413b16050a5345. Not sure why this is here, but it is.

c="${c/76492d1116743f0423413b16050a5345/}"

Next up, decode the encrypted string as base64 and pass it through iconv, to properly parse the utf16-le characters. Then split the result on | into an array (called parts here).

IFS='|' read -r -a parts < <(base64 -d <<< "$c"|iconv -f UTF16LE -co - -)

parts[0] is just a part count, which will be 2 and can be ignored. parts[1] is the cbc initialization vector in base64 format, but openssl wants it in hexadecimal.

read -r iv < <(base64 -d <<< "${parts[1]}"|xxd -p -c 99999)

parts[2] is the actual encrypted data in hexadecimal format.

read -r crypt <<< "${parts[2]}"

Now we decrypt, using the key ($b), iv ($iv) and encrypted data ($crypt). $crypt will need to be converted to binary first, so we use xxd.

read -r decrypted < <(openssl enc -d -A -aes-128-cbc -iv "$iv" -K "$b" < <(xxd -r -p <<< "$crypt"))
echo "$decrypted"

All together now:

b="MySecretKey4Test"
c="76492d1116743f0423413b16050a5345MgB8ADkATgB4AEgAMQBZAHAAdABYAGgASgBJAGoAWABIAFMARgBoAHEANABhAHcAPQA9AHwAOABhADYANgBkAGUAZQBhAGIAMQBiADcANAA4ADMAZgA5AGUAYwA2ADEAZQBiADYAZAA5AGYAMgBmAGMAYgBmAGEANQBhADgAOAA4AGEAYgBhAGIAMgBiADAAYQA4AGYAMwBhAGYANwAyADUAYgA1AGMANgA4ADQAZQBjADgAMAA="
read -r b < <(echo -n "$b"|xxd -p -c 9999)
c="${c/76492d1116743f0423413b16050a5345/}"
IFS='|' read -r -a parts < <(base64 -d <<< "$c"|iconv -f UTF16LE -co - -)
read -r iv < <(base64 -d <<< "${parts[1]}"|xxd -p -c 99999)
read -r crypt <<< "${parts[2]}"
read -r decrypted < <(openssl enc -d -A -aes-128-cbc -iv "$iv" -K "$b" < <(xxd -r -p <<< "$crypt"))
echo "$decrypted"

Results:

MySecret

Be aware that if you use a 32-byte (256bit) key instead of a 16-byte (128bit) key, use -aes-256-cbc in your openssl command instead of -aes-128-cbc

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.