Public Key Cryptography with Xojo
By Thom McGrath on
Xojo 2013 Release 4 introduces some new RSA Cryptography features I've been waiting for since summer. I did a small project for Xojo, and they agreed to implement these features in exchange. I'll admit my wife would have preferred I take a more traditional payment, but these are features I needed and felt the community should have as well.
There are 5 new functions related to a concept known as Public Key Cryptography. This is something you use nearly every day as it powers SSL/HTTPS. I also use it with certain contacts to have truly encrypted e-mail.
Under Public Key Cryptography, there are two keys as part of a matched pair: the public key and the private key. As their name suggests, the public key can be shared freely, but the private key must be kept very, very safe. Generally speaking, a private key should never be transmitted over a network. Using these keys, you can encrypt with one key and only decrypt with the other. In nearly all cases, you would encrypt with the public key only. Since the public key can be shared freely, encrypting with the private key is pretty much pointless.
So let's say you need to send me some data that you know only I can read. The first step is for me to send you my public key. You use my public key to encrypt your message, and send me the encrypted version. Using my private key, I can decrypt your message. If I have lost my private key, I cannot decrypt it. And if my private key is stolen, the thief can decrypt. But as long as the private key is safe, this process will work.
With SSL, both parties exchange public keys as part of the initial handshake. The server has a fixed public key, the client (your browser) generates a new key for each connection. Anything you need to send to the server is encrypted with the server's public key, and all responses and encrypted using your public key. This ensures nobody can listen in without both private keys, yet still works over proxies.
Generating a key
You create a key pair using the Crypto.RSAGenerateKeyPair function. You currently must use a key generated within Xojo, as the data structure is private and there are no functions to import or export keys. I've already filed a feature request to introduce conversion functions, and I expect to see them in 2014r1. After creating a key, you should also verify the keys. I've never found a situation where you don't get back valid keys, but it is a slim possibility, so code defensively.
Dim PublicKey, PrivateKey As String If Crypto.RSAGenerateKeyPair(2048,PrivateKey,PublicKey) Then If Crypto.RSAVerifyKey(PrivateKey) Then MsgBox("Private key verified") Else MsgBox("Private key did not verify") End If If Crypto.RSAVerifyKey(PublicKey) Then MsgBox("Public key verified") Else MsgBox("Public key did not verify") End If End If
The strings returned are hex encoded already, so there is no additional processing you need to do to them should you want to save them to disk, for example.
Once you have your keys, now you can start having some fun. In this example code, we're going to define a variable Message to contain our body of text. We're going to encrypt it and then decrypt it as a means to test the functions.
Dim Message As String = "Hello World" Dim Encrypted As String = Crypto.RSAEncrypt(Message,PublicKey) Dim Decrypted As String = Crypto.RSADecrypt(Encrypted,PrivateKey) If Decrypted = Message Then MsgBox("Encryption test passed") Else MsgBox("Encryption test failed") End If
It is important to note that RSAEncrypt and RSADecrypt actually work with _MemoryBlock_s, not strings. This is because they accept and return pure binary. But since MemoryBlock has implied converters, this code will function. If you want to transfer the encrypted string over the network, you'll probably want to hex encode or Base64 encode it first.
Along with encryption comes signatures. Using a digital signature, you can verify with certainty that a particular user created a series of bytes. This is commonly used with license keys these days. The license server produces a license key, then uses the private key to create a signature of the license key. The software to be unlocked then uses the license key, signature, and public key to verify the signature was created by the matching private key.
The following code will produce a signature on our original message, then verify the signature was produced by our private key.
Dim Signature As String = Crypto.RSASign(Message,PrivateKey) If Crypto.RSAVerifySignature(Message,Signature,PublicKey) Then MsgBox("Signature test passed") Else MsgBox("Signature test failed") End If
Just like RSAEncrypt and RSADecrypt, RSASign and RSAVerifySignature work with _MemoryBlock_s. If you need to transfer the signature over the network - and you probably will - you'll likely want to either hex encode or Base64 encode it first.
And there you have it. Public Key Cryptography is a fantastic way to handle encryption, since both parties don't need a pre-shared secret.