I've been pondering using custom built assemblies for the purpose of application licensing. The key file approach is inherently flawed. Effectively, it's a bunch of flags saying "Feature X is enabled, Feature Y is not". Even if we encrypt it, the application will have all the functionality built in - along with the method to decrypt the file. Any determined hacker is unlikely to find it terribly hard to break this protection (though it may be enough to keep the honest people honest, which is really what we want).
Let's assume this approach of encrypted "Yay/Nay" feature flags is not enough. What would be better is to actually not ship the restricted functionality at all. Using dynamic assembly loading, we can easily put just one or two core functions from each restricted feature into another assembly and pull them in when needed. These extra "enablement" assemblies become the keyfiles. For maximum security, you can sign them with your private key, and not load them unless they're well signed.
Moreover, for each customer, your build and licensing process could include some hard to find customer specific data, that effectively ties each enablement assembly to that customer. If they choose to distribute them, you can track them back easily.
The advantage of this approach over simple Yay/Nay key files is that the application itself does not include the functionality of the restricted modes. It cannot be hacked without at least a strong idea of what these extra assemblies do - if the hacker removes their loading (as they would remove the keyfile), the code just can't function.
Disadvantages of this approach include patch release, which is somewhat mitigated by having the code in the keyfile assemblies be simple and compact (yet critical). Custom construction of an assembly for each customer may be tricky, depending on your distribution scenario.