Monday, August 30, 2010

Exploring Java AES encryption algorithm with Clojure

Encryption is one of those library that I use infrequently. It seems that every time I need to work with some encryption algorithm, it passes memory expiration date of my last implementation usage of some encryption algorithm. Recently, I had to implement some password encryption tool in Java and again, I had to revisit Java’s encryption library. In the past, for exploring unfamiliar libraries, I would normally write some code sprinkled with print statements, compile it and run the compiled code and adjust my code afterwards. But in the past couple years, I’ve become a big fan of REPL development environment for purposes of library exploration. In the .NET environment, I would use F# Interactive, Ruby & Python have their own REPL environment. For Java, I could have picked either Groovy or Clojure. I’ve scripted Groovy in the past and certainly liked the shorthand expressions to a lot of the Java code. However, I have heard a lot of positive blog posts about Clojure such that I wanted to try it out.

I never had the chance to program in Lisp in the past. But I have read some of Paul Graham’s articles which seems to make Lisp a programmer’s great secret weapon in becoming a better than average programmer. So I figure Clojure can get my feet wet with another variant of Lisp and help me accomplish my day job goals at the same time. The hardest part about learning Clojure was learning the API. The program structure was not hard to figure out. I used an RPN based HP 11C calculator while in college and Clojure program structure reminds me a lot of working with RPN calculators (albeit with a lot more parenthesis). Once I got the hang of the basic Clojure syntax, it became a great environment to work in. I would define a function, run the code and then interactively explore properties or call methods. After exploring in Clojure, it became fairly trivial task to translate that to the Java code.

While it was certainly fun to work in Clojure, I'm not sure I can substantiate Paul Graham's claim that knowing Lisp makes you a better than average programmer. Maybe it's more of the concept that a polyglot programmer generally makes a better programmer simply because the programmer that goes and learns multiple programming languages has a self driven desire to become a better programmer and therefore becomes a better programmer. I'll leave that discussion to the programmer philosophers out there and return to the more pragmmatic code construction.

Here’s the prototype AES encryption code in Clojure:

(import (javax.crypto KeyGenerator SecretKey Cipher))
(import (javax.crypto.spec SecretKeySpec))
(import (java.io File FileOutputStream DataInputStream FileInputStream))
(import (java.util Properties))
(import (org.apache.commons.codec.binary Base64))

(def msg "Hello encryption world!")
(defn encode-base64 [raw] (. (new Base64) encode raw))
(defn decode-base64 [coded] (. (new Base64) decode coded))

(def aes (. KeyGenerator getInstance "AES"))
(def cipher (. Cipher getInstance "AES"))
(def encrypt (. Cipher ENCRYPT_MODE))
(def decrypt (. Cipher DECRYPT_MODE))

(defn writekey [rawkey filename]     
    ( let [out (new FileOutputStream (new File filename))]
          (do (. out write rawkey)
              (. out close))))
    
(defn readkey [filename]
    (let [file (new File filename)
          rawkey (byte-array (. file length))
          in  (new DataInputStream (new FileInputStream file))]
          (do (. in readFully rawkey)
              (. in close)
              rawkey
          )))
          
(defn get-propfile [filename]   
    (let [prop (new Properties)]
        (do (. prop load (new FileInputStream filename)))
        prop))
    

(defn genkey [keygen] 
    (do (. keygen init  128)
        (. (. keygen generateKey ) getEncoded)
    )
)    
    
(defn do-encrypt [rawkey plaintext]
    (let [cipher (. Cipher getInstance "AES")]
        (do (. cipher init encrypt (new SecretKeySpec rawkey "AES"))
            (. cipher doFinal (. plaintext getBytes)))))
    
(defn do-decrypt [rawkey ciphertext]
    (let [cipher (. Cipher getInstance "AES")]
        (do (. cipher init  decrypt (new SecretKeySpec rawkey "AES"))
            (new String(. cipher doFinal ciphertext)))))
            
            
(defn get-password [key rawkey filename]
    (let [ props (get-propfile filename)
           coded (. props getProperty key)
           cipher (decode-base64 coded)]
         (do (do-decrypt rawkey cipher))))
         
(comment "Example usage"
(get-password "jms" (readkey "test.key") "data.out")
)         

Friday, May 14, 2010

F# FileInfo, DirectoryInfo and DriveInfo

Recent changes in my day job have sidetracked me from doing much development or working with F#. However, to prevent myself from getting rusty with F# development, I decided to pick up the book Visual C# 2010 Recipes by Allen Jones, Adam Freeman, Matthew MacDonald, and Rakesh Rajan and randomly work through some of the recipes in F#. I've also incorporated Alex Gorbatchev's Syntax Highligher along with Steve Gilham's F# brush in this blog so source code syntax coloring will start to look very different from before.

Here is a translation of Recipe 5.1 to F# 2.0:

(*  Recipe 5.1. Retrieve Information About a File, Directory or Drive *)
// An interesting aspect when writing this recipe was trying to write
// the display function.  A StackOverflow entry help me to understand
// the printf format string.
// http://stackoverflow.com/questions/2162081/type-of-printfn-in-f-static-vs-dynamic-string
open System
open System.IO

(* Having some fun with pipeline operators... *)
let display  (stuff : (string * string) list) =
    List.iter (fun (fmt,text) ->  Printf.TextWriterFormat unit>(fmt) |> printfn  <| text) stuff

let displayFile (file:FileInfo) =
    [("File created: %s",file.CreationTime.ToString());
     ("File last updated: %s",file.LastWriteTime.ToString());
     ("File last accessed: %s",file.LastAccessTime.ToString());
     ("File size (bytes): %s",file.Length.ToString());
     ("File attribute list: %s",file.Attributes.ToString());]
    |> display
    
let displayDirectory  (dir:DirectoryInfo) =
    [("Directory created: %s ",dir.CreationTime.ToString());
     ("Directory last updated: %s",dir.LastWriteTime.ToString());
     ("Directory last accessed: %s",dir.LastAccessTime.ToString());
     ("Directory attribute list: %s",dir.Attributes.ToString());
     ("Directory contains: %s files",dir.GetFiles().Length.ToString());]
    |> display

let displayDrive (drive:DriveInfo) =
    [("Drive type: %s", drive.DriveType.ToString());
     ("Drive format: %s", drive.DriveFormat.ToString());
     ("Drive free space: %s", drive.AvailableFreeSpace.ToString());]
    |> display
    

let args = fsi.CommandLineArgs
if args.Length = 1 then
    printfn "Please supply a filename."
    exit 1
    
let file = new FileInfo(args.[1])
if file.Exists then
    displayFile file

    
let dir = file.Directory
[("Checking directory: %s",dir.Name);
 ("In directory: %s",dir.Parent.Name);
 ("Directory exists : %s",dir.Exists.ToString());]
|> display 

if dir.Exists then
    displayDirectory dir
    
let drv = new DriveInfo(file.FullName)

[("Drive: %s",drv.Name);] |> display
if drv.IsReady then
    displayDrive drv
    
Environment.NewLine |> Console.WriteLine
"Main method completed. Press Enter" |> printfn "%s"
Console.ReadLine()