I implemented a 100% BASH Base32 decoder according to Sectio 6 of RFC4648.
Download:
- base32d.v1.1.sh (sig) (sha1: cdf9100662efd6d9b31d087f98197a385d54df7a) – updated to take advantage of BASH return values and bitwise operations
- base32d.v1.0.sh (sig) (sha1: 314f0cb9b395c8cbad323163ef5adc246cdea66c)
#!/bin/bash # base32d.sh v1.1 September 21, 2014 # Copyright (c) 2014 Kenji Yoshino https://www.tidgubi.com # This script is released under the Version 3 of the GNU General Public # License https://www.gnu.org/licenses/gpl-3.0.txt # # This script implements 100% BASH base32 decoding as specified in section 6 of # https://tools.ietf.org/html/rfc4648 function base32dErrorMsg { printf 'Invalid character encountered.\n' } # decodeChar $ch # converts Encoded char to Value according to Table 3 of RFC4648 and treat # lowercase as valid characters. function decodeChar { local ch="${1:0:1}" # if this is an = or empty, return 0, but exit 2 to flag that this is the # end of the input if [[ "$ch" = '=' || "${#ch}" -eq 0 ]]; then printf '0' exit 2 fi # convert the char to its ASCII Value local val=$(printf '%d' "'$ch") # shift lowercase to upper case if [[ $val -gt 96 ]]; then (( val -= 32 )) fi # shift the ASCII value to convert it to the 0-31 value if [[ $val -gt 55 ]]; then (( val -= 65)) else (( val -= 24)) fi # Verify that the decoded value is valid if [[ $val -gt 31 || $val -lt 0 ]]; then base32dErrorMsg exit 1 fi printf "$val" } function base32dUsage { printf 'Usage: base32d.sh [ | -f] [-h]\n' printf '\n' exit 1 } function base32dexit { if [[ "$1" -eq 2 ]]; then printf '\n' exit 0 elif [[ "$1" -eq 1 ]]; then base32dErrorMsg exit 1 fi } function base32d { # verify that any command line parameters are valid. local input local prefix='\x' if [[ "$#" -gt 0 ]]; then if [[ "$1" = '-f' ]]; then if [[ "$2" = '-' ]]; then input=$(cat) elif [[ -r "$2" ]]; then input=$(cat "$2") else printf 'Cannot access the specified file.\n' exit 1 fi if [[ "$3" = '-h' ]]; then prefix='' fi elif [[ "$1" = '-h' ]]; then input=$(cat) prefix='' else input="$1" if [[ "$2" = '-h' ]]; then prefix='' fi fi else input=$(cat) fi local ndx=0 local len=${#input} local buffer local term=0 local val while [ $ndx -lt $len ]; do # parse the next quantum (40 bits) of characters out of the input buffer=$(decodeChar "${input:$ndx:1}") || base32dexit $? #1 (( buffer <<= 5 )) (( ndx++ )) val=$(decodeChar "${input:$ndx:1}"); term=$? #2 (( buffer |= val )) # print the first 5 + 3 bits printf "$prefix$(printf '%02x' $(( buffer >> 2 )) )" # 1st byte base32dexit $term (( buffer <<= 5 )) (( ndx++ )) val=$(decodeChar "${input:$ndx:1}") || base32dexit $? #3 (( buffer |= val )) (( buffer <<= 5 )) (( ndx++ )) val=$(decodeChar "${input:$ndx:1}"); term=$? #4 (( buffer |= val )) (( buffer &= 0xFFF )) # print 2 + 5 + 1 bits printf "$prefix$(printf '%02x' $(( buffer >> 4 )) )" # 2nd byte base32dexit $term (( buffer <<= 5 )) (( ndx++ )) val=$(decodeChar "${input:$ndx:1}") || base32dexit $? #5 (( buffer |= val )) (( buffer &= 0x1FF )) printf "$prefix$(printf '%02x' $(( buffer >> 1 )) )" #3rd byte base32dexit $term (( buffer <<= 5 )) (( ndx++ )) val=$(decodeChar "${input:$ndx:1}") || base32dexit $? #6 (( buffer |= val )) (( buffer <<= 5 )) (( ndx++ )) val=$(decodeChar "${input:$ndx:1}"); term=$? #7 (( buffer |= val )) (( buffer &= 0x7FF )) printf "$prefix$(printf '%02x' $(( buffer >> 3 )) )" # 4th byte base32dexit $term (( buffer <<= 5 )) (( ndx++ )) val=$(decodeChar "${input:$ndx:1}") || base32dexit $? #8 (( buffer |= val )) printf "$prefix$(printf '%02x' $(( buffer & 0xFF )) )" # 5th byte (( ndx++ )) done printf '\n' exit 0 } case $# in 0) base32d ;; 1) base32d "$1" ;; 2) base32d "$1" "$2" ;; *) base32d "$1" "$2" "$3" ;; esac