A system with a "candy machine interface" is one where the user interface is so poor it guides you into the wrong action. The term was coined in the seminal book "Writing Solid Code" by Steve Maguire many years ago.
A similar meme is the pit of success, coined by Rico Mariani to describe an API which has a "gravitational pull" towards the correct approach.
Unfortunately, the new DPAPI (ProtectedData) support in .Net v2 is a candy machine interface and more importantly, a pit of failure. First let me describe what the DPAPI does. It was introduced in Windows 2000 and allows you to store "secrets" on a computer. These secrets can only be decrypted by the user that stored the secret in the first place - in other words, it uses the NT user's credentials to encrypt and decrypt data.
The API is very simple: The ProtectedData static class has two methods, Protect and Unprotect. You can find out how to use them from Keith Brown's book The .Net Developer's guide to Windows Security. What could go wrong? Well, several weeks after I used these methods I suddenly began receiving errors like:
The second of these errors occured while I was in the IDE. It turns out that .Net v2 has a "Managed Debug Assistant" (MDA) which watches Single Threaded Appartments (STAs) and if they do not respond to a Windows messagepump within 60 seconds, then it issues an alert inside of the IDE.
- Key not valid for use in specified state.
- ContextSwitchDeadlock was detected
The first of these errors is the message from the CryptographicException which occurs 60 seconds after the call to ProtectedData.Unprotect().
A bit more searching around and I discover that the DPAPI loses the ability to decrypt data when a user changes their password (which I had done several days previously). Due to not rebooting until Windows Update forced my computer to reboot overnight, I'd not seen this error occur. Which is why a perfectly working bit of code one evening failed to work when I arrived at the office the next morning.
So what have we learnt? That the DPAPI wrapper in .Net is stupid enough to spend 60 seconds trying to decrypt a secret and then causes an exception to be thrown if the user has changed their password. This is totally unexpected behaviour - a candy machine interface.
If you would like to receive an email when updates are made to this post, please register here
Subscribe to this post's comments using