mIRC Home    About    Download    Register    News    Help

Print Thread
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
I have located 2 edge cases where I don't find $hotp() performing correctly.

1. When key is length 16/24/32 containing only the case-insensitive 32 characters of the Base-32 alphabet, it uses the length 10/15/20 binary string obtained from the Base-32-decoding of the key parameter. However when the key is a case-insensitive hexadecimal string of length 40/64/128, instead of Base-16-decoding the key to the binary string of length 20/32/64, $hotp allows 0x00 as part of the binary key, but appears to utf8-encode bytes 0x80 thru 0xff before using them as part of the key. These return identical values but should not, due to the text string being utf8-encoded:

Code:
//echo -a $hotp($str(é,20),1,sha256,9) $hotp($str(e9,20),1,sha256,9)


The above both return the same 348960335 password, but from a 20-byte password of all 0xe9 bytes I was expecting the 2nd password to be 661185583.

2. Because the COUNT parameter is translated from a text number into a big-endian binary 64-bit value that's used as an 8-byte binary message parameter when calling $hmac(), the only valid values should be 0 thru 2^64-1. All invalid COUNT values above 18446744073709551615 return identical passwords to the password when using the max valid 2^64-1. I can't find the RFC saying what to do with invalid count values, but I would think $hotp should either return $null or use the lowest 64 bits of the COUNT parameter when the number is out of range. Negative 64-bit numbers are being handled so that negative N returns the same password as 2^64 less N, and that choice seems more appropriate than making them all be the same.

Joined: Dec 2002
Posts: 5,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
Thanks for your bug report. Indeed, this is due to the design of the identifier. It guesses what the format is based on the number of characters and the string content. So, the first example is 20 characters of é as plain text and gets converted to UTF8 and processed. The second example is 40 characters of hex, gets converted into literal characters from hex, into UTF-8, and processed. There are no plans to change how this works at this point.

As for the count issue, this is present throughout mIRC and in many identifiers. When a number is specified that goes beyond the min/max limits, when converted or used in calculations, it simply wraps around and that is the result that is returned to and used by mIRC

Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
The strings being base-32 encoded are not being handled the same way as these hex strings. When 20 plaintext é are encoded into the 5HU6T2PJ5HU6T2PJ5HU6T2PJ5HU6T2PJ base32 string of length 32, $hotp is using a 20-byte key of 20 alt-233's, and not a key containing pairs of alt-195 alt-169.

Is there a reference showing that hex-encoded strings are matching test vectors when being handled this way? Because /help mentioned these 3 specific hex lengths, it looks like the intent is not to encode text strings of arbitrary length, but rather to have the key be the 20/32/64 bytes of the sha1/sha256/sha512 digests, such as the 32 bytes from:

Code:
//bset &key 1 $regsubex($sha256(abc),/(..)/g,$base(\t,16,10) $chr(32)) | echo -a $bvar(&key,1-)


Instead it sounds like this encoding is returning more than a dozen extra bytes from:

Code:
//bunset &key | var %key $regsubex($sha256(abc),/(..)/g,$base(\t,16,10) $chr(32)) | var %i 0 | while (%i < $numtok(%key,32)) { inc %i | var %a $gettok(%key,%i,32) | if (%a != 0) bset -t &key -1 $chr(%a) } | echo -a $bvar(&key,1-)


It also appears the key is stripping 0x00's out of the hex string then padding the string to an unknown length. $sha1(deadbeef) contains a byte position containing 00. I can cut/paste that 00 to any byte position in the 40 digit hex string and the output does not change. On the other hand, base32-encoded strings containing binary 0x00 bytes inside them use the 0x00's as part of the key and do not UTF-8 encode the contents.

Joined: Dec 2002
Posts: 5,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
Quote:
The strings being base-32 encoded are not being handled the same way as these hex strings. When 20 plaintext é are encoded into the 5HU6T2PJ5HU6T2PJ5HU6T2PJ5HU6T2PJ base32 string of length 32

They are not encoded into base32. As they are plain text, they are converted directly to UTF-8 and used as a literal key.

Quote:
It also appears the key is stripping 0x00's out of the hex string

That is correct. The results are converted to a null-terminated UTF-8 string before being used.


Link Copied to Clipboard