Reputation: 21
I am creating a function that will accept an input and determine if the value is a certain type of hash encoding (md5, sha1, sha256, and sha512). I have asked a few classmates and logically it makes sense, but clearly something is wrong.
#!/usr/bin/bash
function identify-hash() {
encryptinput=$(echo $1 | grep -E -i '^[a-z0-9=]+${32}')
if [[ -n $encryptinput ]]; then
echo "The $1 is a valid md5sum string"
exit
else
encryptinput=$(echo $1 | grep -E -i '^[a-z0-9=]+${40}')
if [[ -n $encryptinput ]]; then
echo "The $1 is a valid sha1sum string"
exit
else
encryptinput=$(echo $1 | grep -E -i '^[a-z0-9=]+${64}')
if [[ -n $encryptinput ]]; then
echo "The $1 is a valid sha256sum string"
exit
else
encryptinput=$(echo $1 | grep -E -i '^[a-z0-9=]+${128}')
if [[ -n $encryptinput ]]; then
echo "The $1 is a valid sha512sum string"
exit
else
echo "Unable to determine the hash function used to generate the input"
fi
fi
fi
fi
}
identify-hash $1
I know that hashes have a specific number of characters for them, but I don't know exactly why it's not working. Removing the {32} out of line 4 allows it to answer as a md5sum, but than it assumes everything is md5sum.
Suggestions?
Upvotes: 1
Views: 882
Reputation: 70822
Something shorter, using bash:
checkHash() {
local -ar sumnames=([32]=md5sum [40]=sha1sum [64]=sha256sum [128]=sha512sum)
[[ "$1" =~ [[:xdigit:]]{32,129} ]]
echo "${sumnames[${#BASH_REMATCH}]+String $BASH_REMATCH could be }${sumnames[
${#BASH_REMATCH}]:-No hash tool match this string.}"
}
This will extract [:xdigit:]
part out of any complete line:
checkHash 'Filename: 13aba32dbe4db7a7117ed40a25c29fa8 --'
String 13aba32dbe4db7a7117ed40a25c29fa8 could be md5sum
checkHash a32dba32dbe4db7a7117ed40a25c29fa8e4db7a7117ed40a25c29fa8
No hash tool match this string.
checkHash a32dba32dbe4db7a7117ed40a25c29fa8e4db7a7117ed40a25c29fa8da921adb
String a32dba32dbe4db7a7117ed40a25c29fa8e4db7a7117ed40a25c29fa8da921adb could be sha256sum
... then ${var+return this only if $var exist}
... and ${var:-return this if $var is empty}
Upvotes: 1
Reputation: 775
Further explaining @Gordon Davissons' comment and some basics for anyone who stops by
NB This answer is extremely simplified to apply only to the current question. here's my preferred guide for more regex
^
- start of a line$
- end of a line[...]
- list of possible characters
a-z
= all lowercase (English) letters; 0-9
= all digits; etc.[:xdigit:]
for hexadecimal characters
[[:xdigit:]]
- i.e [:class:]
inside [...]
{...}
- number of times the preceding expression should be matched
^[a]{1}$
will match a
but not aa
^f[o]{2}d$
will match food
but not fod, foood, fooo*d
^[a-z]{4}$
will match
ball
✔️ but not buffalo
❌cove
✔️ but not cover
❌^...$
) containing a string of exactly 4 (English) alphabetic characters{1,5}
- at least 1
and at most 5
*
- shorthand for {0,}
meaning 0 or any number of times+
- shorthand for {1,}
meaning at least 1; but no upper limit?
- shorthand for {1}
So ${32}
is looking for 32 "end of line" \n
in jargon and what you need is [a-z0-9=]{32}
instead
BUT as also pointed out by Andrej Podzimek in the comments you need to match only hexadecimal [0-9a-f]
characters which is the same as [:xdigit:]
. Either can be used.
PS
.
(fullstop/period) matches ANY character including spaces and special characters(...)
is to match patterns[a-z ]*(chicken).*
will match anything from chicken coop
to chicken soup
and please pass that chicken cookbook, Alex?
[.]
means period/fullstop not any characterz
this is to make space (ascii 32
) a possible character.
is case-insensituvePPS if it's for homework/assignment/schoolwork, please specify so in your question :)
Upvotes: 0
Reputation: 19555
Fixed your script. I advise you would have spotted most of the issues if you had used ShellCheck:
#!/usr/bin/env bash
identify_hash() {
# local variables
local -- encrypt_input
local -- sumname
# Regex capture the hexadecimal digits
if [[ "$1" =~ ([[:xdigit:]]+) ]]; then
encrypt_input="${BASH_REMATCH[1]}"
else
encrypt_input=''
fi
# Determine name of sum algorithm based on length of encrypt_input
case "${#encrypt_input}" in
32) sumname=md5sum ;;
40) sumname=sha1sum ;;
64) sumname=sha256sum ;;
128) sumname=sha512sum ;;
*) sumname=;;
esac
# If sum algorithm name found (sumname is not empty)
if [ -n "$sumname" ]; then
printf 'The %s is a valid %s string\n' "$encrypt_input" "$sumname"
else
printf 'Unable to determine the hash function used to generate the input\n' >&2
exit 1
fi
}
identify_hash "$1"
Upvotes: 2