There’s a nice survey of programming with "Crypto API: Next Generation," aka CNG, in the July 2007 issue of MSDN Magazine – http://msdn.microsoft.com/msdnmag/issues/07/07/Security/default.aspx. Kenny Kerr wrote the piece.
My favorite quote is near the end of the article, when he’s discussing interoperability between Microsoft’s native and managed crypto APIs. He observes, "working with CNG is quite a bit simpler than working with the managed cryptography classes as there are fewer abstractions and inherited defaults to think about. Effective cryptography relies on programmers being explicit about every single detail."
That’s an interesting statement on a couple of levels. It initially resonated with me, since working on the legacy (native) Crypto API was one of my first responsibilities at Microsoft, right out of college. So CAPI made a big impression on me in my formative years 🙂 From that background, when the managed (System.Security.Cryptography) interfaces were released, they seemed a little bit unnatural. Case in point – the "RSAOAEPKeyExchangeFormatter" class. I had always assumed that the intent of the CLR is to provide a careful balance between power and usability, in contrast to Win32, which is all about full power. But if you’re going to be using something called RSAOAEPKeyExchangeFormatter, then you had better really understand crypto. In other words, where’s the usability (I’ll come back to that)?
On the other hand, if you have to really understand crypto to safely use managed CAPI, why, as Kenny Kerr asks, do the higher level classes offer so many defaults? "Default behavior" is bad news in many aspects of system-level programming, but it’s especially dangerous in crypto. For example, what happens when the chosen default behavior is no longer secure? You either fix it and break apps, or leave it and perpetuate an insecure system. Better to force application programmers to make explicit choices (about crypto algorithm, key size, cipher chaining mode, etc) from the outset about handling versioning and configuration.
Herein lies the betrayal of crypto APIs in general: there is no way for the layman to use them safely (regardless of default vs explicit behavior). Applications should be built on top of existing, proven security protocols. This generally implies that application programmers won’t be calling the low level crypto interfaces directly. And this brings me to my second point regarding this month’s CNG article – any overview-level guide for a cryptographic interface should include such a disclaimer.
Examples of existing, proven security protocols follow. All provide integrity as well as confidentiality (encryption) features.
* Authentication: Kerberos (http://en.wikipedia.org/wiki/Kerberos_%28protocol%29)
* File: EFS (http://en.wikipedia.org/wiki/Encrypting_File_System)
* Network: IPsec (http://en.wikipedia.org/wiki/IPsec)
* Socket: TLS (http://en.wikipedia.org/wiki/Secure_Sockets_Layer)