Initial commit of stable v1.0
This commit is contained in:
519
zotp.inc.sh
Normal file
519
zotp.inc.sh
Normal file
@@ -0,0 +1,519 @@
|
||||
#!/bin/bash
|
||||
|
||||
## zOTP Bash - Generates/Tests One Time Pins in Bash Scripts
|
||||
## Version : 1.0
|
||||
## Author : Ze'ev Schurmann
|
||||
## Git Repo : https://git.3volve.net.za/thisiszeev/zotp-bash
|
||||
## Reddit : u/thisiszeev
|
||||
## License : GPL3
|
||||
##
|
||||
## One Time Pins generated using newOTP are unique to the minute. So from minute to minute the OTPs will be different.
|
||||
## When using testOTP to verify an OTP, you can assign a validity time in minutes from 1 minute to 120 minutes.
|
||||
##
|
||||
## Either copy and paste the functions to your project or use "source /path/to/zotp.inc.sh" above your main code.
|
||||
## If you copy and paste the functions in your project, please also include this commented out text.
|
||||
##
|
||||
## Don't forget to declare "thesalt" and "theseed" in your code before you call the functions newOTP and testOTP.
|
||||
##
|
||||
## "thesalt" must be a string unique to your project or to each instance of the project. This avoids other projects getting the same OTP at the same time.
|
||||
## Example:
|
||||
## declare thesalt="Name of project or service"
|
||||
## **Only needs to be declared once, ideally at the start of your code**
|
||||
##
|
||||
## "theseed" must be a string unique to the user the OTP is for. This avoids other users getting the same OTP at the same time.
|
||||
## Example:
|
||||
## declare theseed="user@domain.tld"
|
||||
## **Needs to be declared each time the current user changes**
|
||||
##
|
||||
## I do plan to port these functions to Perl, Python3 and PHP. I will make sure the OTPs created in one language can be verified in another.
|
||||
## If there is demand for other languages then I am willing to put it on my to-do list. Send me a chat request on Reddit.
|
||||
## Or maybe you keen to do a port to another language, send me a chat request and we can chat. I will link your port in the Git Repo for this project.
|
||||
|
||||
function cmdAwk1 {
|
||||
## cmdAwk1 is a pre/post command pipeline used by the function genHash.
|
||||
awk '{print $1}'
|
||||
}
|
||||
|
||||
function genHash {
|
||||
## genHash will calculate a hexidecimal hash string from a provided sting of any length or format using one of several Hashing Algorithms.
|
||||
## Outputs the hash as a string of hexadecimal digits. Used by the functions newOTP and testOTP.
|
||||
##
|
||||
## Usage:
|
||||
## genHash "{input-string}" {hash}
|
||||
## {input-string} - A string of any kind. Supports ESCAPE codes such as \n \t \r \$ etc. [REQUIRED - MUST BE ENCLOSED IN SINGLE OR DOULBE QUOTES]
|
||||
## {hash-algorithm} - The hashing algorithm used for generating the hexadecimal hash string [OPTIONAL - Defaults to MD5 if omitted]
|
||||
## **The above must be given in the order of input-string first and optional hash-algorithm after. The input-string is case sensitive but the hash-algorithm is not case sensitive**
|
||||
##
|
||||
## Examples:
|
||||
## Calculate a Blake2 Hash using a short string if text:
|
||||
## variablename="$(genHash "This is a short string of text." b2)"
|
||||
##
|
||||
## Calculate a SHA512 Hash using a multiline string of text:
|
||||
## variablename="$(genHash "
|
||||
## This is the first line of text.
|
||||
## This is the second line of text.
|
||||
## This is the third line of text.
|
||||
## " sha512)"
|
||||
##
|
||||
## Supported Hashing Algorithms:
|
||||
## b2 - Blake2 (up to 512bit) - 128 digits - Very High Entropy - Fast
|
||||
## md5 - Message Digest Algorithm 5 (128bit) - 32 digits - Very Low Entropy - Fast
|
||||
## sha - Secure Hash Algorithm (160bit) - 40 digits - Low Entropy - Fast
|
||||
## sha1 - Secure Hash Algorithm (160bit) - 40 digits - Low Entropy - Fast
|
||||
## sha224 - Secure Hash Algorithm (224bit) - 56 digits - Medium Entropy - Slow
|
||||
## sha256 - Secure Hash Algorithm (256bit) - 64 digits - High Entropy - Slow
|
||||
## sha384 - Secure Hash Algorithm (384bit) - 96 digits - Very High Entropy - Medium
|
||||
## sha512 - Secure Hash Algorithm (512bit) - 128 digits - Very High Entropy - Medium
|
||||
## **sha and sha1 are the same algorithm, but I've included both variants as some systems execute it as shasum and others as sha1sum.**
|
||||
## **Not all of these algorithms are available in Bash on all systems. Please test first. The function will output an error message**
|
||||
## **to the terminal and give an exit code 3 if the chosen algorithm is not found on your system.**
|
||||
##
|
||||
## Exit Codes:
|
||||
## 0 - Hash successfully calculated
|
||||
## 11 - Function encounted an error and could not calculate the Hash (No data given)
|
||||
## 23 - Function encounted an error and could not calculate the Hash (Invalid hashing algorithm given)
|
||||
## 29 - Function encounted an error and could not calculate the Hash (Hashing Algorithm not found)
|
||||
|
||||
local -A hashcmds=(
|
||||
[b2]="b2sum"
|
||||
[md5]="md5sum"
|
||||
[sha]="shasum"
|
||||
[sha1]="sha1sum"
|
||||
[sha224]="sha224sum"
|
||||
[sha256]="sha256sum"
|
||||
[sha384]="sha384sum"
|
||||
[sha512]="sha512sum"
|
||||
)
|
||||
|
||||
local -A precmds=(
|
||||
[b2]=""
|
||||
[md5]=""
|
||||
[sha]=""
|
||||
[sha1]=""
|
||||
[sha224]=""
|
||||
[sha256]=""
|
||||
[sha384]=""
|
||||
[sha512]=""
|
||||
)
|
||||
|
||||
local -A postcmds=(
|
||||
[b2]="cmdAwk1"
|
||||
[md5]="cmdAwk1"
|
||||
[sha]="cmdAwk1"
|
||||
[sha1]="cmdAwk1"
|
||||
[sha224]="cmdAwk1"
|
||||
[sha256]="cmdAwk1"
|
||||
[sha384]="cmdAwk1"
|
||||
[sha512]="cmdAwk1"
|
||||
)
|
||||
|
||||
if [[ -z "${1}" ]]; then
|
||||
echo "ERROR: function genHash - No data given... Must give string input..." >&2
|
||||
return 11
|
||||
fi
|
||||
|
||||
if [[ -z "${2}" ]]; then
|
||||
local hashcmd="md5sum"
|
||||
local precmd=""
|
||||
local postcmd="cmdAwk1"
|
||||
else
|
||||
if [[ -z "${hashcmds[${2,,}]}" ]]; then
|
||||
echo "ERROR: function genHash - Invalid hashing algorithm given..." >&2
|
||||
return 23
|
||||
else
|
||||
local hashcmd="${hashcmds[${2,,}]}"
|
||||
local precmd="${precmds[${2,,}]}"
|
||||
local postcmd="${postcmds[${2,,}]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$(whereis "${hashcmd}" | awk '{print $2}')" ]]; then
|
||||
echo "ERROR: function genHash - Hashing Algorithm not found... ${hashcmd} is not supported on this system..." >&2
|
||||
return 29
|
||||
fi
|
||||
|
||||
if [[ -z "${precmd}" ]] && [[ -z "${postcmd}" ]]; then
|
||||
echo -e "${1}" | ${hashcmd}
|
||||
elif [[ -z "${precmd}" ]] && [[ -n "${postcmd}" ]]; then
|
||||
echo -e "${1}" | ${hashcmd} | ${postcmd}
|
||||
elif [[ -n "${precmd}" ]] && [[ -z "${postcmd}" ]]; then
|
||||
echo -e "${1}" | ${precmd} | ${hashcmd}
|
||||
elif [[ -n "${precmd}" ]] && [[ -n "${postcmd}" ]]; then
|
||||
echo -e "${1}" | ${precmd} | ${hashcmd} | ${postcmd}
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function genOTP {
|
||||
## genOTP will calculate an OTP using 1 to 3 hexadecimal hash strings of 32 digits or more. Outputs the OTP as text digits. Used by the functions newOTP and testOTP.
|
||||
##
|
||||
## Usage:
|
||||
## genOTP {hash-one} {hash-two} {hash-three} {number-of-digits}
|
||||
## {hash-one} - A hexadecimal hash string of 32 digits or more [REQUIRED]
|
||||
## {hash-two} - A hexadecimal hash string of 32 digits or more [OPTIONAL - Defaults to a string of zeros equal in length to hash-one if omitted]
|
||||
## {hash-three} - A hexadecimal hash string of 32 digits or more [OPTIONAL - Defaults to a string of zeros equal in length to hash-one o hash-two, which ever is shorter, if omitted]
|
||||
## {number-of-digits} - An integer from 4 to 16 [OPTIONAL - Defaults to 6 if omitted]
|
||||
## **The above can be given in any order and is not case sensitive**
|
||||
##
|
||||
## Examples:
|
||||
## Calculate a custom 5 digit OTP using a single hash:
|
||||
## variablename="$(genOTP d03d5fc2f2b73c917cee8d0bc1153b5affe4a243 5)"
|
||||
##
|
||||
## Calculate a custom 8 digit OTP using three hashes:
|
||||
## variablename="$(genOTP 09bf8c7563e7d577e07cca414b37c572a5e1676d 7540acafd1bb0ce0383e38859379e2c062cac45c 316fa3932ec66d9778be4df6132b4544d46ab146 8)"
|
||||
##
|
||||
## Exit Codes:
|
||||
## 0 - OTP successfully calculated
|
||||
## 11 - Function encounted an error and could not calculate OTP (No data given)
|
||||
## 12 - Function encounted an error and could not calculate OTP (Too much data given)
|
||||
## 13 - Function encounted an error and could not calculate OTP (Invalid data given)
|
||||
## 72 - Function encounted an error and could not calculate OTP (Too many OTP size integers given)
|
||||
## 81 - Function encounted an error and could not calculate OTP (No hexadecimal hash strings given)
|
||||
## 82 - Function encounted an error and could not calculate OTP (Too many hexadecimal hash strings given)
|
||||
## 84 - Function encounted an error and could not calculate OTP (Given hexadecimal hash string is too short)
|
||||
|
||||
local optdigits=1
|
||||
local opthashes=3
|
||||
local digits=6
|
||||
local -a hashes
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "ERROR: function genOTP - No data given... Must give at least one hexadecimal hash string of at least 32 digits..." >&2
|
||||
return 11
|
||||
fi
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
if [[ ${optdigits} -eq 0 ]] && [[ ${opthashes} -eq 0 ]]; then
|
||||
echo "ERROR: function genOTP - Too much data given... Only one integer from 4 to 16 for number of OTP digits and one to three hexadecimal hash strings of 32 digits or more can be given..." >&2
|
||||
return 12
|
||||
fi
|
||||
if [[ "${1}" =~ ^([4-9]|1[0-6])$ ]]; then
|
||||
if [[ ${optdigits} -gt 0 ]]; then
|
||||
digits=${1}
|
||||
((optdigits--))
|
||||
else
|
||||
echo "ERROR: function genOTP - Too many OTP size integers given... Only one integer from 4 to 16 for number of OTP digits can be given..." >&2
|
||||
return 72
|
||||
fi
|
||||
elif [[ "${1}" =~ ^[0-9a-fA-F]+$ ]]; then
|
||||
if [[ ${opthashes} -gt 0 ]]; then
|
||||
if [[ ${#1} -lt 32 ]]; then
|
||||
echo "ERROR: function genOTP - Given hexadecimal hash string is too short... Only hexadecimal hash strings of 32 digits or more can be given..." >&2
|
||||
return 84
|
||||
fi
|
||||
hashes+=("${1,,}")
|
||||
((opthashes--))
|
||||
else
|
||||
echo "ERROR: function genOTP - Too many hexadecimal hash strings given... Only one to three hexadecimal hash strings of 32 digits or more can be given..." >&2
|
||||
return 82
|
||||
fi
|
||||
elif [[ "${1}" == "" ]]; then
|
||||
local donothing=0
|
||||
else
|
||||
echo "ERROR: function genOTP - Invalid data given... Only one integer from 4 to 16 for number of OTP digits and one to three hexadecimal hash strings of 32 digits or more can be given..." >&2
|
||||
return 13
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ ${#hashes[@]} -eq 0 ]]; then
|
||||
echo "ERROR: function genOTP - No hexadecimal hash strings given... Must give at least one hexadecimal string of at least 32 digits..." >&2
|
||||
return 81
|
||||
fi
|
||||
|
||||
local hashlength=${#hashes[0]}
|
||||
|
||||
while [[ ${#hashes[@]} -lt 3 ]]; do
|
||||
hashes+=("$(printf '%0*d\n' "${hashlength}" 0)")
|
||||
done
|
||||
|
||||
local n
|
||||
|
||||
for ((n=1; n<3; n++)); do
|
||||
if [[ ${#hashes[${n}]} -lt ${hashlength} ]]; then
|
||||
hashlength=${#hashes[${n}]}
|
||||
fi
|
||||
done
|
||||
|
||||
local -A hex2dec=(
|
||||
[0]=0
|
||||
[1]=1
|
||||
[2]=2
|
||||
[3]=3
|
||||
[4]=4
|
||||
[5]=5
|
||||
[6]=6
|
||||
[7]=7
|
||||
[8]=8
|
||||
[9]=9
|
||||
[a]=10
|
||||
[b]=11
|
||||
[c]=12
|
||||
[d]=13
|
||||
[e]=14
|
||||
[f]=15
|
||||
)
|
||||
|
||||
local -a values
|
||||
local position
|
||||
local sum
|
||||
|
||||
for ((position=0; position<hashlength; position++)); do
|
||||
(( sum =
|
||||
hex2dec[${hashes[0]:position:1}] +
|
||||
hex2dec[${hashes[1]:position:1}] +
|
||||
hex2dec[${hashes[2]:position:1}]
|
||||
))
|
||||
(( value = (sum + sum % 3 + 1) % 16 ))
|
||||
values+=(${value})
|
||||
done
|
||||
|
||||
local offset=$((hashlength/digits))
|
||||
local value
|
||||
|
||||
for ((digit=0; digit<digits; digit++)); do
|
||||
value=0
|
||||
for ((position=0; position<offset; position++)); do
|
||||
value=$((value+${values[$((position*digits+digit))]}))
|
||||
done
|
||||
value=$((value%10))
|
||||
echo -n ${value}
|
||||
done
|
||||
echo
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function newOTP {
|
||||
## newOTP will create a new OTP based on the current time (to the minute). Outputs the OTP as text digits.
|
||||
##
|
||||
## Usage:
|
||||
## newOTP {number-of-digits} {hash-algorithm}
|
||||
## {number-of-digits} - An integer from 4 to 16 [OPTIONAL - Defaults to 6 if omitted]
|
||||
## {hash-algorithm} - The hashing algorithm used for generating OTPs [OPTIONAL - Defaults to MD5 if omitted]
|
||||
## See comments provided in the function genHash
|
||||
## **The above can be given in any order and is not case sensitive**
|
||||
##
|
||||
## Examples:
|
||||
## Create a new 7 digit OTP using Default Hashing Agorithm:
|
||||
## declare thesalt="Name of project or service"
|
||||
## declare theseed="user@domain.tld"
|
||||
## variablename="$(newOTP 7)"
|
||||
##
|
||||
## Create a new 4 digit OTP using SHA384:
|
||||
## declare thesalt="Name of project or service"
|
||||
## declare theseed="user@domain.tld"
|
||||
## variablename="$(newOTP 4 sha384)"
|
||||
##
|
||||
## Exit Codes:
|
||||
## 0 - OTP successfully created
|
||||
## 12 - Function encounted an error and could not create OTP (Too much data given)
|
||||
## 13 - Function encounted an error and could not create OTP (Invalid data given)
|
||||
## 22 - Function encounted an error and could not create OTP (Too many hash algorithm strings given)
|
||||
## 72 - Function encounted an error and could not create OTP (Too many OTP size integers given)
|
||||
|
||||
local optdigits=1
|
||||
local optsums=1
|
||||
local digits=6
|
||||
local hashsum="md5"
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
if [[ ${optdigits} -eq 0 ]] && [[ ${optsums} -eq 0 ]]; then
|
||||
echo "ERROR: function newOTP - Too much data given... Only one integer from 4 to 16 for number of OTP digits and one string of 2 characters or more for Hash Algorithm can be given..." >&2
|
||||
return 12
|
||||
fi
|
||||
if [[ "${1}" =~ ^([4-9]|1[0-6])$ ]]; then
|
||||
if [[ ${optdigits} -gt 0 ]]; then
|
||||
digits=${1}
|
||||
((optdigits--))
|
||||
else
|
||||
echo "ERROR: function newOTP - Too many OTP size integers given... Only one integer from 4 to 16 for number of OTP digits can be given..." >&2
|
||||
return 72
|
||||
fi
|
||||
elif [[ "${1}" =~ ^[0-9a-zA-Z][0-9a-zA-Z]+$ ]]; then
|
||||
if [[ ${optsums} -gt 0 ]]; then
|
||||
hashsum="${1,,}"
|
||||
((optsums--))
|
||||
else
|
||||
echo "ERROR: function newOTP - Too many hash algorithm strings given... Only one string of 2 characters or more for Hash Algorithm can be given..." >&2
|
||||
return 22
|
||||
fi
|
||||
elif [[ "${1}" == "" ]]; then
|
||||
local donothing=0
|
||||
else
|
||||
echo "ERROR: function newOTP - Invalid data given... Only one integer from 4 to 16 for number of OTP digits and one string of 2 characters or more for Hash Algorithm can be given..." >&2
|
||||
return 13
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ -z "${thesalt}" ]] || [[ "${thesalt}" == "" ]]; then
|
||||
local salthash=""
|
||||
echo "WARNING: Variable \${thesalt} has not been declared with a value... Assign it a string unique to the service the OTP is being used for to avoid other services getting the same OTP..." >&2
|
||||
else
|
||||
local salthash="$(genHash "${thesalt}" "${hashsum}")"
|
||||
fi
|
||||
if [[ -z "${theseed}" ]] || [[ "${theseed}" == "" ]]; then
|
||||
local seedhash=""
|
||||
echo "WARNING: Variable \${theseed} has not been declared with a value... Assign it a string unique to the user account the OTP is being used for to avoid other users getting the same OTP..." >&2
|
||||
else
|
||||
local seedhash="$(genHash "${theseed}" "${hashsum}")"
|
||||
fi
|
||||
|
||||
local timehash="$(genHash "$(date -u "+%Y%B%d%H%M%A%U%u")" "${hashsum}")"
|
||||
|
||||
genOTP "${seedhash}" "${salthash}" "${timehash}" ${digits}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function testOTP {
|
||||
## testOTP will verify if an OTP is still valid and correct. Outputs the text "VALID" (exit code 0) or "INVALID" (exit code 255).
|
||||
##
|
||||
## Usage:
|
||||
## testOTP {OTP} {valid-minutes} {hash-algorithm} {quiet}
|
||||
## {OTP} - A 4 to 16 digit OTP to be verified [REQUIRED]
|
||||
## {valid-minutes} - The time in minutes (from 1 to 120) the OTP is valid for [OPTIONAL - Defaults to 30 minutes if omitted]
|
||||
## {hash-algorithm} - The hashing algorithm used for generating OTPs [OPTIONAL - Defaults to MD5 if omitted]
|
||||
## See comments provided in the function genHash
|
||||
## {quiet} - Disables text output when verifying allowing you to rely on exit codes instead. [OPTIONAL]
|
||||
## You can use just the letter "q" as an alternative to "quiet"
|
||||
## **The above can be given in any order and is not case sensitive**
|
||||
##
|
||||
## Examples:
|
||||
## Using text output for validation over 15 minutes:
|
||||
## declare thesalt="Name of project or service"
|
||||
## declare theseed="user@domain.tld"
|
||||
## if [[ "$(testOTP 123456 15)" == "VALID" ]]; then
|
||||
## echo "OTP is valid..."
|
||||
## else
|
||||
## echo "OTP is invalid or expired..."
|
||||
## fi
|
||||
##
|
||||
## Using exit code for validation over 45 minutes:
|
||||
## declare thesalt="Name of project or service"
|
||||
## declare theseed="user@domain.tld"
|
||||
## if testOTP 123456 45 q; then
|
||||
## echo "OTP is valid..."
|
||||
## else
|
||||
## echo "OTP is invalid or expired..."
|
||||
## fi
|
||||
##
|
||||
## Exit Codes:
|
||||
## 0 - OTP is VALID
|
||||
## 11 - Function encounted an error and could not verify OTP (No data given)
|
||||
## 12 - Function encounted an error and could not verify OTP (Too much data given)
|
||||
## 13 - Function encounted an error and could not verify OTP (Invalid data given)
|
||||
## 33 - Function encounted an error and could not verify OTP (Too many hash algorithm strings given)
|
||||
## 41 - Function encounted an error and could not verify OTP (No OTP given)
|
||||
## 43 - Function encounted an error and could not verify OTP (Too many OTPs given)
|
||||
## 53 - Function encounted an error and could not verify OTP (Too many minute integers given)
|
||||
## 55 - Function encounted an error and could not verify OTP (Minute integer given to high)
|
||||
## 63 - Function encounted an error and could not verify OTP (Too many "quiet" strings given)
|
||||
## 255 - OTP is INVALID or EXPIRED
|
||||
|
||||
local optotps=1
|
||||
local optvalids=1
|
||||
local optsums=1
|
||||
local optquiets=1
|
||||
local theotp
|
||||
local quiet=false
|
||||
local validminutes=30
|
||||
local hashsum="md5"
|
||||
local digits=0
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "ERROR: function testOTP - No data given... Must at least give one OTP of 4 to 16 digits..." >&2
|
||||
return 11
|
||||
fi
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
if [[ ${optotps} -eq 0 ]] && [[ ${optvalids} -eq 0 ]] && [[ ${optsums} -eq 0 ]] && [[ ${optquiets} -eq 0 ]]; then
|
||||
echo "ERROR: function testOTP - Too much data given... Only one OTP of 4 to 16 digits, one integer from 1 to 120 for valid time in minutes, one string of 2 characters or more for Hash Algorithm can be given and optional string \"quiet\" for silent mode relying on exit code 0 for MATCH and 255 for NO MATCH..." >&2
|
||||
return 12
|
||||
fi
|
||||
if [[ "${1}" =~ ^[0-9]+$ ]] && [[ ${#1} -ge 4 ]] && [[ ${#1} -le 16 ]]; then
|
||||
if [[ ${optotps} -gt 0 ]]; then
|
||||
theotp=${1}
|
||||
digits=${#theotp}
|
||||
((optotps--))
|
||||
else
|
||||
echo "ERROR: function testOTP - Too many OTPs given... Only one OTP of 4 to 16 digits can be given..." >&2
|
||||
return 43
|
||||
fi
|
||||
elif [[ "${1}" =~ ^([1-9]|[1-9][0-9]+)$ ]]; then
|
||||
if [[ ${optvalids} -gt 0 ]]; then
|
||||
if [[ ${1} -gt 120 ]]; then
|
||||
echo "ERROR: function testOTP - Minute integer given to high... Integer must be from 1 to 120 for valid time in minutes can be given..." >&2
|
||||
return 55
|
||||
fi
|
||||
validminutes=${1}
|
||||
((optvalids--))
|
||||
else
|
||||
echo "ERROR: function testOTP - Too many minute integers given... Only one integer from 1 to 120 for valid time in minutes can be given..." >&2
|
||||
return 53
|
||||
fi
|
||||
elif [[ "${1,,}" =~ ^(q|quiet)$ ]]; then
|
||||
if [[ ${optquiets} -gt 0 ]]; then
|
||||
quiet=true
|
||||
((optquiets--))
|
||||
else
|
||||
echo "ERROR: function testOTP - Too many \"quiet\" strings given... Only one optional string \"quiet\" for silent mode can be given relying on exit code 0 for MATCH and 255 for NO MATCH..." >&2
|
||||
return 63
|
||||
fi
|
||||
elif [[ "${1}" =~ ^[0-9a-zA-Z][0-9a-zA-Z]+$ ]]; then
|
||||
if [[ ${optsums} -gt 0 ]]; then
|
||||
hashsum="${1,,}"
|
||||
((optsums--))
|
||||
else
|
||||
echo "ERROR: function testOTP - Too many hash algorithm strings given... Only one string of 2 characters or more for Hash Algorithm can be given..." >&2
|
||||
return 33
|
||||
fi
|
||||
elif [[ "${1}" == "" ]]; then
|
||||
local donothing=0
|
||||
else
|
||||
echo "ERROR: function testOTP - Invalid data given... Only one OTP of 4 to 16 digits, one integer from 1 to 120 for valid time in minutes, one string of 2 characters or more for Hash Algorithm can be given and optional string \"quiet\" for silent mode relying on exit code 0 for MATCH and 255 for NO MATCH..." >&2
|
||||
return 13
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ ${digits} -eq 0 ]]; then
|
||||
echo "ERROR: function testOTP - No OTP given... Must give one OTP of 4 to 16 digits..." >&2
|
||||
return 41
|
||||
fi
|
||||
|
||||
if [[ -z "${thesalt}" ]] || [[ "${thesalt}" == "" ]]; then
|
||||
local salthash=""
|
||||
echo "WARNING: Variable \${thesalt} has not been declared with a value... Assign it a string unique to the service the OTP is being used for to avoid other services getting the same OTP..." >&2
|
||||
else
|
||||
local salthash="$(genHash "${thesalt}" "${hashsum}")"
|
||||
fi
|
||||
if [[ -z "${theseed}" ]] || [[ "${theseed}" == "" ]]; then
|
||||
local seedhash=""
|
||||
echo "WARNING: Variable \${theseed} has not been declared with a value... Assign it a string unique to the user account the OTP is being used for to avoid other users getting the same OTP..." >&2
|
||||
else
|
||||
local seedhash="$(genHash "${theseed}" "${hashsum}")"
|
||||
fi
|
||||
|
||||
local n
|
||||
|
||||
((validminutes++))
|
||||
for ((n=0; n<${validminutes}; n++)); do
|
||||
local timehash="$(genHash "$(date -u -d "${n} minutes ago" "+%Y%B%d%H%M%A%U%u")" "${hashsum}")"
|
||||
genOTP "${seedhash}" "${salthash}" "${timehash}" ${digits}
|
||||
done | grep -q ^${theotp}$
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
if [[ ${quiet} == false ]]; then
|
||||
echo "VALID"
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
if [[ ${quiet} == false ]]; then
|
||||
echo "INVALID"
|
||||
fi
|
||||
return 255
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user