AES128-CBC "bad magic number" and "error reading input file" - bash

I am trying to decrypt a file (part444.txt) with message:
y2EdLtmNQsZkvwwf8jf3fM6c1thfzF0sQfblayGIBik=
This is base64 encoded encrypted text under 128 bit AES in CBC mode. It is not padded. The IV is the first 16 bytes of the encrypted text and the key is h4ckth1sk3yp4d16.
I know that people received the bad magic number error from problems with Base64 but now I get the "error reading input file" and not sure where to go from here.
I have tried:
openssl enc -base64 -d part444.txt | openssl aes-128-cbc -d -k h4ckth1sk3yp4d16
Why am I encountering the errors "bad magic number" and "error reading input file"?

This is sort of a pain to do with openssl, because openssl's encryption makes assumptions about padding and deriving a salted key from the entered password that you have to deliberately turn off.
It's much easier to do in python with say PyCrypto, where these assumptions aren't made.
>>> import base64
>>> data = base64.b64decode('y2EdLtmNQsZkvwwf8jf3fM6c1thfzF0sQfblayGIBik=')
>>> from Crypto.Cipher import AES
>>> aes_crypter = AES.new('h4ckth1sk3yp4d16', AES.MODE_CBC, data[:16])
>>> aes_crypter.decrypt(data[16:]) # this gives the encrypted secret.
It is possible to do this with openssl, but you have to read the base64 encoded data -- take out the first 16 bytes and remember it as your $IV (after encoding it back to hex that openssl expects), start reading all the bytes after the first 16 and remember it as the $CIPHERTEXT (and say re-encode in base64). Similar for the $KEY, you have to convert it from ASCII to bytes in hex. Assuming you stored these in variables, then the following would work:
IV=`base64 -d part444.txt | xxd -p -l 16`
CIPHERTEXT=`base64 -d part444.txt | cut -b 17- | base64`
KEY=`echo -n h4ckth1sk3yp4d16 |xxd -p`
echo $CIPHERTEXT | openssl aes-128-cbc -d -a -nopad -K $KEY -iv $IV && echo ""
Note base64 -d decodes base64 to binary (using base64 from GNU coreutils; on BSD replace with base64 -D), base64 b64 encodes binary data, cut -b 17- reads from the 17th byte of data to the end of the file, and xxd -p converts binary to hex.

Related

if i know key=iv=text, can i crack AES?

The thing is, i want to encrypt some information on my disk.
The method i choose to encrypt my text is:
read pwd
key=${pwd}
iv=${pwd}
encrypt_info = $(echo ${text} | openssl enc -e -A -aes-256-cbc -a -K ${key} -iv ${iv} -nosalt)
But I do not want to enter my password every time I encrypt my information. So i put my "pubkey" somewhere public. The "pubkey" is generated in this way:
read password
pubkey=$(echo ${password} | openssl enc -e -A -aes-256-cbc -a -K ${password} -iv ${password} -nosalt)
I only enter my password every time i want to decrypt my text. Steps to decrypt:
Enter password
Calculate "pubkey" in the way above
If the pubkeys match, the password is the correct one.
Use the correct password to decrypt my information.
You see my steps. My question is, if some one get my "pubkey" and know that the "pubkey" is generated by the way above, can he/she crash my password?
openssl enc -e -A -aes-256-cbc -a -K ${password} -iv ${password} -nosalt)
With aes-256 the key needs to have 32 bytes and iv needs to have 16 bytes, so properly you cannot use the same value (it works for aes-128 though).
You are using the password as a key (-K parameter), so let's use a proper denotation key, which in this case should be 32 bytes hex encoded.
if some one get my "pubkey" and know that the "pubkey" is generated by the way above, can he/she crash my password?
no, that shouldn't be possible
If the pubkeys match, the password is the correct one.
Use the correct password to decrypt my information.
I don't really understand the reason behind the step. You can just try to decrypt the file and if the key is not current, the decryption fails on invalid padding.
Or - do you want to validate the key once when provided by the user? In that case you could validate a hash of the password
echo 'some password' | openssl dgst -sha256
Usually storing a simple hash of a user password is not secure enough, but assuming you provide a random 256 bit key, it should be ok.
iv=${pwd}
This seems to be a vulnerability, the cbc mode needs a random IV to be secure. Reusing the IV for multiple encryptions is not secure.
Maybe just let the openssl generate a random salt (and derive the key and IV from the salt and password) would solve the problem.
echo -n 'some text' | openssl enc -e -A -aes-128-cbc -k 'password' -a

Generating a SHA1 Signature with Different Results Between Ubuntu/Bash and Windows/Powershell

Why would these respective bash and powershell scripts return different signatures:
## (Ubuntu) Bash
now='Fri, 26 Jul 2019 12:32:36 -0400'
bucket="mybucket"
path="/"
awsKey="MSB0M3K06ELMOI65QXI1"
awsSsecret="706Fdj+LFKf8pf/2Wh5V8Q8jbgGUUQo3xSXr5sbt"
## Create the signature
message="GET\n\n\n${now}\n/${bucket}${path}"
messageSignature=$(echo -en "${message}" | openssl sha1 -hmac "${awsSsecret}" -binary | openssl base64)
echo $messageSignature
Returns >> 5oJM2L06LeTcbYSfN3fDFZ9yt5k=
## Powershell
$OutputEncoding = [Text.UTF8Encoding]::UTF8
$now='Fri, 26 Jul 2019 12:32:36 -0400'
$bucket="mybucket"
$path="/"
$awsKey="MSB0M3K06ELMOI65QXI1"
$awsSsecret="706Fdj+LFKf8pf/2Wh5V8Q8jbgGUUQo3xSXr5sbt"
## Create the signature
$message="GET\n\n\n${now}\n/${bucket}${path}"
$messageSignature=$(echo -en "${message}" | openssl sha1 -hmac "${awsSsecret}" -binary | openssl base64)
echo $messageSignature
Returns >> 77u/W8O5RwJeBsOodDddXeKUlCQD4pSUduKVrD3ilIxADQo=
]2
On Ubuntu, my shell is running "en_US.UTF-8".
I've run into the case where the signature is different on different systems: AIX, Windows w/Ubuntu, Windows w/Powershell, etc. I'm trying to figure out why.
There are at least three problems here: Powershell pipelines aren't binary-safe, you have the wrong variable name, and echo isn't portable/reliable.
At least according to this question, you can't pipe binary data in Powershell. The output of openssl (which is raw binary data) is getting treated as UTF-8 text (presumably due to $OutputEncoding), and mangled in the process. You can tell by decoding from base64 and looking in hex instead:
$ echo '77u/W8O5RwJeBsOodDddXeKUlCQD4pSUduKVrD3ilIxADQo=' | base64 -D | xxd
00000000: efbb bf5b c3b9 4702 5e06 c3a8 7437 5d5d ...[..G.^...t7]]
00000010: e294 9424 03e2 9494 76e2 95ac 3de2 948c ...$....v...=...
00000020: 400d 0a #..
It starts with EF BB BF, which is a UTF-8 byte order mark; and it ends with 0D 0A, which is a DOS/Windows line ending (ASCII carriage return and linefeed characters). Something else bad is happening as well, since it's much too long for a sha1 hash, even if you account for the BOM and line ending.
The output of echo is probably getting mangled similarly, so even if the hash wasn't mangled it'd be the hash of the wrong byte sequence.
See this question (and its answer) for an example of using Powershell's own tools to compute the HMAC-SHA1 of a string.
The message to be signed is in $message, but you actually sign $string_to_sign, which is undefined. The Ubuntu result is the correct HMAC-SHA1 for the null string:
$ </dev/null openssl sha1 -hmac "706Fdj+LFKf8pf/2Wh5V8Q8jbgGUUQo3xSXr5sbt" -binary | openssl base64
NCRRWG4nL9sN8QMrdmCPmUvNlYA=
As Lorinczy Zsigmond pointed out, echo -en isn't predictable. Under some implementations/OSes/shells/compile & runtime options/phases of moon/etc, it might or might not print "-en" as part of its output, and maybe also print a newline (or something) at the end. Use printf instead:
printf 'GET\n\n\n%s\n/%s%s' "${now}" "${bucket}" "${path}" | openssl sha1 ...
Or (in bash, but not all other shells):
printf -v message 'GET\n\n\n%s\n/%s%s' "${now}" "${bucket}" "${path}"
printf '%s' "$message" | openssl sha1 ...
Or (bash again):
nl=$'\n'
message="GET${nl}${nl}${nl}${now}${nl}/${bucket}${path}"
printf '%s' "$message" | openssl sha1 ...
Providing a summary for anyone who stumbled onto this thread. The problem problems were....
Cannot pass binary data through the pipeline as noted by Gordon Davisson
Need to represent newlines with "`n" instead of "\n"
The Powershell script that ultimately replicated my results in Ubuntu/Bash was...
$now='Fri, 26 Jul 2019 12:32:36 -0400'
$bucket="mybucket"
$path="/"
$awsKey="MSB0M3K06ELMOI65QXI1"
$awsSsecret="706Fdj+LFKf8pf/2Wh5V8Q8jbgGUUQo3xSXr5sbt"
$message="GET`n`n`n${now}`n/${bucket}${path}"
## Create the signature
$sha = [System.Security.Cryptography.KeyedHashAlgorithm]::Create("HMACSHA1")
$sha.Key = [System.Text.Encoding]::UTF8.Getbytes($awsSsecret)
[Convert]::Tobase64String($sha.ComputeHash([System.Text.Encoding]::UTF8.Getbytes($message)))
While it's a better idea to use printf over echo on Linux/Unix systems, that difference wasn't material in this use-case.

md5 hash function in binary format

I am trying to calculate the digests of a file using md5 algorithm. I am asked to format the output to be in binary not hex. So this is my command in terminal (I use mac):
openssl dgst -md5 -binary ~/Documents/msg_Joudi.txt > ~/Documents/hash.txt
this generates hash.txt file, but its content is not in binary format, and I do not know where is the error.
Create MD5 hash of file: msgFile.txt > Convert to Binary and save:
cat msgFile.txt | openssl dgst -md5 -binary > hash.bin.txt
Save binary in Base64 format:
cat msgFile.txt | openssl dgst -md5 -binary | base64 > hash.bin.b64.txt
Save binary in Hexadecimal representation:
cat msgFile.txt | openssl dgst -md5 -binary | xxd -b > hash.bin.hex.txt
The OP says he wants binary and then says "Binary should be 0s and 1s right?".
Although, probably unlikely, if he really wants a binary number output, do this:
$ echo -e "xx\nyy" >in.txt
$ perl -ln0777e 'use Digest::MD5 "md5"; print "0b".unpack("B*",md5($_))' <in.txt
0b001111000101011000010000100101100011010101000101111000101000000011110110011010110011010000!
Meaning of above:
slurp in whole file into $_, calculate md5 digest on $_ to create binary data
use unpack to convert binary data to binary number string
If he really wants binary data, modify the above:
$ perl -ln0777e 'use Digest::MD5 "md5"; print md5 $_' <in.txt >binout.txt

HMAC_256 using Message Authentication Code on Solaris

This problem is really leaving me astounded
Take a input file and create a HMAC_256 value from it using a private key
Base64 encode HMAC_256 hash
Code
#Create HMAC-SHA2 hash from shell parameter
filehash=`echo $1 | mac -a sha256_hmac -k test.key`
echo "HMAC_SHA256 hash : "$filehash
#Base64 encode filehash using openssl
filehash_64=`echo "$filehash" | /usr/sfw/bin//openssl enc -base64 | tr '\n' ' ' | cut -d " " -f2 `
echo "64 bit encoded hash : "$filehash_64
Using a test.key of
Bob123
Shell Input
Hello
Shell Output
SHA256 hash : 411796cfb1e6c30c1b39b589c79d6f8bf1fdde8d58fda4a6ec1e59538ecaa39a
64 bit encoded hash : ZWMxZTU5NTM4ZWNhYTM5YQo=
However if I go to these sites and do a HMAC_256 test they both generate a different hash
http://asecuritysite.com/encryption/hmac
http://jetcityorange.com/hmac/
They both Output a HMAC_256 hash of
a30410f584726f32ba3e6e823bfdecbdf28448d64e4ab8f11f6a2e66818b50fe
Why are they generating a different hash? I am assuming they are correct as they both have the same.
Does Solaris 10 have a bug with its MAC (Message Authentication Code)
tool?
Is it UTF8 or ASCII problem?
Is it a server problem, Windows / Unix?
I don't understand why I am generating a different hash to them, even though I am using the same hashing algorithm and key.
I'll guess that the problem is newline characters. The echo command puts a newline after "Hello", so if you don't want it, use "echo -n". Also make sure that there is no newline character in your key file.

Encrypting using 64-bit DES with openssl

I'm trying to do a very simple thing, namely using a 64-bit password and a 64-bit plaintext (both in hex) and encrypt it with simple old DES.
my script looks like this:
plaintext=`echo -n "$2" | sed 's/\(..\)/\\\x\1/g'`
key=$1
printf "$plaintext" | openssl enc -nosalt -e -des -nopad -K "$key" -iv "0000000000000000" | od --format=x1 --width=32 --address-radix=n | sed 's/ //g'
I execute and get the following result:
./des_enc 5B5A57676A56676E 675A69675E5A6B5A
b617e2c84a4fba2149dd7132433031392257b99d9284b1031c351c15825aca52
The problem is there's too much data coming back from openssl, I expect to only get 64-bits of data instead I get 512. I don't know how to explicit request a 64-bit version of DES, is it even possible?
Note: The values used above are from "H. Katzan, The Standard Data Encryption Algorithm, pp75-94, Petrocelli Books Inc., New York, 1977" is:
Key: 5B5A57676A56676E
Plaintext: 675A69675E5A6B5A
Ciphertext: 974AFFBF86022D1F
Use -des-ecb. Also, xxd makes this pipeline much cleaner, if you have it handy (it's part of the vim package):
sh % echo 675A69675E5A6B5A | xxd -r -ps | openssl enc -des-ecb -nopad -K 5B5A57676A56676E | xxd -ps
974affbf86022d1f

Resources