Quote:
1st rule:
Old: If key is a length 40/64/128 case-insensitive hex string, it is decoded to become a text string that is then UTF-8 encoded, and any 0x00's stripped. If the string is entirely 0x00's, the key is $null.
New: These hex strings should instead be decoded to binary keys of length 20/32/64 the same way base32 strings are being decoded to their binary contents.

When I originally researched this topic, I based the design of $hotp()/$totp() on many of the real-world C/C++ examples, discussions, and examples I found. So, for example, UTF-8 encoding all of the formats was something that was common to the implementations I saw, so that is what mIRC does. UTF-8 encoding obviously breaks keys that include null bytes. So the question is, are null bytes actually allowed?

Quote:
3rd rule:
Old: If the key length is 16/24/32 and contains only spaces or case-insensitive Base-32 characters, the spaces are stripped and the remaining Base-32 characters of arbitrary length are decoded into a binary key.
New: The target key lengths should instead be 16/26/32, and should be compared against the string length only after the spaces are removed. The spaces should be used only to group the characters into the same pattern presented by Google Authenticator, such as groups of 4 non-spaces, and valid strings should probably not include mixed-case letters.

Puzzling. mIRC's implementation uses 16/24/32 because that is what other implementations were using.

As it took a lot of time to research, implement, and validate these identifiers originally, I will need to go through this process again. I have added this to my to-do list.