rds :: graphikos

[ home | photos | gallery | scheme | notes | blog | facebook | twitter | youtube | last.fm | myspace | del.icio.us | EverythingHerePlus ]

Kawa Implementation of Asymmetric Encryption Keys Via KeyPairGenerator

Example Code and Tutorials Home

Example of standalone executable program duplicating the functionality of the January 16, 2004 'Core Java Technologies Tech Tips' article 'Asymmetric Encryption Keys With the KeyPairGenerator'. This example assumes the reader has obtained their own copy of that document and will reference it and the Java source for our purpose of reproducing the functionality. It is not reproduced here due to the lengthy and confusing amount of copyright and terms of use information Sun uses on all their documentation. The Sun source for the AsymmetricKeyMaker program is 25 lines, so we can reference things by line number.

Kawa Functionality Utilized
6.4 Compiling Scheme to a standalone application
10.4 Calling Java methods from Scheme

AsymmetricKeyMaker is an excellent example for several reasons. It is a command line program takes user input and returns a result. It utilizes the Java exception system and gives us an opportunity to deal with both abstract and concrete classes. Briefly, let's look at the Java source. Lines 1-3 import the packages used by the program. Line 5 declares the 'class' or program name. Line 7 processes the command line arguments. Line 8 is an example of archaic variable initialization. Line 9 is a conditional statement that passes the command line arguments to the core functionality. Line 11 begins the beginning of a try, catch construction that throws an error if the parameter passed is incorrect. Line 12 through 14 instantiates the key generator object with the requested key algorithm and then generates the key pair. Lines 16 and 17 print out the portions of the key pair. Lines 19 through 21 handle the exception created if the requested algorithm to KeyPairGenerator is bad. Here is our version of the program in Scheme.

; -*-scheme-*- Copyright © Robert D. Skeels 02/07/2004 <athene@earthlink.net>

(module-name <AsymmetricKeyMaker>)

(define-namespace key-pair-generator "class:java.security.KeyPairGenerator")

(define gen-keys
  (lambda (algorithm)
    (let* ((our-kpg (key-pair-generator:getInstance algorithm))
           (our-key-pair (invoke our-kpg 'generateKeyPair))
           (writeln (lambda (args) (display args) (newline))))
           (writeln (invoke our-key-pair 'getPublic))
           (writeln (invoke our-key-pair 'getPrivate)))))

(define try-gen-keys
  (lambda (algorithm)
    (try-catch (gen-keys algorithm)
        (ex <java.security.NoSuchAlgorithmException>
          (begin
          (display  "usage: java AsymmetricKeyMaker <RSA | DSA>")
          (newline))))))

(if (> (vector-length command-line-arguments) 0)
  (try-gen-keys (vector-ref command-line-arguments 0)))

Recreating this functionality in Kawa Scheme is reasonably simple. Although the module-name declaration on line 3 is unnecessary here, it make it easier to reuse the code later by adding module-export to call the routines from other code. The global variable `command-line-arguments' referred to in the Kawa Manual §6.4 is a vector. Rather than comparing its length like the Java code, we will use the first argument if it exists. When I was first evaluating the Java code I really didn't understand why they called java.security.KeyPairGenerator.getInstance without sanity checking the command line input first. Then I read further and discovered the function is case insensitive and will handle any variation of RSA or DSA. The package allows for others to be added as well. An exception are is thrown if algorithm is unrecognized, so it is fine for us to pass the argument as is.

Lines 15 to 21 define try-gen-keys, which is a simple function that deals with the exception handling and passes control on. Kawa's statement is a very elegant. We could have included the gen-keys function in the body of the try-catch statement, but it is more scheme like to call it separately. Further, we could later use module-export for gen-keys to call it from other code, with a different handler for the exception that would be appropriate in a application that isn't be called from the command line. The exception we catch is java.security.NoSuchAlgorithmException, which is NoSuchAlgorithmException in the Java source since it was already imported in their source.

Lines 7 to 13 define gen-keys. This function relies on the define-namespace declaration on line 5. It is suggested to read §10 and specifically §10.4 of the Kawa manual to understand this more clearly. Unlike the somewhat clumsy and cryptic keyPair assignments in the Java source, we handle creating the KeyPair object instance and the invoking its functionality separately. We use let* because it is important that the statements are handled sequentially, since we cannot access a KeyPairGenerator object until we have an actual instance of it. On line 9 we bind our-kpg to the result of the method call getInstance for the abstract object KeyPairGenerator with the arguments we've passed from the command line. Our alias to the call java.security.KeyPairGenerator.getInstance(algorithm) created during define-namespace. our-kpg is now bound to an instance of a KeyPairGenerator object.

Now that we have an instance or concrete KeyPairGenerator object we can use it. We bind our-key-pair to the invocation of the generateKeyPair method in our newly instantiated KeyPairGenerator object bound to our-kpg. The resulting object bound to our-key-pair is a KeyPair object. Since I already have a let binding, a quick definition of writeln on line 11 saves us from two consecutive display, newline calls. Lines 12 and 13 print the public and private portions of the RSA or DSA key pair. our-key-pair is bound to the KeyPair object, the accessor functions (methods) access the actual data contained in the object fields. Lines 10 through 13 could have been written in the define-namespace style as well, but for clarity and for pedagogical reasons we used both styles.

All that is left to do is compile the code and run the program. Please feel free to copy the above code into a AsymmetricKeyMaker.scm file, it is under an ISC/Berkeley license. Compile into a standalone application as per the Kawa Manual §6.4. Don't forget to include Kawa and the AsymmetricKeyMaker.class in your CLASSPATH. When in the directory with AsymmetricKeyMaker.class I do setenv CLASSPATH /Users/Shared/share/java/kawa.jar:`pwd`. Running the program is java AsymmetricKeyMaker RSA or java AsymmetricKeyMaker DSA.