Be careful when concatenating multiple strings, before hashing.
An error I sometimes see: People want a hash of the strings S and T. They concatenate them to get a single string S||T, then hash it to get H(S||T). This is flawed.
The problem: Concatenation leaves the boundary between the two strings ambiguous. Example: builtin
||securely
= built
||insecurely
. Put another way, the hash H(S||T) does not uniquely identify the string S and T. Therefore, the attacker may be able to change the boundary between the two strings, without changing the hash. For instance, if Alice wanted to send the two strings builtin
and securely
, the attacker could change them to the two strings built
and insecurely
without invalidating the hash.
Similar problems apply when applying a digital signature or message authentication code to a concatenation of strings.
The fix: rather than plain concatenation, use some encoding that is unambiguously decodeable. For instance, instead of computing H(S||T), you could compute H(length(S)||S||T), where length(S) is a 32-bit value denoting the length of S in bytes. Or, another possibility is to use H(H(S)||H(T)), or even H(H(S)||T).
For a real-world example of this flaw, see this flaw in Amazon Web Services or this flaw in Flickr [pdf].