No.
EDIT: I've been told to elaborate.
This is just direct fallout from the way Merkle-Damgard hash functions work. MD hash functions look like this:
function MD(C, h, M):
M <- pad(M)
for m in blocks(M):
h <- C(h, m)
return h
The core of an MD hash is the compression function C, which takes an input state h and a message block m and produces a new state. When you find a collision in an MD hash function, you're really finding a collision in C. That is, some state h and some pair of message blocks m1 and m2 such that C(h, m1) = C(h, m2).Now, HMAC. HMAC is defined over a hash function, and it looks like this:
function HMAC(H, k, M):
k1 <- ipad ^ k
k2 <- opad ^ k
return H(k2 || H(k1 || M))
Where "||" is the concatenation operator. A simplified view of HMAC is that the key is used to scramble the initial state of H. This prevents the attacker from finding collisions on the inner hash function, because they don't know any interior state h. (The outer hash prevents length-extension attacks.)Which makes this article pretty silly: the whole point of HMAC is that the attacker doesn't get to know interior hash states. It pretty much goes without saying that if a) an attacker can find collisions on H for arbitrary states h and b) they know some interior state h of the HMAC, then it follows directly that they can find collisions on the HMAC.
Hey, want to see some more practical "attacks" on HMAC? Here we go!
In [11]: HMAC(b'\x00', b'chili dog', sha256).hexdigest()
Out[11]: '3128a12ed7dd6cd4ad9d2720126698d1c0c3e2d991ddbf73ebbecd947581acd9'
In [12]: HMAC(b'\x00\x00', b'chili dog', sha256).hexdigest()
Out[12]: '3128a12ed7dd6cd4ad9d2720126698d1c0c3e2d991ddbf73ebbecd947581acd9'
Whoaaa, what?! Again! In [17]: HMAC(sha256(b'A'*500).digest(), b'chili dog', sha256).hexdigest()
Out[17]: '426b6ec9b0e6b5fae9d12924432c023e8bc3444aa3adc4c48fdc875357c54c2f'
In [18]: HMAC(b'A'*500, b'chili dog', sha256).hexdigest()
Out[18]: '426b6ec9b0e6b5fae9d12924432c023e8bc3444aa3adc4c48fdc875357c54c2f'
Oh nooo! HMAC!