Wednesday, January 10, 2007

Using OpenSSL in Cocoa

There are a LOT of uses for encryption within applications today. But security isn't exactly easy, and rolling your own security is generally a horrible idea. (Like coming up with your own cipher scheme for example... probably not bulletproof) So if you want encryption technologies, it's a good idea to use the industry standard OpenSSL. This is extremely easy to do using the SSCrypto Framework.

If you've used this framework in the past, you should take another look at it. I recently helped to update it, and we've added a LOT of documentation to make it extremely easy for even the security beginner to use!

Let's dive right in with some examples of how (and why) we'd use this helpful framework.

First let's pretend we're a shareware developer. We want to come up with some sort of licensing scheme. A highly recommended article on doing this is Using OpenSSL for license keys. But instead of using code like this:

// Congrats if you know what this means
PEM_read_bio_RSA_PUBKEY(bio, &rsa_key, NULL, NULL)

We'll use our SSCrypto framework instead. So let's say we want to verify a signed license key.

Signing is the act of encrypting a message using our private key. It can therefore only be verified (or decrypted) using the public key. This is exactly what you would do if you were using OpenSSL for license keys. You'd sign the license using your private key on your server, and the public key would be distributed within the application, and could be used to verify the downloaded license.

NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public" ofType:@"pem"];
NSData *publicKeyData = [NSData dataWithContentsOfFile:publicKeyPath];

SSCrypto *crypto = [[SSCrypto alloc] initWithPublicKey:publicKeyData];
[crypto setClearTextWithString:signedKey];
[crypto verify];

NSString *verifiedKey = [crypto clearTextAsString];

And that's all there is to it! Fairly straightforward isn't it? Let's do some more stuff.

Say you're downloading files, and you want to verify it's the right file, or that it hasn't been corrupted during the download. A common way of doing something like this is with digests, and one of the most popular digests is SHA1.

NSData *fileData = [NSData dataWithContentsOfFile:filePath];
NSData *digestData = [SSCrypto getSHA1ForData:fileData];
NSString *digest = [digestData hexval];

That hexval method is included in the SSCrypto framework. (It's got a category for common, very helpful NSData operations)

How about if we wanted to create a digest of a password using MD5?

SSCrypto *crypto = [[SSCrypto alloc] init];
[crypto setClearTextWithString:password];

NSString *digest = [[crypto digest:@"MD5"] hexval];

This should give you a good idea of how amazingly easy it is to use this framework. Like I said before, it's heavily documented. It comes with clear instructions, including graphics, on how to add the framework into your xcode project. And it comes with heavily commented sample code on how to do some of the following:

Create digests using md2, md4, md5, sha1, ripemd160, etc...
Symmetric encryption and decryption using aes256, blowfish, rc5, des, etc...
Asymmetric encryption including encrypting, decrypting, signing and verifying.

It also includes a category for NSData that allows you to encode and decode base64 data, as well as hex dumps.

To download the framework to your desktop, just type the following in your terminal:

cd ~/Desktop
svn co ./SSCrypto

(SVN stands for subversion, which is a source code versioning system)
(co means you're Checking Out the code, or downloading it)


Anonymous said...

For your example of verifying a signed file, shouldn't you be setting the cipher text rather than the clear text?

Robbie Hanson said...

I suppose that may make sense too. But most times, I suppose, people want to create digests from clear text. That is, they want a digest of a password, or of a file (which isn't encrypted). Plus the documentation says that the digest method works on the clearText.