Pages

HTTP authentication, base64 encoding

In the previous post dyndee.sh - dyndns update client, I faced a problem: I had to authenticate to dyndns.org but didn't want to use lynx, links or any other external tool.
For HTTP authentication to work I need to base64 encode the string "username:password"
I will try to explain each step.


First I had to get the decimal value of each character of the string. I couldn't find any function to do that, so what I did is to first create a string (using a loop) with all the ASCII chars and store it into a variable (ascii).
for ((i=0; i<128; i++)); do
ascii=$ascii$(echo -en $(printf "%s%o" "\\" "$i"))
done
ASCII consists of 128 characters (man ascii) Storing each ASCII character into a string will enable me to get each characters position from it, thus giving me its decimal value. For example having generated the ascii string, to get the decimal value of "B":
t="${ascii%%B*}"     # Removes everything after B, including B
Now the position of B would be the total length of t + 2
t=$((${#t}+2))
Why plus 2? Because (1) the null character was not printed in the ascii string and (2) because ${ascii%%B*} removes everything after B including B. Now I had to convert decimal to binary. To do that we need to divide the decimal by 2 until decimal becomes 0. The remainder of each division makes up our binary number.
while ((t>0)); do
d2b="$((t%2))$d2b"
t="$((t/2))"
done
I then create a string with all binaries in 8-bit form and pad it with 0's if needed.
bit8="$bit8$(printf "%08d" "$d2b")"
pad0=$(($((6-${#bit8}%6))%6))
((pad0)) && bit8=$bit8$(printf "%0$((pad0))d" 0)
After that, I had to convert every 6 bits of bit8 to uascii which is the international alphabet IA5.
uascii="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
In bash to convert from base n to decimal you can do decimal=$((n#number)) where n is the base
~$ t=120
~$ while ((t>0)); do d2b="$((t%2))$d2b"; t="$((t/2))"; done
~$ echo $d2b
1111000
~$ echo $((2#$d2b))
120
Therefore every 6-bit in our 8-bit string is converted to decimal and used as an index to uascii to create the encoded string.
for ((i=0; i<${#bit8}; i+=6)); do
encstr="$encstr${uascii:$((2#${bit8:i:6})):1}"
done
When I created the 8bit string, I might have used 0's to create a full 8bit. For each two 0's a "=" is added to our encoded string.
eqpad="=="
encstr="$encstr${eqpad:0:$((pad0/2))}"

No comments: