diff --git a/.gitattributes b/.gitattributes
index 956f086e8f9509668b0ed2e950c38053038ce3f2..f90b6c3f70635097be4430743719deae18e61ebe 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -381,6 +381,7 @@ testfont binary
 /src/modules/_Crypto/lib/sha.c foreign_ident
 /src/modules/_Crypto/md5.c foreign_ident
 /src/modules/_Crypto/md5.pike foreign_ident
+/src/modules/_Crypto/nt.c foreign_ident
 /src/modules/_Crypto/pipe.c foreign_ident
 /src/modules/_Crypto/rc4.c foreign_ident
 /src/modules/_Crypto/sha.c foreign_ident
diff --git a/lib/modules/Crypto/randomness.pmod b/lib/modules/Crypto/randomness.pmod
index 0336bedd6da50b034055a79b686b15f9913f6159..b1879bad78d375e15dfe3786d27d66aed684ef8c 100644
--- a/lib/modules/Crypto/randomness.pmod
+++ b/lib/modules/Crypto/randomness.pmod
@@ -1,4 +1,4 @@
-/* $Id: randomness.pmod,v 1.13 1999/11/25 23:10:52 grubba Exp $
+/* $Id: randomness.pmod,v 1.14 1999/12/01 22:37:22 marcus Exp $
  */
 
 //! module Crypto
@@ -41,6 +41,22 @@ PRIVATE object global_rc4;
 //	Executes several programs to generate some entropy from their output.
 PRIVATE string some_entropy()
 {
+#ifdef __NT__
+  object ctx = Crypto.nt.CryptAcquireContext(0, 0, Crypto.nt.PROV_RSA_FULL,
+					     Crypto.nt.CRYPT_VERIFYCONTEXT
+					     /*|Crypto.nt.CRYPT_SILENT*/);
+  if(!ctx)
+    throw(({ "Crypto.random: couldn't create crypto context\n", backtrace()}));
+
+  string res = ctx->CryptGenRandom(8192);
+
+  if(!res)
+    throw(({ "Crypto.random: couldn't generate randomness\n", backtrace()}));
+
+  destruct(ctx);
+
+  return res;
+#else /* !__NT__ */
   string res;
   object parent_pipe, child_pipe;
   mapping env=getenv()+([]);
@@ -50,13 +66,8 @@ PRIVATE string some_entropy()
   if (!child_pipe)
     throw( ({ "Crypto.random->popen: couldn't create pipe\n", backtrace() }) );
 
-
-#ifndef __NT__
   object null=Stdio.File("/dev/null","rw");
   env["PATH"]=PATH;
-#else
-  object null=Stdio.File("nul:","rw");
-#endif
   
   foreach(SYSTEM_COMMANDS, string cmd)
     {
@@ -72,6 +83,7 @@ PRIVATE string some_entropy()
   destruct(child_pipe);
   
   return parent_pipe->read();
+#endif
 }
 
 
diff --git a/src/modules/_Crypto/Makefile.in b/src/modules/_Crypto/Makefile.in
index aa04a2b015490182696d55827b9df06a01c17e51..5ebbdea60232187d64c7d64a010bcc9fa4369d32 100644
--- a/src/modules/_Crypto/Makefile.in
+++ b/src/modules/_Crypto/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.19 1999/11/18 08:01:48 hubbe Exp $
+# $Id: Makefile.in,v 1.20 1999/12/01 22:37:22 marcus Exp $
 @make_variables@
 VPATH=@srcdir@:@srcdir@/../..:../..
 
@@ -6,7 +6,7 @@ VPATH=@srcdir@:@srcdir@/../..:../..
 MASS_DESTRUCTION_OBJS = idea.o des.o cast.o rc4.o 
 # END NATIONAL SECURITY
 
-OBJS= $(MASS_DESTRUCTION_OBJS) crypto.o invert.o sha.o md5.o pipe.o cbc.o
+OBJS= $(MASS_DESTRUCTION_OBJS) crypto.o invert.o sha.o md5.o pipe.o cbc.o nt.o
 
 MODULE_ARCHIVES=lib/algorithms.a
 MODULE_SUBDIRS=lib
diff --git a/src/modules/_Crypto/nt.c b/src/modules/_Crypto/nt.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce2f8445e95f4b4c80259a11d47ce9756421fb2a
--- /dev/null
+++ b/src/modules/_Crypto/nt.c
@@ -0,0 +1,171 @@
+/*
+ * $Id: nt.c,v 1.1 1999/12/01 22:37:22 marcus Exp $
+ *
+ * NT crypto stuff for Pike
+ */
+
+#include "global.h"
+#include "stralloc.h"
+#include "interpret.h"
+#include "svalue.h"
+#include "object.h"
+#include "error.h"
+#include "las.h"
+#include "module_support.h"
+
+#ifdef __NT__
+
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+#include <wincrypt.h>
+
+
+static struct program *cryptcontext_program = NULL;
+
+struct cryptcontext_storage {
+  HCRYPTPROV handle;
+};
+
+#define THIS_CRYPTCONTEXT ((struct cryptcontext_storage *)(fp->current_storage))
+
+static void init_cryptcontext_struct(struct object *o)
+{
+  struct cryptcontext_storage *c = THIS_CRYPTCONTEXT;
+
+  c->handle = 0;
+}
+
+static void exit_cryptcontext_struct(struct object *o)
+{
+  struct cryptcontext_storage *c = THIS_CRYPTCONTEXT;
+
+  if(c->handle)
+    CryptReleaseContext(c->handle, 0);
+}
+
+static void f_CryptGenRandom(INT32 args)
+{
+  struct cryptcontext_storage *c = THIS_CRYPTCONTEXT;
+  struct pike_string *str = NULL, *res;
+  INT32 siz;
+
+  get_all_args("CryptGenRandom()", args, (args>1? "%i%S":"%i"), &siz, &str);
+
+  if(siz == 0 && str != NULL)
+    siz = str->len;
+
+  res = begin_shared_string(siz);
+  if(str != NULL && siz > 0)
+    memcpy(res->str, str->str, (str->len<siz? str->len : siz));
+  if(CryptGenRandom(c->handle, siz, (BYTE*)res->str)) {
+    pop_n_elems(args);
+    push_string(end_shared_string(res));
+  } else {
+    pop_n_elems(args);
+    free_string(end_shared_string(res));
+    push_int(0);
+  }
+}
+
+static void f_CryptAcquireContext(INT32 args)
+{
+  char *str1=NULL, *str2=NULL;
+  INT32 typ, flags, fake1, fake2;
+  int nullflag=0;
+  HCRYPTPROV prov;
+
+  if(args>0 && sp[-args].type == T_INT && sp[-args].u.integer == 0)
+    nullflag |= 1;
+  if(args>1 && sp[1-args].type == T_INT && sp[1-args].u.integer == 0)
+    nullflag |= 2;
+
+  switch(nullflag) {
+  case 0:
+    get_all_args("Crypto.nt.CryptAcquireContext()", args, "%s%s%i%i",
+		 &str1, &str2, &typ, &flags);
+    break;
+  case 1:
+    get_all_args("Crypto.nt.CryptAcquireContext()", args, "%i%s%i%i",
+		 &fake1, &str2, &typ, &flags);
+    break;
+  case 2:
+    get_all_args("Crypto.nt.CryptAcquireContext()", args, "%s%i%i%i",
+		 &str1, &fake2, &typ, &flags);
+    break;
+  case 3:
+    get_all_args("Crypto.nt.CryptAcquireContext()", args, "%i%i%i%i",
+		 &fake1, &fake2, &typ, &flags);
+    break;
+  }
+
+  if(!CryptAcquireContext(&prov, str1, str2, typ, flags)) {
+    pop_n_elems(args);
+    push_int(0);
+    return;
+  }
+  
+  pop_n_elems(args);
+  push_object(clone_object(cryptcontext_program, 0));
+  ((struct cryptcontext_storage *)get_storage(sp[-1].u.object,
+					      cryptcontext_program))->handle =
+    prov;
+}
+
+
+#endif /* __NT__ */
+
+
+void pike_nt_init(void)
+{
+#ifdef __NT__
+
+#define SIMPCONST(X) \
+      add_integer_constant(#X,X,0);
+
+  start_new_program();
+
+  SIMPCONST(PROV_RSA_FULL);
+  SIMPCONST(PROV_RSA_SIG);
+  SIMPCONST(PROV_DSS);
+  SIMPCONST(PROV_FORTEZZA);
+  SIMPCONST(PROV_MS_EXCHANGE);
+  SIMPCONST(PROV_SSL);
+
+  SIMPCONST(CRYPT_VERIFYCONTEXT);
+  SIMPCONST(CRYPT_NEWKEYSET);
+  SIMPCONST(CRYPT_DELETEKEYSET);
+#ifdef CRYPT_MACHINE_KEYSET
+  SIMPCONST(CRYPT_MACHINE_KEYSET);
+#endif
+#ifdef CRYPT_SILENT
+  SIMPCONST(CRYPT_SILENT);
+#endif
+
+  add_function_constant("CryptAcquireContext",f_CryptAcquireContext,
+			"function(string,string,int,int:object)", 0);
+
+  end_class("nt", 0);
+
+  start_new_program();
+  ADD_STORAGE(struct cryptcontext_storage);
+  /* function(int,string|void:string) */
+  ADD_FUNCTION("CryptGenRandom", f_CryptGenRandom,
+	       tFunc(tInt tOr(tString,tVoid),tString), 0);
+  set_init_callback(init_cryptcontext_struct);
+  set_exit_callback(exit_cryptcontext_struct);
+  cryptcontext_program = end_program();
+
+#endif /* __NT__ */
+}
+
+void pike_nt_exit(void)
+{
+#ifdef __NT__
+  if(cryptcontext_program) {
+    free_program(cryptcontext_program);
+    cryptcontext_program=NULL;
+  }
+#endif /* __NT__ */
+}