normalize keys into lower-cased strings

This also changes the hash to use plain string keys instead of calling `toList` everywhere, which I imagine would be more memory-efficient.