I'm looking for a (possibly cryptographic strong) hash function in Bash with the following properties:
- The input is only a string with 4 lower-case characters: aaaa to zzzz
- The output should be a decimal number (with leading zeros) in range: 0000 to 9999
- Low number of collusionscollisions and hash values distributed as evenly as possible
- Surjective (each output should appear)
- Chaos (should have a good diffusion of hash values)
- Optional: Confusing (it should not be possible to draw any conclusions about the input value from the hash value)
I have not yet found a (simple) algorithm that would fulfillfulfil these requirements.
This is my approach. How would you rate it?
#!/bin/bash
# ord() - converts ASCII character to its decimal value
ord() {
printf '%d' "'$1"
}
my_hash_4 () {
s=$1
while (( ${#s} < 4 ));
do
s="${s}a"
done
hash=0
multiplier=1
for i in $(seq 0 3);
do
j=$(ord "${s:$i:1}")
hash=$((hash+(multiplier*(j-97)*961)))
multiplier=$((multiplier*26))
done
# (int) (10_000 / Math.pow(26, 4) * hash) % 10_000
hash=$((((10000000*hash)/456976000)%10000))
printf '%04d\n' "$hash"
}
my_hash_4 "$1"
Example output:
bash my_hash.sh aaaa
0000
bash my_hash.sh baaa
0021
bash my_hash.sh abaa
0546
bash my_hash.sh bbaa
0567
bash my_hash.sh zzzz
9978
bash my_hash.sh hallo
2292