Cryptkit

Cryptkit is a Tcl binding to the Cryptlib security toolkit.

From the Cryptlib web site - "The Cryptlib security toolkit is a powerful security toolkit that allows even inexperienced crypto programmers to easily add encryption and authentication services to their software. The high-level interface provides anyone with the ability to add strong security capabilities to an application in as little as half an hour, without needing to know any of the low-level details that make the encryption or authentication work. Because of this, cryptlib dramatically reduces the cost involved in adding security to new or existing applications." [L1 ]

Cryptkit brings these benefits to Tcl.

This first release provides an API that closely matches the Cryptlib C API (to remain consistent with the existing documentation). The next release will have a more "Tclish" API.

Downloads

  • the Cryptkit README [L2 ]
  • a Starkit containing a pre-built Cryptkit package for Linux-x86, Mac OSX, Windows-x86 and Sharp Zaurus (Linux-ARM) [L3 ]
  • the Cryptkit source [L4 ]
  • some test scripts at [L5 ] also demonstrate the use of Cryptkit from Tcl

Cryptkit was written by Steve Landers and was made possible through the financial support of Eolas Technologies Inc.

Cryptkit is distributed under a Tcl BSD style license, as documented in the license.terms file in the distribution.


MDD: Great job Steve!


Example - test cipher

 proc testCipher {cryptAlgo keySize algoName} {
    # Create context with random IV (if it needs one) and a key derived
    # from a password using a salt and iteration count to hinder guessing
    # attacks
    cryptCreateContext encContext CRYPT_UNUSED $cryptAlgo
    cryptSetAttribute $encContext CRYPT_CTXINFO_KEYSIZE $keySize
    cryptSetAttribute $encContext CRYPT_CTXINFO_KEYING_ITERATIONS 10000
    cryptSetAttributeString $encContext CRYPT_CTXINFO_KEYING_SALT "salt1234"
    cryptSetAttributeString $encContext CRYPT_CTXINFO_KEYING_VALUE "password123"

    # Encrypt 10 MB of text     
    set text [binary format a[expr {10 * 1024 * 1024}] \0]
    set startTime [clock seconds]
    cryptEncrypt $encContext $text
    set endTime [clock seconds]
    puts "$cryptAlgo 10 Mb in [expr {$endTime - $startTime}] seconds"

    cryptDestroyContext $encContext
 }   

 cryptInit
 cryptAddRandom NULL CRYPT_RANDOM_SLOWPOLL
 testCipher CRYPT_ALGO_HMAC_SHA 32 "HMAC-SHA1   Processed"
 testCipher CRYPT_ALGO_RC4      16 "RC4         Encrypted"
 testCipher CRYPT_ALGO_AES      16 "AES-128 CBC Encrypted"
 testCipher CRYPT_ALGO_AES      32 "AES-256 CBC Encrypted"
 testCipher CRYPT_ALGO_3DES     24 "3DES CBC    Encrypted"
 cryptEnd

Implementation

Cryptkit is implemented using Critcl and uses the new critcl::cdefines feature that maps C #defines and enums into a Tcl namespace.

For example, cryptkit.tcl uses the following to map Cryptlib symbols (i.e. #defines and enums) into the cryptkit namespace

    # map Cryptlib #defines and enums into the current namespace
    critcl::cdefines CRYPT_* [namespace current]

    # other defines
    critcl::cdefines {
        NULL
        TRUE
        FALSE
        TCL_OK
        TCL_ERROR
    } cryptkit

SHA-1 Example

 source cryptkit.kit
 package require cryptkit
 namespace import cryptkit::*
 cryptkit::cryptInit

 proc sha1 {data} {
    cryptCreateContext hashContext CRYPT_UNUSED CRYPT_ALGO_SHA
    cryptEncrypt $hashContext $data
    # Finalize: if you want to stream, wait until the last block to do this.
    cryptEncrypt $hashContext ""
    cryptGetAttributeString $hashContext CRYPT_CTXINFO_HASHVALUE hash 20
    cryptDestroyContext $hashContext
    binary scan $hash H* hexhash
    return $hexhash
 }

RLH - Is there a way to put the 'source cryptkit.kit' in a pkgIndex file? I like to keep all my stuff in the lib directory (I am on Windows).

02feb05 - The way to do that is to unwrap the starkit, and copy all its lib/* directories to yours. The above "source" is a way to avoid the need for unwrapping when things live in a starkit - it does nothing but mount and add (all packages in) the starkit's lib area to auto_path -jcw

LV There was/is a TIP that aku I think proposed that described tcl modules, right? In that TIP, I was thinking that there was something about being able to distribute Tcl extensions in other forms, such as a starkit.

I know I think that being able to drop a starkit somewhere in $exec_prefix/lib and having a package require find and load it - without having to unwrap the starkit - would make distribution for me a lot easier.

jcw - Do:

    foreach x [glob -nocomplain /path/to/my/starkit/collection/*] { source $x }

After that, all packages inside them can be used via package require.

RLH - That is cool...

Lars H: How about this for putting the source command in a pkgIndex file?

  package ifneeded cryptkit.kit 0.0 [format {
      source [file join %s cryptkit.kit]
      package require cryptkit
  } [list $dir]]

Whether it will do any good in this particular case I cannot say, but perhaps it can serve as inspiration.

RLH - I tried the above on Windows XP and it does not work. But it would be cool if it did.

stevel - one technique mentioned to me by Steve Redler IV is to put the Starkit somewhere on your PATH, and use auto_execok thus

   source [auto_execok cryptkit.kit]
   package require cryptkit

PT: The following pkgIndex.tcl will work with cryptkit.kit if it is installed in the same directory.

 package ifneeded cryptkit 1.0 \
     "source [file join $dir cryptkit.kit];\
      source [file join $dir cryptkit.kit lib cryptkit critcl.tcl];\
      critcl::loadlib [file join $dir cryptkit.kit lib cryptkit] cryptkit 1.0;\
      eval \[package ifneeded cryptkit 1.0\]"

I have problems with importing certs witch cryptkit and accessing attributes. I loop on att and I dont't know how to see if an attribute will be in binary form (conversion needeed with binary scan) or in string form. ::cryptkit::cryptGetAttributeString $cert $att attributeNeeded ::cryptkit::NULL Any idea ?


RLH - Does cryptlib/Cryptkit support SHA-256/512?

PT 23-Feb-2005: Not at this time. See the FAQ at [L6 ]

stevel 23-Feb-2005: See also this post where the Cryptlib author puts concerns re SHA-1 into perspective [L7 ]

RLH - I happen to think it is not a real big deal myself but thought I would ask about the others.


Hermann Boeken 13-Aug-2009:

Is cryptkit from http://www.digitalsmarties.com/cryptkit/cryptkit.tar.gz compatible with cryptlib 3.3.3 from http://www.cs.auckland.ac.nz/~pgut001/cryptlib/ ? After building the static cryptlib library, copying the cryptlib.h and libcl.a (renaming it to libcl-linux-ix86.a) to the cryptkit directory and building the cryptkit with critcl2 I get an error when trying to load the package into my tclsh 8.5.4:

% package req cryptkit
couldn't load file "/home/hermann/Tcl/cryptkit/lib/cryptkit/linux-ix86/cryptkit.so": /home/hermann/Tcl/cryptkit/lib/cryptkit/linux-ix86/cryptkit.so: undefined symbol: __res_query

Sorry for posting this here, but I couldn't find a better place.

stevel 13-Aug-2009 - That cryptkit version was built against Cryptlib 3.2, and I haven't yet tried building against the latest cryptlib. Re the res_query, depending on the Linux version you might need to add -lresolv to the link arguments.

Hermann Boeken 14-Aug-2009: I found where I had to add -lresolv (in cryptkit.tcl). Now when creating a session I get an error '::cryptkit::cryptCreateSession session CRYPT_UNUSED CRYPT_SESSION_SSH' : expected integer but got "("

Is the previous version of cryptlib (3.2) still available for download?


Acknowledgements


Pierre Coueffin July 20, 2007: All the Digital Smarties links for cryptkit appear to be down. The Starkit is still available, but there is no source tarball anymore. Any idea what happened?

stevel Yes, I changed servers and forgot to copy it. Fixed now.