domingo, 26 de agosto de 2007

Requirements

I just found this image around my messy HD.

(Click to enlarge)

It is funny because it's true.

quarta-feira, 15 de agosto de 2007

Cryptography with Caché/Ensemble

Some months ago I was looking for cryptography APIs within Caché/Ensemble, because I was going to implement some security at Web services (something simple, actually, very far from WS-Security - here are the specs, if you want).

After searching Caché´s and Ensemble´s online help, and asking the big G without success, I gave up. I finally realized that there were not any Caché API for it. Something curious, since even Oracle has one API for crytography operations.

Never mind. What mattered was finding a solution. My first idea was to use a Java Gateway. You might ask what is it? It is nothing more than a way to create a Java virtual machine inside Ensemble, and be able to interact with Java objects in it. Since Java has some good crytography API, I thought my problems were over... Unfortunately, this JVM/Caché partnership wasn´t very happy, with a lot of bugs and strange stuff (some crashes froze the machine, and I had to reboot it).

Then, I had two options. Or I would wait some years until someone decides some cryptography API would be nice and put it into Caché, or I would write something myself. I decided for the second option.

First question: which algorithm should I implement? My 'security architecture' was not very complex, so I discarded the public/private keys algorithms. Then, which symmetric algorithms I would choose? As I was not getting any raise or something, I wanted the most easy to implement (but not so easy to break, like Caesar´s).

Actually, I didn´t find any algorithm that was so easy. So I picked one that had good material/refereces available. I ended up with DES. I really don´t remember all pages where I researched, but two good references are: The DES Algorithm Illustrated and DES Encryption.

In the end, all code was distributed in 3 classes (although one of these classes is just a holder). I won´t post here the source code, since it is a lot of code, if you want to see it, you can download it here (some warning: comments are in portuguese, if you want some detail, leave a comment here in the blog).

The class DadosLoginBean is only used as holder to user/password.

The class Util has, besides specific methods for DES algorithm, several methods that can be used in other places, as methods to convert strings with ASCII to hexadecimal representation, or hexa values to bitstrings (bitstring is an special data structure, an array of bits, used in Caché).

The main class is DESCrypto. Since I´m tired of writing here, I will just say that this class ciphers/deciphers the data using DES algorithm, with block modifier CBC, and padding PKCS#5, with an initial vector of zeros.

You should not worry if you didn´t catch the letter soup above. It also took me some time until I figured out all those letters =P. Anyway, the last method of DESCrypto, decifraLogin, shows how to use all this stuff (if you just want to cipher/decipher using those classes, you really don´t need to know all the letter soup). The method decifraLogin has as first parameter one ciphered message (in hexadecimal as %String), and a key (also in hexadecimal as %String), and returns an object with user and password. Here is the code:


///
/// *******************************************************************
///
/// Static method to decipher a message with user/password.
/// It creates a DESCrypto object, sets the key, converts
/// the hexadecimal string to ASCII, and returns a bean with user
/// and password.
///
/// In case of any error, returns null (empty).
///
ClassMethod decifraLogin(msg As %String, chave As %String = "5C6F2F5F45793A50") As eey.security.bean.DadosLoginBean
{
set $ztrap = "EXCEPTION"

set des = ##class(eey.security.DESCrypto).%New()
set st = des.setKey(chave)
if ($System.Status.IsError(st)) goto EXCEPTION

set st = des.performChainCrypto(msg, .desc, "D")
if ($System.Status.IsError(st)) goto EXCEPTION

set userSenha = ##class(eey.security.Util).strHexToStringAscii(desc)

if (userSenha = "") goto EXCEPTION

set user = $piece(userSenha, "/")
set pass = $piece(userSenha, "/", 2)

set bean = ##class(eey.security.bean.DadosLoginBean).%New()
set bean.usuario = user
set bean.senha = pass

kill des

Quit bean
EXCEPTION
Quit ""
}


If you are interested, take a look at the source code, and leave a comment if you have any doubt.

P.S.: to those interested, above code is under WTFPL license. =P