Is there a standard for hashing a list of strings? I'm working in Python, and my goal is to hash a list of strings with a cryptographic hash function such as sha256. It would need the property that a change in any string, or the order of the strings, will affect the outcome. For example, this would not be sufficient.  

sha256(''.join(['string1', 'string2'])).digest()


because ['string1', 'string2'], ['string1str', 'ing2'], as well as ['string1string2'] will all result in the same hash.  

One idea I've had for this is to hash repr(strings), but I'm concerned this may be inefficient, as unprintable characters are converted to the 4-byte form \xAB.  

strings = ['string1', 'string2', '\x00', '\\x00']
tohash = repr(strings) # tohash == "['string1', 'string2', '\\x00', '\\\\x00']"
result = sha256(tohash).hexdigest() # 2da24fba01c065fe1f33cb937dec2c865de20ebdbd8f172d59d82cd920d3266d


This method works, but I haven't seen it used anywhere else, and it seems inefficient. Is there a standard way to hash multiple strings?
There are two ways of going about this:


create a hash tree (or, as it is only one deep, a hash list);
create a canonical representation of the strings;


For the first option you simply hash each string, and then hash all the resulting hashes. As the hashes should not have collisions, you can be certain that the resulting hash doesn't collide either.

In the other option you create a canonical hash. You've got three options:


use escape characters or bytes;
define the structure and size of the elements outside the strings;
a combined approach of the above.


The first approach I won't explain much. It consists of appointing an escape character and use that for structural information. So e.g. a single 00 byte is used to indicate the end of a string and all the existing 00 in the string are doubled. Disadvantage  of this approach is that your string may grow significantly.

As for the second approach: take a look at how ASN.1 would create structures using DER. You would use a "tag" to indicate a set, then the length of the set. Then you would put one or two strings in the set. Each string again has a tag and a length. This structure is completely canonical without requiring any escape characters (as DER is a binary encoding). This will only add a limited amount of overhead.

The combined approach is e.g. applied by Python: you can perfectly distinguish between ['string1', 'string2'], ['string1str', 'ing2'], as well as ['string1string2']. The language is already showing you how to encode lists of string!