diff --git a/src/sbbs3/js_cryptcon.c b/src/sbbs3/js_cryptcon.c
index 196961b6e5078a8b4a74225075a0b6d3e515e0fe..1092154df919a002c442154221cb86ec5963e6be 100644
--- a/src/sbbs3/js_cryptcon.c
+++ b/src/sbbs3/js_cryptcon.c
@@ -5,7 +5,7 @@
 #include "sbbs.h"
 #include <cryptlib.h>
 #include "js_request.h"
-#include "js_socket.h"
+#include "ssl.h"
 
 struct private_data {
 	CRYPT_CONTEXT	ctx;
diff --git a/src/sbbs3/js_socket.c b/src/sbbs3/js_socket.c
index 51247ee70a4681622a072896262c857454ac223a..6ecee94d830e29dc4ce3e0874dd018c16db80e21 100644
--- a/src/sbbs3/js_socket.c
+++ b/src/sbbs3/js_socket.c
@@ -45,15 +45,8 @@
 
 #ifdef JAVASCRIPT
 
-int cryptInitialized=0;
-
 static const char* getprivate_failure = "line %d %s JS_GetPrivate failed";
 
-static void do_cryptEnd(void)
-{
-	cryptEnd();
-}
-
 static int do_cryptAttribute(const CRYPT_CONTEXT session, CRYPT_ATTRIBUTE_TYPE attr, int val)
 {
 	int ret;
@@ -76,26 +69,6 @@ static int do_cryptAttribute(const CRYPT_CONTEXT session, CRYPT_ATTRIBUTE_TYPE a
 	return ret;
 }
 
-int DLLCALL do_cryptInit(void)
-{
-	int ret;
-
-	if(!cryptInitialized) {
-		if((ret=cryptInit())==CRYPT_OK) {
-			cryptAddRandom(NULL,CRYPT_RANDOM_SLOWPOLL);
-			cryptInitialized=1;
-			atexit(do_cryptEnd);
-		}
-		else {
-			if (ret == -12)	// This is a bit of a hack...
-				cryptInitialized=1;
-			else
-				lprintf(LOG_ERR,"cryptInit() returned %d", ret);
-		}
-	}
-	return cryptInitialized;
-}
-
 static int do_cryptAttributeString(const CRYPT_CONTEXT session, CRYPT_ATTRIBUTE_TYPE attr, void *val, int len)
 {
 	int ret=cryptSetAttributeString(session, attr, val, len);
diff --git a/src/sbbs3/js_socket.h b/src/sbbs3/js_socket.h
index 75f79519492bdd4fb0271e7ee67831cf6454fead..ad02ad24890bac99b0722f79959845ed34e16351 100644
--- a/src/sbbs3/js_socket.h
+++ b/src/sbbs3/js_socket.h
@@ -26,10 +26,6 @@ typedef struct
 extern "C" {
 #endif
 
-extern int cryptInitialized;
-
-DLLEXPORT int DLLCALL do_cryptInit(void);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 3000fd4b4354aebaa09040a3191f63abf66d76f7..b5bd3bb9841d76de1128f2c09dedf485dfa46b0a 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -41,7 +41,7 @@
 #include "netwrap.h"
 #include "js_rtpool.h"
 #include "js_request.h"
-#include "js_socket.h"
+#include "ssl.h"
 #include <multisock.h>
 #include <limits.h>		// HOST_NAME_MAX
 
diff --git a/src/sbbs3/ssl.c b/src/sbbs3/ssl.c
index 0accf74e2d15c3b695637d6acf1d854cf4949811..365d993c1ce9b93da91606b9e5ed3c97d86e3610 100644
--- a/src/sbbs3/ssl.c
+++ b/src/sbbs3/ssl.c
@@ -1,7 +1,10 @@
 #include <stdbool.h>
 #include <stdio.h>
+
+#include <threadwrap.h>
+
 #include "ssl.h"
-#include "js_socket.h"	// TODO... move this stuff in here?
+//#include "js_socket.h"	// TODO... move this stuff in here?
 
 static scfg_t	scfg;
 
@@ -48,6 +51,34 @@ static bool get_error_string(int status, CRYPT_SESSION sess, char estr[SSL_ESTR_
 	return false;
 }
 
+static pthread_once_t crypt_init_once = PTHREAD_ONCE_INIT;
+static pthread_mutex_t ssl_cert_mutex;
+
+static void do_cryptEnd(void)
+{
+	cryptEnd();
+}
+
+static void internal_do_cryptInit(void)
+{
+	int ret;
+
+	if((ret=cryptInit())==CRYPT_OK) {
+		cryptAddRandom(NULL,CRYPT_RANDOM_SLOWPOLL);
+		atexit(do_cryptEnd);
+	}
+	else {
+		lprintf(LOG_ERR,"cryptInit() returned %d", ret);
+	}
+	pthread_mutex_init(&ssl_cert_mutex, NULL);
+	return;
+}
+
+int DLLCALL do_cryptInit(void)
+{
+	pthread_once(&crypt_init_once, internal_do_cryptInit);
+}
+
 #define DO(x)	get_error_string(x, ssl_context, estr, __FILE__, __LINE__)
 
 CRYPT_CONTEXT DLLCALL get_ssl_cert(scfg_t *cfg, char estr[SSL_ESTR_LEN])
@@ -61,16 +92,20 @@ CRYPT_CONTEXT DLLCALL get_ssl_cert(scfg_t *cfg, char estr[SSL_ESTR_LEN])
 
 	if(!do_cryptInit())
 		return -1;
+	pthread_mutex_lock(&ssl_cert_mutex);
 	memset(&ssl_context, 0, sizeof(ssl_context));
 	/* Get the certificate... first try loading it from a file... */
 	SAFEPRINTF2(str,"%s%s",cfg->ctrl_dir,"ssl.cert");
 	if(cryptStatusOK(cryptKeysetOpen(&ssl_keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, str, CRYPT_KEYOPT_NONE))) {
-		if(!DO(cryptGetPrivateKey(ssl_keyset, &ssl_context, CRYPT_KEYID_NAME, "ssl_cert", cfg->sys_pass)))
+		if(!DO(cryptGetPrivateKey(ssl_keyset, &ssl_context, CRYPT_KEYID_NAME, "ssl_cert", cfg->sys_pass))) {
+			pthread_mutex_unlock(&ssl_cert_mutex);
 			return -1;
+		}
 	}
 	else {
 		/* Couldn't do that... create a new context and use the cert from there... */
 		if(!cryptStatusOK(i=cryptCreateContext(&ssl_context, CRYPT_UNUSED, CRYPT_ALGO_RSA))) {
+			pthread_mutex_unlock(&ssl_cert_mutex);
 			sprintf(estr, "cryptlib error %d creating SSL context",i);
 			return -1;
 		}
@@ -101,6 +136,7 @@ CRYPT_CONTEXT DLLCALL get_ssl_cert(scfg_t *cfg, char estr[SSL_ESTR_LEN])
 	}
 
 	cryptKeysetClose(ssl_keyset);
+	pthread_mutex_unlock(&ssl_cert_mutex);
 	return ssl_context;
 
 failure_return_3:
@@ -109,5 +145,6 @@ failure_return_2:
 	cryptKeysetClose(ssl_keyset);
 failure_return_1:
 	cryptDestroyContext(ssl_context);
+	pthread_mutex_unlock(&ssl_cert_mutex);
 	return -1;
 }
diff --git a/src/sbbs3/ssl.h b/src/sbbs3/ssl.h
index 336df99efbafcef554a691b524131b368f4ac0a1..439c07c066b47985186a3a5888f5b74457ce3533 100644
--- a/src/sbbs3/ssl.h
+++ b/src/sbbs3/ssl.h
@@ -37,6 +37,7 @@ DLLEXPORT void DLLCALL free_crypt_attrstr(char *attr);
 DLLEXPORT char* DLLCALL get_crypt_attribute(CRYPT_SESSION sess, C_IN CRYPT_ATTRIBUTE_TYPE attr);
 DLLEXPORT char* DLLCALL get_crypt_error(CRYPT_SESSION sess);
 DLLEXPORT CRYPT_CONTEXT DLLCALL get_ssl_cert(scfg_t *cfg, char estr[SSL_ESTR_LEN]);
+DLLEXPORT int DLLCALL do_cryptInit(void);
 
 #if defined(__cplusplus)
 }