rc4c.tcl

Go to the documentation of this file.
00001 /*  rc4c.tcl - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>*/
00002 /* */
00003 /*  This provides a critcl C implementation of RC4 */
00004 /* */
00005 /*  INSTALLATION*/
00006 /*  ------------*/
00007 /*  This package uses critcl (http://wiki.tcl.tk/critcl). To build do:*/
00008 /*   critcl -libdir <your-tcl-lib-dir> -pkg rc4c rc4c*/
00009 /* */
00010 /*  To build this for tcllib use sak.tcl:*/
00011 /*   tclsh sak.tcl critcl*/
00012 /*  generates a tcllibc module.*/
00013 /* */
00014 /*  $Id: rc4c.tcl,v 1.2 2005/10/05 00:18:39 patthoyts Exp $*/
00015 
00016 package require critcl
00017 package provide rc4c 1.0.0
00018 
00019 namespace ::rc4 {
00020 
00021     critcl::ccode {
00022         typedef struct RC4_CTX {
00023             unsigned char x;
00024             unsigned char y;
00025             unsigned char s[256];
00026         } RC4_CTX;
00027 
00028         /* /* define TRACE trace */*/
00029         /* define TRACE 1 ? ((void)0) : trace*/
00030 
00031         static void trace(const char *format, ...)
00032         {
00033             va_list args;
00034             va_start(args, format);
00035             vfprintf(stderr, format, args);
00036             va_end(args);
00037         }
00038         static Tcl_ObjType rc4_type;
00039     
00040         static void rc4_free_rep(Tcl_Obj *obj)
00041         {
00042             RC4_CTX *ctx = (RC4_CTX *)obj->internalRep.otherValuePtr;
00043             TRACE("rc4_free_rep(%08x)\n", (long)obj);
00044             Tcl_Free((char *)ctx);
00045         }
00046 
00047         static void rc4_dup_rep(Tcl_Obj *obj, Tcl_Obj *dup)
00048         {
00049             RC4_CTX *ctx = (RC4_CTX *)obj->internalRep.otherValuePtr;
00050             TRACE("rc4_dup_rep(%08x,%08x)\n", (long)obj, (long)dup);
00051             dup->internalRep.otherValuePtr = (RC4_CTX *)Tcl_Alloc(sizeof(RC4_CTX));
00052             memcpy(dup->internalRep.otherValuePtr, ctx, sizeof(RC4_CTX));
00053             dup->typePtr = &rc4_type;
00054         }
00055 
00056         static void rc4_string_rep(Tcl_Obj* obj)
00057         {
00058             RC4_CTX *ctx = (RC4_CTX *)obj->internalRep.otherValuePtr;
00059             Tcl_Obj* tmpObj;
00060             char* str;
00061             TRACE("rc4_string_rep(%08x)\n", (long)obj);
00062             /* convert via a byte array to properly handle null bytes */
00063             tmpObj = Tcl_NewByteArrayObj((char *)ctx, sizeof(RC4_CTX));
00064             Tcl_IncrRefCount(tmpObj);
00065             
00066             str = Tcl_GetStringFromObj(tmpObj, &obj->length);
00067             obj->bytes = Tcl_Alloc(obj->length + 1);
00068             memcpy(obj->bytes, str, obj->length + 1);
00069             
00070             Tcl_DecrRefCount(tmpObj);
00071         }
00072 
00073         static int rc4_from_any(Tcl_Interp* interp, Tcl_Obj* obj)
00074         {
00075             TRACE("rc4_from_any %08x\n", (long)obj);
00076             return TCL_ERROR;
00077         }
00078 
00079         static Tcl_ObjType rc4_type = {
00080             "rc4c", rc4_free_rep, rc4_dup_rep, rc4_string_rep, rc4_from_any
00081         };
00082 /* ifdef __GNUC__*/
00083         inline
00084 /* endif*/
00085         void swap (unsigned char *lhs, unsigned char *rhs) {
00086             unsigned char t = *lhs;
00087             *lhs = *rhs;
00088             *rhs = t;
00089         }
00090     }
00091 
00092     critcl::ccommand rc4c_init {dummy interp objc objv} {
00093         RC4_CTX *ctx;
00094         Tcl_Obj *obj;
00095         const unsigned char *k;
00096         int n = 0, i = 0, j = 0, keylen;
00097 
00098         if (objc != 2) {
00099             Tcl_WrongNumArgs(interp, 1, objv, "keystring");
00100             return TCL_ERROR;
00101         }
00102         
00103         k = Tcl_GetByteArrayFromObj(objv[1], &keylen);
00104 
00105         obj = Tcl_NewObj();
00106         ctx = (RC4_CTX *)Tcl_Alloc(sizeof(RC4_CTX));
00107         ctx->x = 0;
00108         ctx->y = 0;
00109         for (n = 0; n < 256; n++)
00110             ctx->s[n] = n;
00111         for (n = 0; n < 256; n++) {
00112             j = (k[i] + ctx->s[n] + j) % 256;
00113             swap(&ctx->s[n], &ctx->s[j]);
00114             i = (i + 1) % keylen;
00115         }
00116         
00117         if (obj->typePtr != NULL && obj->typePtr->freeIntRepProc != NULL)
00118             obj->typePtr->freeIntRepProc(obj);
00119         obj->internalRep.otherValuePtr = ctx;
00120         obj->typePtr = &rc4_type;
00121         Tcl_SetObjResult(interp, obj);
00122         Tcl_IncrRefCount(obj);
00123         Tcl_InvalidateStringRep(obj);
00124         return TCL_OK;
00125     }
00126 
00127     critcl::ccommand rc4c {dummy interp objc objv} {
00128         Tcl_Obj *resObj = NULL;
00129         RC4_CTX *ctx = NULL;
00130         unsigned char *data, *res, x, y;
00131         int size, n, i;
00132 
00133         if (objc != 3) {
00134             Tcl_WrongNumArgs(interp, 1, objv, "key data");
00135             return TCL_ERROR;
00136         }
00137 
00138         if (objv[1]->typePtr != &rc4_type
00139             && rc4_from_any(interp, objv[1]) != TCL_OK) {
00140             return TCL_ERROR;
00141         }
00142 
00143         ctx = objv[1]->internalRep.otherValuePtr;
00144         data = Tcl_GetByteArrayFromObj(objv[2], &size);
00145         res = (unsigned char *)Tcl_Alloc(size);
00146 
00147         x = ctx->x;
00148         y = ctx->y;
00149         for (n = 0; n < size; n++) {
00150             x = (x + 1) % 256;
00151             y = (ctx->s[x] + y) % 256;
00152             swap(&ctx->s[x], &ctx->s[y]);
00153             i = (ctx->s[x] + ctx->s[y]) % 256;
00154             res[n] = data[n] ^ ctx->s[i];
00155         }
00156         ctx->x = x;
00157         ctx->y = y;
00158 
00159         resObj = Tcl_NewByteArrayObj(res, size);
00160         Tcl_SetObjResult(interp, resObj);
00161         Tcl_Free(res);
00162         return TCL_OK;
00163     }
00164 }
00165 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1