How should i shrink my bash script into 5 for loops? - bash

I am trying to shrink bash script so it do not have to rerun the same codes over and over again. but according to some people i can run the line at test dealing with all 4 encryption at 1 go.
help i do not know what do they meant by that.
Code Gore:
#!/bin/bash
LIST1=(K F L W )
LIST2=(8 2 9 2 )
LIST3=(x b s v )
LIST4=("~" "-" "[" "*" )
LIST5=("$" "+" "]" "%" )
encr1=".8742cNKlzqQ8Mgjip/Fg1"
salt1="bCgxj8Yt"
encr2="31HvJ8Iinxk2k"
salt2="31"
encr3="AyPVCzU.ourSwFdL3N6/YP9RRfIwwKZPNrnt0/yn5vB"
salt3="klPjs90j"
encr4="Cd9AjUI4nGglIcP3MByrZUnu.hHBJc7.eR0o/v0A1gu0/6ztFfBxeJgKTzpgoCLptJS2NnliZLZjO40LUseED/"
salt4="8899Uidd"
for i in "${LIST1[#]}"
do
for j in "${LIST2[#]}"
do
for k in "${LIST3[#]}"
do
for l in "${LIST4[#]}"
do
for a in "${LIST5[#]}"
do
test="$(mkpasswd -m MD5 "$i$j$k$l$a" -s $salt1 | cut -d"$" -f4)"
if [ "$test" == "$encr1" ] ; then
echo " MD5 Salted Hash Password is: $i$j$k$l$a"
echo " Salt: "$salt1""
for i in "${LIST1[#]}"
do
for j in "${LIST2[#]}"
do
for k in "${LIST3[#]}"
do
for l in "${LIST4[#]}"
do
for a in "${LIST5[#]}"
do
test="$(mkpasswd -m SHA-256 "$i$j$k$l$a" -s $salt3 | cut -d"$" -f4)"
if [ "$test" == "$encr3" ] ; then
echo " SHA-256 Salted Hash Password is: $i$j$k$l$a"
echo " Salt: "$salt3""
fi
done
done
done
done
done
for i in "${LIST1[#]}"
do
for j in "${LIST2[#]}"
do
for k in "${LIST3[#]}"
do
for l in "${LIST4[#]}"
do
for a in "${LIST5[#]}"
do
test="$(mkpasswd -m SHA-512 "$i$j$k$l$a" -s $salt4 | cut -d"$" -f4)"
if [ "$test" == "$encr4" ] ; then
echo " SHA-512 Salted Hash Password is: $i$j$k$l$a"
echo " Salt: "$salt4""
for i in "${LIST1[#]}"
do
for j in "${LIST2[#]}"
do
for k in "${LIST3[#]}"
do
for l in "${LIST4[#]}"
do
for a in "${LIST5[#]}"
do
test="$(mkpasswd -m des "$i$j$k$l$a" -s $salt2)"
if [ "$test" == "$encr2" ] ; then
echo " DES Salted Hash Password is: $i$j$k$l$a"
echo " Salt: "$salt2""
exit
fi
done
done
done
done
done
fi
done
done
done
done
done
fi
done
done
done
done
done
The Output still somehow displayed as i wanted:

Since you use the arrays LIST1 ... LIST5 only for the 5×for constructs I would replace them with brace expansions. That way you end up with only one loop.
Instead of manually listing and checking variable pairs like encr1 and salt1 use three arrays encr, salt, and algo (the algorithm you specified manually before). Then you can use a loop to iterate over all these triples instead of having to write each check manually.
#! /bin/bash
n=4
encr=(
".8742cNKlzqQ8Mgjip/Fg1"
"31HvJ8Iinxk2k"
"AyPVCzU.ourSwFdL3N6/YP9RRfIwwKZPNrnt0/yn5vB"
"Cd9AjUI4nGglIcP3MByrZUnu.hHBJc7.eR0o/v0A1gu0/6ztFfBxeJgKTzpgoCLptJS2NnliZLZjO40LUseED/"
)
salt=(bCgxj8Yt 31 klPjs90j 8899Uidd)
algo=(MD5 SHA-256 SHA-512 des)
for candidate in {K,F,L,W}{8,2,9}{x,b,s,v}{'~','-','[','*'}{'$','+',']','%'}; do
for (( i = 0; i < n; i++ )); do
test="$(mkpasswd -m "${algo[i]}" "$candidate" -s "${salt[i]}")"
if [ "$test" = "${encr[i]}" ]; then
echo " ${algo[i]} Salted Hash Password is: $candidate"
echo " Salt: ${salt[i]}"
fi
done
done
Here I removed the duplicated 2 from the 2nd symbol candidates. Thank you Gordon Davisson for pointing this out.
By the way: I used the variable names from your original script. However, it would be better to name the array of hashes something other than encr. Hashing and encryption differ – just like shredding a document and then picking ten of its pieces is different from locking the intact document away.

You can loop over all candidates in a single loop with combinatorial {} expansion:
for candidate in {K,F,L,W}{8,2,9,2}{x,b,s,v}{\~,-,[,\*}{$,+,],%}; do
...
done
Note that this is not POSIX, but works in bash and zsh.

In the current script, your loops and if blocks are all weirdly nested inside each other. The simple way to do this is just have one set of loops that generates candidate passwords, and for each candidate test all 4 hashes:
#!/bin/bash
LIST1=(K F L W )
LIST2=(8 2 9 2 )
LIST3=(x b s v )
LIST4=("~" "-" "[" "*" )
LIST5=('$' "+" "]" "%" )
encr1=".8742cNKlzqQ8Mgjip/Fg1"
salt1="bCgxj8Yt"
encr2="31HvJ8Iinxk2k"
salt2="31"
encr3="AyPVCzU.ourSwFdL3N6/YP9RRfIwwKZPNrnt0/yn5vB"
salt3="klPjs90j"
encr4="Cd9AjUI4nGglIcP3MByrZUnu.hHBJc7.eR0o/v0A1gu0/6ztFfBxeJgKTzpgoCLptJS2NnliZLZjO40LUseED/"
salt4="8899Uidd"
# Loop over characters to generate candidate passwords
for i in "${LIST1[#]}"; do
for j in "${LIST2[#]}"; do
for k in "${LIST3[#]}"; do
for l in "${LIST4[#]}"; do
for a in "${LIST5[#]}"; do
# For this candidate...
candidate="$i$j$k$l$a"
# test whether it matches the MD5 hash
test="$(mkpasswd -m MD5 "$candidate" -s "$salt1" | cut -d'$' -f4)"
if [ "$test" = "$encr1" ] ; then
echo " MD5 Salted Hash Password is: $candidate"
echo " Salt: $salt1"
fi
# test whether it matches the SHA-256 hash
test="$(mkpasswd -m SHA-256 "$candidate" -s "$salt3" | cut -d'$' -f4)"
if [ "$test" = "$encr3" ] ; then
echo " SHA-256 Salted Hash Password is: $candidate"
echo " Salt: $salt3"
fi
# test whether it matches the SHA-512 hash
test="$(mkpasswd -m SHA-512 "$candidate" -s "$salt4" | cut -d'$' -f4)"
if [ "$test" = "$encr4" ] ; then
echo " SHA-512 Salted Hash Password is: $candidate"
echo " Salt: $salt4"
fi
# test whether it matches the DES hash
test="$(mkpasswd -m des "$candidate" -s "$salt2")"
if [ "$test" = "$encr2" ] ; then
echo " DES Salted Hash Password is: $candidate"
echo " Salt: $salt2"
fi
done
done
done
done
done
Note that this will find the DES and SHA-512 passwords twice, because "2" is listed twice in LIST2.
This approach is a little less efficient than it could be, because it continues checking for matches to the hashes it's already found matches to. This could be fixed in several ways, but they'd all complicate the code more than I want to get into here. In the usual situation, where you're only looking for one match, you can just break out of the loops as soon as you find it.
BTW, I fixed the comparison operator (as #Jens pointed out, = is standard in a [ ] expression) and quoting (salts were not properly quoted, and using a literal $ in double-quotes is weird even when it's legal).

Related

shell - iterating a loop for a (validated) supplied number or range of numbers

I need to accept input from user (i.e. 'read').
This input can be either a single positive number or a range of numbers (in the form X-Y ).
I then need to validate this input and perform an iterative loop through the range of numbers (or just once in the case of only X).
examples:
1) User supplies: "8" or "8-"
Loop runs only a single time supplying the number 8
2) User supplies: "13-22"
Loop runs 11 times (13 through 22) referencing the number 13.
3) User supplies: "22-13"
Probably should behave like #2 above...but I'm open to other clean ways to validate the input.
I have worked on the following so far, which isn't very clean, complete, or even 100% correct for what I was asking - but it shows the effort and idea I'm going for:
echo "line?"; read -r deleteline
case "$deleteline" in
''|*[!0-9\-]*) echo "not a number";;
[1-9]|[1-9][0-9]*);;
esac
deleteline_lb=$(echo $deleteline|awk -F "-" '{print $1}')
deleteline_ub=$(echo $deleteline|awk -F "-" '{print $2}')
if [ ! $deleteline_lb = "" ] && [ ! "$deleteline_ub" = "" ]; then
delete_line_count=1
delete_line_count=$(expr $deleteline_ub - $deleteline_lb)
if [ $delete_line_count -le 0 ]; then
delete_line_count=1
fi
fi
i=1; while [ $i -le $delete_line_count ]; do
echo $deleteline_lb $i
i=$(($i + 1))
done
This needs to run in sh, things like seq are not supported - so stick with posix compliant methods...
To clarify I am looking to do the following (pseudo-code):
1) accept input from user
2) validate if input is in the form "#" or "#-#" (range).
3) Execute chosen (arbitrary) code path based on proper/improper input.
4) If single # is given then store that to variable to perform future operations against.
5) If range is given, store both numbers in variable to be able to perform the operation against the lower # up to the higher number. More specifically it would be "(higher #) - (lower #) + 1". So if range were 12-17 then we need to perform operation against 12, 6x. (17 - 12 + 1). IOW, 12-17 inclusive.
6) A way to easily denote if data set is range vs single number is also desired so that code path to each can be easily branched.
thanks for helping!
UPDATE:
Using my basic code I reworked it (with a bit of input from a friend), and basically came up with this:
while true;do
printf "\\delete lines? [e=Exit] ";read -r deleteline
case "$deleteline" in
[Ee]) break;;
*)
echo "$deleteline" | egrep -q '^[[:digit:]-]*$'
if [ $? -ne 0 ]; then
printf "\\n input is not a number.\\n"
else
delete_range_start=`echo $deleteline|awk -F "-" '{print $1}'`
delete_range_end=`echo $deleteline|awk -F "-" '{print $2}'`
if [ $delete_range_end -lt $delete_range_start ]; then
printf "\\n upper range must be higher than lower range.\\n"
else
if [ "$delete_range_end" = "" ]; then
delete_range_end=$delete_range_start
elif [ $delete_range_end -gt $lineNumbers ]; then
printf "\\Setting range to last entry\\n"
fi
break
fi
fi
;;
esac
done
deleteline=$delete_range_start
deleteloop=`expr $delete_range_end - $delete_range_start + 1`
i=1
while [ $i -le $deleteloop ]; do
# Insert all processing code in here
i=`expr $i + 1`
done
If you have a posix compliant awk, try this:
echo "$userInput" | awk -F- '
($1+0==$1&&$2+0==$2){
for(i=$1;($1<$2?i<=$2:i>=$2);)
print ($1<$2?i++:i--);
next
}
$1+0==$1{
print $1;
next
}
$2+0==$2{
print $2;
next
}
($1+0!=$1&&$2+0!=$2){
exit 1
}'
The script check if the 2 fields (separated with -) are numbers. If so, it prints these numbers in an ascending or descending way depending if the first number is greater or lower than the second one.
If only one input, the script just prints it.
If none of the field are number, it exits with a non zero value.
This script could be the validation step of a shell script like this:
$ cat test.sh
#!/bin/sh
echo -n "range: "
read -r range
validated_input=$(echo "$range" | awk -F- '($1+0==$1&&$2+0==$2){for(i=$1;($1<$2?i<=$2:i>=$2);)print ($1<$2?i++:i--);next}$1+0==$1{print $1;next}$2+0==$2{print $2;next}($1+0!=$1&&$2+0!=$2){exit 1}')
if [ $? -ne 0 ]; then
echo "Incorrect range" >&2
fi
for i in $validated_input; do
echo "$i"
done
Examples:
$ ./test.sh
range: 10-6
10
9
8
7
6
$ ./test.sh
range: 8-
8
$ ./test.sh
range: hello
Incorrect range

always giving password not strong enough message (else condition is running)

I have been working on this function in shell scripting to take up a password from a user and check if it satisfies the criteria of being an effective password but it always says password not strong enough. The password I'm trying to use is LK#12abc.
Here is my code:
function paq()
{
read -p "PASSWORD :-" password
pasq="^(?=.*[A-Z].*[A-Z])(?=.*[!##$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$"
if [[ $password =~ $pasq ]]; then
echo "Valid password"
echo "The password is:- $password" >> user1.txt
echo "$password" >>password.txt
else
echo "password not strong enough"
fi
}
paq
It appears your password has to have:
3 lower case letters
2 upper case letters
2 digits
1 punctuation character
exactly 8 characters long
So, with bash glob patterns:
if [[ $password == *[a-z]*[a-z]*[a-z]* ]] &&
[[ $password == *[A-Z]*[A-Z]* ]] &&
[[ $password == *[0-9]*[0-9]* ]] &&
[[ $password == *[!##$\&*]* ]] &&
(( ${#password} == 8 ))
then
echo password OK
else
echo password does not satisfy criteria
fi
I'm surprised that I need to escape the & in the 4th test
As it says in man bash:
An additional binary operator, =~, is available, with the same
precedence as == and !=. When it is used, the string to the right of
the operator is considered an extended regular expression and matched
accordingly (as in regex(3)).
The first problem is that POSIX regex does not allow for lookahead
and lookbehing assertions.
The second problem is that your test password is not correct - you
miss 8 random characters at the end.
The third problem is that you didn't specify the
shebang and didn't quote variables correctly.
All in all, your script should look like that:
#!/usr/bin/env bash
paq() {
read -r -p "PASSWORD :- " password
pasq="^(.*[A-Z].*[A-Z])(.*[!##$&*])(.*[0-9].*[0-9])(.*[a-z].*[a-z].*[a-z]).{8}$"
if [[ "$password" =~ $pasq ]]; then
echo "Valid password"
echo "The password is:- $password" >> user1.txt
echo "$password" >>password.txt
else
echo "password not strong enough"
fi
}
paq
Run it:
$ ./paq.sh
PASSWORD :- AB!11abc12345678
Valid password
You can take your original regex and feed it to grep -P (only if your system's grep supports Perl regular expressions). Then use the script:
while ! echo "$password" | grep -P '^(?=.*[A-Z].*[A-Z])(?=.*[!##$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$'
do
read -r -p "PASSWORD: " password
echo -e "Password not strong enough, it needs\n\
3 lower case letters\n\
2 upper case letters\n\
2 digits\n\
1 punctuation character\n\
exactly 8 characters long\n"
done
echo "Valid password"
echo "The password is:- $password" | tee user1.txt
Using tr to translate each wanted character classes to a digit, sorting that digit string and count matching with grep (using #glennjackman defined character classes except the exact length):
echo LK#12abc |
tr '[:digit:]' 1 | # do this first
tr '[:upper:]' 2 |
tr '[:lower:]' 3 |
tr '[:punct:]' 4 |
tr -c '[:digit:]' 5 | # all else to 5
grep -o . | # transpose
sort | # sort
tr -d '\n' | # transpose
if
grep -q "1\{2,\}2\{2,\}3\{3,\}4\{1,\}5" # 5 is the trailing newline
then
echo yes
else
echo no
fi # outputs
yes
( I was trying to tr '[:digit:][:upper:][:lower:]' '123' but apparently that won't work so each class is now processed on its own line. Maybe you could loose the trs, just sort the password string and count match classes with grep)

Storing output of here-string BC calculation into a variable for error-checking

I have an assignment for school which is to create a script that can calculate a math equation any length using order of operations. I had some trouble with this and ended up finding out about here-strings. The biggest problem with the script seems to be error-checking.
I tried to check the output of bc using $?, however it is 0 whether it is success or fail. In response to that I am now attempting to store the output of the here-string into a variable, and then I will use regex to check if output begins with a number. Here is the piece of code I wish to store in a variable, followed by the rest of my script.
#!/bin/bash
set -f
#the here-string bc command I wish to store output into variable
cat << EOF | bc
scale=2
$*
EOF
read -p "Make another calculation?" response
while [ $response = "y" ];do
read -p "Enter NUMBER OPERATOR NUMBER" calc1
cat << EOF | bc
scale=2
$calc1
EOF
read -p "Make another calculation?" response
done
~
This should do the trick:
#!/bin/sh
while read -p "Make another calculation? " response; [ "$response" = y ]; do
read -p "Enter NUMBER OPERATOR NUMBER: " calc1
result=$(bc << EOF 2>&1
scale=2
$calc1
EOF
)
case $result in
([0-9]*)
printf '%s\n' "$calc1 = $result";;
(*)
printf '%s\n' "Error, exiting"; break;;
esac
done
Sample run:
$ ./x.sh
Make another calculation? y
Enter NUMBER OPERATOR NUMBER: 5+5
5+5 = 10
Make another calculation? y
Enter NUMBER OPERATOR NUMBER: 1/0
Error, exiting
Note that you might do this without a here-document like this:
result=$(echo "scale=2; $calc1" | bc 2>&1)

Simple bash script (input letter output number)

Hi I'm looking to write a simple script which takes an input letter and outputs it's numerical equivalent :-
I was thinking of listing all letters as variables, then have bash read the input as a variable but from here I'm pretty stuck, any help would be awesome!
#!/bin/bash
echo "enter letter"
read "LET"
a=1
b=2
c=3
d=4
e=5
f=6
g=7
h=8
i=9
j=10
k=11
l=12
m=13
n=14
o=15
p=16
q=17
r=18
s=19
t=20
u=21
v=22
w=23
x=24
y=25
z=26
LET=${a..z}
if
$LET = [ ${a..z} ];
then
echo $NUM
sleep 5
echo "success!"
sleep 1
exit
else
echo "FAIL :("
exit
fi
Try this:
echo "Input letter"
read letter
result=$(($(printf "%d\n" \'$letter) - 65))
echo $result
0
ASCII equivalent of 'A' is 65 so all you've got to do to is to take away 65 (or 64, if you want to start with 1, not 0) from the letter you want to check. For lowercase the offset will be 97.
A funny one, abusing Bash's radix system:
read -n1 -p "Type a letter: " letter
if [[ $letter = [[:alpha:]] && $letter = [[:ascii:]] ]]; then
printf "\nCode: %d\n" "$((36#$letter-9))"
else
printf "\nSorry, you didn't enter a valid letter\n"
fi
The interesting part is the $((36#$letter-9)). The 36# part tells Bash to understand the following string as a number in radix 36 which consists of a string containing the digits and letters (case not important, so it'll work with uppercase letters too), with 36#a=10, 36#b=11, …, 36#z=35. So the conversion is just a matter of subtracting 9.
The read -n1 only reads one character from standard input. The [[ $letter = [[:alpha:]] && $letter = [[:ascii:]] ]] checks that letter is really an ascii letter. Without the [[:ascii:]] test, we would validate characters like é (depending on locale) and this would mess up with the conversion.
use these two functions to get chr and ord :
chr() {
[ "$1" -lt 256 ] || return 1
printf "\\$(printf '%03o' "$1")"
}
ord() {
LC_CTYPE=C printf '%d' "'$1"
}
echo $(chr 97)
a
USing od and tr
echo "type letter: "
read LET
echo "$LET" | tr -d "\n" | od -An -t uC
OR using -n
echo -n "$LET" | od -An -t uC
If you want it to start at a=1
echo $(( $(echo -n "$LET" | od -An -t uC) - 96 ))
Explanation
Pipes into the tr to remove the newline.
Use od to change to unsigned decimal.
late to the party: use an associative array:
# require bash version 4
declare -A letters
for letter in {a..z}; do
letters[$letter]=$((++i))
done
read -p "enter a single lower case letter: " letter
echo "the value of $letter is ${letters[$letter]:-N/A}"

Implement a Data Structure to Compare NTLM Hashfiles

Currently I'm in the process of simplifying a process for extracting Windows password hashes in security audits. Personally I want to make the process easier to generate a list of recovered users and their passwords when I do an audit. I think it would also be useful for other people who are trying to compare and generate large amounts of data.
So here's the gist:
When I extract all of the data from the Windows system files, I simplify them down to the format user:hash, where the hash is an NTLM hash such as "a87f3a357d73085c45f9416be5787e86."
I then will use oclHashcat and attempt to crack the hashes, whether it be dictionary or brute-force, it doesn't matter. I generate an output of all of the recovered hashes, however Hashcat generates them in the format hash:password.
Now here's my problem and what I would like some input on - I want to produce the output as user:password given the two input files. Considering that I can have hundreds of hashes yet only a few recovered passwords, there is no use of trying to order the lists.
I am unsure which data structure might benefit me the most. Arrays were too inefficient for large tables. I've looked into serialization and I've been exploring the use of Hash Maps and Hash Tables. Given the size of the hash, I haven't had any luck implementing either of these methods, or I'm doing so incorrectly.
Currently I'm running the program like so:
program [user:hash file] [hash:password file] -o [user:password output]
And I'm effectively trying to run the program like so (briefly):
Load Files
// user:hash file
For each line, split by ':' delimiter
before delimiter = table1.user
after delimiter = table1.hash
// hash:password file
For each line, split by ':' delimiter
before delimiter = table2.hash
after delimiter = table2.password
// generate user:password file
Check each entry of table1 vs table2
if table1.hash = table2.hash
table1.user = output.user
table2.password = output.password
print to output "output.user:output.password"
I am only trying to figure out an efficient method for tracing through each line and extracting the necessary data into a data structure that I can easily trace through.
If I need to clarify anything, please let me know. Any help is appreciated!
I would do this for my data structure
std::map<std::string,std::string> hash_user_map;
No go through all the users and hashes from table 1
For each user in table1
hash_user_map[table1.hash] = table1.user;
No go through all the cracked passwords with hashes from table2
std::string user = hash_user_map[table2.hash];
std::cout << user << ":" << table2.password << "\n;
I decided to go with a shell script, and I used an associated array to match the required data that I needed.
Note: Most of this program deals with the way my hash files are formatted. Look at the comments in the script.
#!/bin/bash
# Signus
# User-Password Hash Comparison Tool v1.0
# Simple utility that allows for the comparison between a file with a 'user:hash' format to a separate file with a 'hash:password' format. The comparison matches the hashes and returns an output file in the format 'user:password'
# Example of 'user:hash' -> george:c21cfaebe1d69ac9e2e4e1e2dc383bac
# Example of 'hash:password' -> c21cfaebe1d69ac9e2e4e1e2dc383bac:password
# 'user:hash' obtained from creddump suite: http://code.google.com/p/creddump/
# Note: Used custom 'dshashes.py' file: http://ptscripts.googlecode.com/svn/trunk/dshashes.py
# 'hash:password' obtained from ocl-Hashcat output
usage="Usage: $0 [-i user:hash input] [-t hash:password input] [-o output]"
declare -a a1
declare -a a2
declare -A o
index1=0
index2=0
countA1=0
countA2=0
matchCount=0
if [ -z "$*" ]; then
echo $usage
exit 1
fi
if [ $# -ne 6 ]; then
echo "Error: Invalid number of arguments."
echo $usage
exit 1
fi
echo -e
echo "---Checking Files---"
while getopts ":i:t:o:" option; do
case $option in
i) inputFile1="$OPTARG"
if [ ! -f $inputFile1 ]; then
echo "Unable to find or open file: $inputFile1"
exit 1
fi
echo "Reading...$inputFile1"
;;
t) inputFile2="$OPTARG"
if [ ! -f $inputFile2 ]; then
echo "Unable to find or open file: $inputFile2"
exit 1
fi
echo "Reading...$inputFile2"
;;
o) outputFile="$OPTARG"
echo "Writing...$outputFile"
;;
[?]) echo $usage >&2
exit 1
;;
esac
done
shift $(($OPTIND-1))
#First read the files and cut each line into an array
echo -e
echo "---Reading Files---"
while read LINE
do
a1[$index1]="$LINE"
index1=$(($index1+1))
countA1=$(($countA1+1))
done < $inputFile1
echo "Read $countA1 lines in $inputFile1"
while read LINE
do
a2[$index2]="$LINE"
index2=$(($index2+1))
countA2=$(($countA2+1))
done < $inputFile2
echo "Read $countA2 lines in $inputFile2"
#Then cut each item out of the array and store it into separate variables
echo -e
echo "Searching for Matches..."
for (( j=0; j<${#a2[#]}; j++ ))
do
hash2=$(echo ${a2[$j]} | cut -d: -f1)
pword=$(echo ${a2[$j]} | cut -d: -f2)
for (( i=0; i<${#a1[#]}; i++ ))
do
us=$(echo ${a1[$i]} | cut -d: -f1)
hash1=$(echo ${a1[$i]} | cut -d: -f2)
if [ "$hash2" = "$hash1" ]; then
matchCount=$(($matchCount+1))
o["$us"]=$pword
echo -e "Match Found[$matchCount]: \t Username:$us \t Password:$pword"
break
fi
done
done
echo -e "Matches Found: $matchCount\n" >> $outputFile
for k in ${!o[#]}
do
echo -e "Username: $k \t Password: ${o[$k]}" >> $outputFile
done
echo -e "\nWrote $matchCount lines to $outputFile"
unset o

Resources