This is my sixth week of intern in AESTE. I started the week with discussing with Maisha on how should I get started on using Wt. She taught me some of the basic stuff of Wt and with the help of Peter, they set up a simple Wt Application template for me to write my HOTP library on the template and also so that my work will not conflict with theirs. I am really fortunate because all my current colleague are basically experts in Wt, any problem I faced could request SOS from them~

This week my aim is to use Wt to generate HOTP withWt hashe functions (SHA1 and MD5). From Wt library there are 2types of function capable of generating Hashes for both SHA1 and MD5 namely (Wt::Utils::sha1 and Wt::Auth::SHA1HashFunction::compute, the same goes with MD5). For sha1 only one message is being process to generate a sets of 20bytes data, while for SHA1HashFunction two messages are process to generate a sets of 20bytes data. To be able to implement HOTP for Wt, SHA1HashFunction will be used because HMAC-SHA1 is needed which requires 2messages.

HMAC-SHA1 Code with Wt

Wt::Auth::SHA1HashFunction f;
std::string hash = f.compute(Counters, istring);
hash = Wt::Auth::Utils::decodeAscii(hash);
std::string hash1 = f.compute(hash, ostring);
hash1 = Wt::Auth::Utils::decodeAscii(hash1);
hash1 = Wt::Utils::hexEncode(hash1);

The above code is the simplest form to obtain a HMAC-SHA1 data with Wt. Follow the document RFC2104 to know what is ‘istring’ = k_ipad and ‘ostring’ = o_ipad. The idea behind decodeAscii is because the ‘f.compute’ function returns an encodedAscii of string. Therefore this return data must be decoded first into an UTF-8 form and then re-encoded into HEX format to be able to manipulate the data to suit my application. With the above code ‘hash1’ will have a string of HEX data (20bytes in this case) and these data is the HMAC-SHA1 that I desired. After some simple code manipulation these HEX data will become a HOTP value, follow this document RFC4226.


ERROR one might encounter
  1. f.compute(string, string) both messages must be in a string, to make life easier is to parse string into the function, however sometimes an Array can also be used but need to be convert to a string beforehand can write the following code.

    std::string Counters(text, text + sizeof text / sizeof text[0]); //text is an array: unsigned char text[8] = {0};

  2. Many string conversion, encode, decode are necessary for Wt, the main disadvantage/advantage for Wt is that most of the data are in string format, which is why many conversion are needed, therefore use ‘std:stringstream’ for all variable is much recommended.
  3. The idea behind decodedAscii first and then only HexEncode my data is because, directly encodeHex from encodedAscii (which was return from the Wt function) will return wrong data, from my experiment is that 27bytes of data will be return after encodeHex from encodedAscii. So follow the method above, it will not fail.
  4. Finally after deciding which 8byte of HEX data needed for the HOTP (based on RFC4226). To convert the HEX data into Decimal use the following code:

    unsigned int HOTPDecimal = std::stoul(s, nullptr, 16); //s is a string with 8byte of HEX data


 

For HMAC-MD5 is exactly the same thing, just change the ‘Wt::Auth::SHA1Hashfunction’ to ‘Wt::Auth::MD5HashFunction’ and then 16byte of HEX data will be return. The only issue for HMAC-MD5 is that there are only 16bytes of data and for HOTP the maximum offset value is 15. This will cause the HOTP data (8byte HEX data) to have an empty string when the offset value is 15.

 


Case Study:

HMAC-MD5 = 0x80070713463e7749b90c2dc24911e27f

With the above HEX data, offset = 15, thus the 8byte data will start from ‘7f ? ? ? ? ? ? ‘ the problem is the empty string right after ‘7f’, to solve this problem I first string stream HMAC-MD5 and place extra ‘0’ char into the HMAC-MD5 to make it into a 19byte data to carter for this empty string issue.

std::stringstream HexZeroAdd;
HexZeroAdd << hash1 << “000000”;

By adding extra ‘0’ char into the MD5, the HOTP value later can be generated correctly. Of course another reason ‘0’ was inserted rather than ‘1’ or other value is because for the HOTPMD5 in my PIC18, the HEX data also have ‘0’ right after offset = 15.


 

After successfully implemented HOTP for Wt, I was given PIC32 from my boss and my next task will be to have PIC32 able to do basically all the things I had done for PIC18 and add TSL for PIC32. Looking forward to next week with more PIC32 programming and Wednesday for PUBLIC HOLIDAY!!! Woots~ less 1day to work for this week!