diff --git a/.gitattributes b/.gitattributes
index 956820a4e65db3d35d4c7135d7e0867d858532e1..3f1caa5125a3a4caf605194b2b6cbf5dc389f274 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -128,6 +128,7 @@ testfont binary
 /src/modules/Yp/acconfig.h foreign_ident
 /src/modules/Yp/module.pmod.in foreign_ident
 /src/modules/_Crypto/StdCrypt.pike foreign_ident
+/src/modules/_Crypto/cast.c foreign_ident
 /src/modules/_Crypto/cbc.c foreign_ident
 /src/modules/_Crypto/crypto.c foreign_ident
 /src/modules/_Crypto/crypto.h foreign_ident
diff --git a/src/modules/_Crypto/CREDITS b/src/modules/_Crypto/CREDITS
index a4bf66985bc0dbdac934af55193c0cf83b030b6b..bb2da3fd0783fbabc14cbf975500482ef3210bbd 100644
--- a/src/modules/_Crypto/CREDITS
+++ b/src/modules/_Crypto/CREDITS
@@ -9,10 +9,11 @@ idea.c     Original implementation by Xuejia Lai, heavily optimized by
            Colin Plumb. In the Public Domain (although the algorithm
            itself is patented)
 
-sha.c      Written by Peter Gutmann, somewhat hacket by Andrew
+sha.c      Written by Peter Gutmann, somewhat hacked by Andrew
            Kuchling. Public Domain.
 
-descore    Written by Dana L. How. GPL.
-
+md5.c      Written by Colin Plumb. Also hacked by Andrew Kuchling.
 
+descore    Written by Dana L. How. GPL.
 
+cast.c     Written by Steve Reid <sreid@sea-to-sky.net>. Public Domain.
diff --git a/src/modules/_Crypto/Makefile.in b/src/modules/_Crypto/Makefile.in
index 84962a9a8892cd1fb5d26dfe68a5d1e34edf33a4..895557065a691e938d0dbb298a3b5f3b536b0ac5 100644
--- a/src/modules/_Crypto/Makefile.in
+++ b/src/modules/_Crypto/Makefile.in
@@ -1,6 +1,6 @@
 SRCDIR=@srcdir@
 VPATH=@srcdir@:@srcdir@/../..:../..
-OBJS=crypto.o idea.o des.o rc4.o invert.o sha.o md5.o pipe.o cbc.o
+OBJS=crypto.o idea.o des.o cast.o rc4.o invert.o sha.o md5.o pipe.o cbc.o
 MODULE_ARCHIVES=lib/algorithms.a
 MODULE_SUBDIRS=lib
 MODULE_LDFLAGS=@LDFLAGS@
diff --git a/src/modules/_Crypto/cast.c b/src/modules/_Crypto/cast.c
new file mode 100644
index 0000000000000000000000000000000000000000..5bf02f21ca3f68b32739833e19c3c68fb9a27b4e
--- /dev/null
+++ b/src/modules/_Crypto/cast.c
@@ -0,0 +1,200 @@
+/*
+ * $Id: cast.c,v 1.1 1997/11/04 01:28:47 nisse Exp $
+ *
+ * CAST crypto module for Pike
+ *
+ * Niels Möller 1997-11-03
+ *
+ */
+
+/*
+ * Includes
+ */
+
+/* From the Pike distribution */
+#include "global.h"
+#include "stralloc.h"
+#include "interpret.h"
+#include "svalue.h"
+#include "object.h"
+#include "error.h"
+#include "las.h"
+
+#include <cast.h>
+
+/* Module specific includes */
+#include "precompiled_crypto.h"
+
+struct pike_crypto_cast {
+  struct cast_key key;
+  void (*crypt_fun)(struct cast_key* key, unsigned INT8* inblock,
+		    unsigned INT8* outblock);
+};
+
+#define THIS ((struct pike_crypto_cast *)(fp->current_storage))
+#define OBTOCTX(o) ((struct pike_crypto_cast *)(o->storage))
+
+/*
+ * Globals
+ */
+
+struct program *pike_crypto_cast_program;
+
+/*
+ * Functions
+ */
+
+void init_pike_crypto_cast(struct object *o)
+{
+  MEMSET(THIS, 0, sizeof(struct pike_crypto_cast));
+}
+
+void exit_pike_crypto_cast(struct object *o)
+{
+  MEMSET(THIS, 0, sizeof(struct pike_crypto_cast));
+}
+
+/*
+ * methods
+ */
+
+/* string name(void) */
+static void f_name(INT32 args)
+{
+  if (args) {
+    error("Too many arguments to cast->name()\n");
+  }
+  push_string(make_shared_string("CAST"));
+}
+
+/* int query_block_size(void) */
+static void f_query_block_size(INT32 args)
+{
+  if (args) {
+    error("Too many arguments to cast->query_block_size()\n");
+  }
+  push_int(CAST_BLOCKSIZE);
+}
+
+/* int query_key_length(void) */
+static void f_query_key_length(INT32 args)
+{
+  if (args) {
+    error("Too many arguments to cast->query_key_length()\n");
+  }
+  push_int(CAST_MAX_KEYSIZE);
+}
+
+static void set_key(INT32 args)
+{
+  if (args != 1) {
+    error("Wrong number of arguments to des->set_key()\n");
+  }
+  if (sp[-1].type != T_STRING) {
+    error("Bad argument 1 to des->set_key()\n");
+  }
+  if ( (sp[-1].u.string->len < CAST_MIN_KEYSIZE)
+       || (sp[-1].u.string->len > CAST_MAX_KEYSIZE))
+    error("Invalid key length to cast->set_key()\n");
+
+  cast_setkey(&(THIS->key), sp[-1].u.string->str, sp[-1].u.string->len);
+  
+  pop_n_elems(args);
+  push_object(this_object());
+}
+
+/* void set_encrypt_key */
+static void f_set_encrypt_key(INT32 args)
+{
+  set_key(args);
+  THIS->crypt_fun = cast_encrypt;
+}
+
+/* void set_decrypt_key */
+static void f_set_decrypt_key(INT32 args)
+{
+  set_key(args);
+  THIS->crypt_fun = cast_decrypt;
+}
+
+/* string crypt_block(string) */
+static void f_crypt_block(INT32 args)
+{
+  int len;
+  struct pike_string *s;
+  INT32 i;
+  
+  if (args != 1) {
+    error("Wrong number of arguments to cast->crypt_block()\n");
+  }
+  if (sp[-1].type != T_STRING) {
+    error("Bad argument 1 to cast->crypt()\n");
+  }
+
+  len = sp[-1].u.string->len;
+  if (len % CAST_BLOCKSIZE) {
+    error("Bad length of argument 1 to cast->crypt()\n");
+  }
+
+  if (!THIS->key.rounds)
+    error("Crypto.cast->crypt_block: Key not set\n");
+  s = begin_shared_string(len);
+  for(i = 0; i < len; i += CAST_BLOCKSIZE)
+    THIS->crypt_fun(&(THIS->key), 
+		    (unsigned INT8 *) sp[-1].u.string->str + i,
+		    (unsigned INT8 *) s->str + i);
+  
+  pop_n_elems(args);
+
+  push_string(end_shared_string(s));
+}
+
+/*
+ * Module linkage
+ */
+
+#if 0
+void MOD_INIT2(cast)(void)
+{
+  /* add_efun()s */
+}
+#endif
+
+void MOD_INIT(cast)(void)
+{
+  /*
+   * start_new_program();
+   *
+   * add_storage();
+   *
+   * add_function();
+   * add_function();
+   * ...
+   *
+   * set_init_callback();
+   * set_exit_callback();
+   *
+   * program = end_c_program();
+   * program->refs++;
+   *
+   */
+
+  start_new_program();
+  add_storage(sizeof(struct pike_crypto_cast));
+
+  add_function("name", f_name, "function(void:string)", 0);
+  add_function("query_block_size", f_query_block_size, "function(void:int)", 0);
+  add_function("query_key_length", f_query_key_length, "function(void:int)", 0);
+  add_function("set_encrypt_key", f_set_encrypt_key, "function(string:object)", 0);
+  add_function("set_decrypt_key", f_set_decrypt_key, "function(string:object)", 0);
+  add_function("crypt_block", f_crypt_block, "function(string:string)", 0);
+
+  set_init_callback(init_pike_crypto_cast);
+  set_exit_callback(exit_pike_crypto_cast);
+
+  end_class(MODULE_PREFIX "cast", 0);
+}
+
+void MOD_EXIT(cast)(void)
+{
+}
diff --git a/src/modules/_Crypto/crypto.c b/src/modules/_Crypto/crypto.c
index 7960d73b3d0b4fdfd25765b7c58b6176e3a0a33a..0ee1f726c5de51e4a4414f52ce681d72b0cda713 100644
--- a/src/modules/_Crypto/crypto.c
+++ b/src/modules/_Crypto/crypto.c
@@ -1,5 +1,5 @@
 /*
- * $Id: crypto.c,v 1.20 1997/04/10 02:33:27 nisse Exp $
+ * $Id: crypto.c,v 1.21 1997/11/04 01:28:48 nisse Exp $
  *
  * A pike module for getting access to some common cryptos.
  *
@@ -521,6 +521,7 @@ void pike_module_init(void)
   MOD_INIT(crypto)();
   MOD_INIT(idea)();
   MOD_INIT(des)();
+  MOD_INIT(cast)();
   MOD_INIT(rc4)();
   MOD_INIT(invert)();
 
@@ -540,6 +541,7 @@ void pike_module_exit(void)
   MOD_EXIT(md5)();
   MOD_EXIT(crypto)();
   MOD_EXIT(idea)();
+  MOD_EXIT(cast)();  
   MOD_EXIT(des)();
   MOD_EXIT(rc4)();
   MOD_EXIT(invert)();
diff --git a/src/modules/_Crypto/precompiled_crypto.h b/src/modules/_Crypto/precompiled_crypto.h
index fdf12be04fc118ae94d554e6c11f23c3baebac1d..8aaf4aa1008b14ba7dc113cddeb3417e196a08c5 100644
--- a/src/modules/_Crypto/precompiled_crypto.h
+++ b/src/modules/_Crypto/precompiled_crypto.h
@@ -48,11 +48,16 @@ void MOD_INIT2(md5)(void);
 void MOD_INIT(md5)(void);
 void MOD_EXIT(md5)(void);
 
-/* /precompiled/crypto/md5 */
+/* /precompiled/crypto/idea */
 void MOD_INIT2(idea)(void);
 void MOD_INIT(idea)(void);
 void MOD_EXIT(idea)(void);
 
+/* /precompiled/crypto/cast */
+void MOD_INIT2(cast)(void);
+void MOD_INIT(cast)(void);
+void MOD_EXIT(cast)(void);
+
 /* /precompiled/crypto/des */
 void MOD_INIT2(des)(void);
 void MOD_INIT(des)(void);
diff --git a/src/modules/_Crypto/testsuite.in b/src/modules/_Crypto/testsuite.in
index b099f370ed3b3bda0cfd31551b39c41d7b58c919..d3e89f705e71b5651ba045425b858c10f36da146 100644
--- a/src/modules/_Crypto/testsuite.in
+++ b/src/modules/_Crypto/testsuite.in
@@ -6,6 +6,7 @@ test_true([[programp(Crypto.cbc)]])
 test_true([[programp(Crypto.crypto)]])
 test_true([[programp(Crypto.des)]])
 test_true([[programp(Crypto.idea)]])
+test_true([[programp(Crypto.cast)]])
 test_true([[programp(Crypto.invert)]])
 test_true([[programp(Crypto.md5)]])
 test_true([[programp(Crypto.pipe)]])
@@ -63,11 +64,29 @@ cond( [[ master()->resolv("Gmp")->mpz ]],
 
 // IDEA
 test_true([[objectp(Crypto.idea())]])
-test_eq([[Crypto.idea()->set_encrypt_key(Crypto.hex_to_string("0123456789abcdef"
-							      "0123456789abcdef"))
-		->crypt_block(Crypto.hex_to_string("0123456789abcde7"))]],
+test_eq([[Crypto.idea()
+          ->set_encrypt_key(Crypto.hex_to_string("0123456789abcdef"
+					         "0123456789abcdef"))
+	  ->crypt_block(Crypto.hex_to_string("0123456789abcde7"))]],
 	[[Crypto.hex_to_string("2011aacef6f4bc7f")]])
 
+// CAST
+test_true([[objectp(Crypto.cast())]])
+test_eq([[Crypto.cast()
+          ->set_encrypt_key(Crypto.hex_to_string("0123456712345678"
+						 "234567893456789A"))
+	  ->crypt_block(Crypto.hex_to_string("0123456789ABCDEF"))]],
+	[[Crypto.hex_to_string("238B4FE5847E44B2")]])
+test_eq([[Crypto.cast()
+          ->set_encrypt_key(Crypto.hex_to_string("0123456712345678"
+						 "2345"))
+	  ->crypt_block(Crypto.hex_to_string("0123456789ABCDEF"))]],
+	[[Crypto.hex_to_string("EB6A711A2C02271B")]])
+test_eq([[Crypto.cast()
+          ->set_encrypt_key(Crypto.hex_to_string("0123456712"))
+	  ->crypt_block(Crypto.hex_to_string("0123456789ABCDEF"))]],
+	[[Crypto.hex_to_string("7AC816D16E9B302E")]])
+
 // RC4
 test_true([[objectp(Crypto.rc4())]])
 test_eq([[Crypto.rc4()->set_encrypt_key(Crypto.hex_to_string("0123456789abcdef"))
@@ -150,4 +169,4 @@ test_true([[objectp(Crypto.sha())]])
 test_eq([[Crypto.sha()->update("abc")->digest()]],
 	[[Crypto.hex_to_string("a9993e364706816aba3e25717850c26c9cd0d89d")]])
 
-]])
\ No newline at end of file
+]])