diff --git a/README.md b/README.md
index e09e4cb52b079c4a4519f7a082b1528b89a76321..efa4945f6cf870c87a22435f536f39cb3845b15c 100644
--- a/README.md
+++ b/README.md
@@ -6,19 +6,24 @@ Description
 -----------
 
 A VNC client implemented using HTML5, specifically Canvas and
-WebSocket.
+WebSocket (supports 'wss://' encryption).
 
 For browsers that do not have builtin WebSocket support, the project
 includes web-socket-js, a WebSocket emulator using Adobe Flash
 (http://github.com/gimite/web-socket-js).
 
+In addition, as3crypto has been added to web-socket-js to implement
+WebSocket SSL/TLS encryption, i.e. the "wss://" URI scheme.
+(http://github.com/lyokato/as3crypto_patched).
+
 
 Requirements
 ------------
 
 Until there is VNC server support for WebSocket connections, you need
 to use a WebSocket to TCP socket proxy. There is a python proxy
-included ('wsproxy').
+included ('wsproxy'). One advantage of using the proxy is that it has
+builtin support for SSL/TLS encryption (i.e. "wss://").
 
 There a few reasons why a proxy is required:
 
@@ -38,6 +43,13 @@ There a few reasons why a proxy is required:
      the client asks the proxy (using the initial query string) to add
      sequence numbers to each packet.
 
+To encrypt the traffic using the WebSocket 'wss://' URI scheme you
+need to generate a certificate for the proxy to load. You can generate
+a self-signed certificate using openssl. The common name should be the
+hostname of the server where the proxy will be running:
+
+    `openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem`
+
 
 Usage
 -----
diff --git a/TODO b/TODO
index d72e028e47b8f6bbc74b846c41a5c3c6a73cdadf..e030ad6cd76788e067360ae0e38fa321d14242ed 100644
--- a/TODO
+++ b/TODO
@@ -1,8 +1,8 @@
-- Add WSS/https/SSL support to page and wsproxy.py
-
 - Make C version of wsproxy.py
 
 - Implement UI option for VNC shared mode.
 
 - Upgrade to protocol 3.8 
     - implement ZRLE encoding
+
+- Get web-socket-js RFC2817 proxying working again.
diff --git a/include/web-socket-js/WebSocketMain.swf b/include/web-socket-js/WebSocketMain.swf
deleted file mode 100644
index 33810879d37a0a2a29236b04785daaeaca7c61b0..0000000000000000000000000000000000000000
Binary files a/include/web-socket-js/WebSocketMain.swf and /dev/null differ
diff --git a/include/web-socket-js/WebSocketMain.swf b/include/web-socket-js/WebSocketMain.swf
new file mode 120000
index 0000000000000000000000000000000000000000..4753408d885e490df3c9788d765006a4109f8a2c
--- /dev/null
+++ b/include/web-socket-js/WebSocketMain.swf
@@ -0,0 +1 @@
+flash-src/WebSocketMain.swf
\ No newline at end of file
diff --git a/include/web-socket-js/flash-src/WebSocket.as b/include/web-socket-js/flash-src/WebSocket.as
index 3969363391054120293ae0b8bbb31eae9225acdf..40085c18e5150fe021b0acd5e2e6b6e504fd645a 100644
--- a/include/web-socket-js/flash-src/WebSocket.as
+++ b/include/web-socket-js/flash-src/WebSocket.as
@@ -16,6 +16,10 @@ import mx.controls.*;
 import mx.events.*;
 import mx.utils.*;
 import com.adobe.net.proxies.RFC2817Socket;
+import com.hurlant.crypto.tls.TLSSocket;
+import com.hurlant.crypto.tls.TLSConfig;
+import com.hurlant.crypto.tls.TLSEngine;
+import com.hurlant.crypto.tls.TLSSecurityParameters;
 
 [Event(name="message", type="WebSocketMessageEvent")]
 [Event(name="open", type="flash.events.Event")]
@@ -27,7 +31,11 @@ public class WebSocket extends EventDispatcher {
   private static var OPEN:int = 1;
   private static var CLOSED:int = 2;
   
-  private var socket:RFC2817Socket;
+  //private var rawSocket:RFC2817Socket;
+  private var rawSocket:Socket;
+  private var tlsSocket:TLSSocket;
+  private var tlsConfig:TLSConfig;
+  private var socket:Socket;
   private var main:WebSocketMain;
   private var scheme:String;
   private var host:String;
@@ -59,6 +67,7 @@ public class WebSocket extends EventDispatcher {
     // "Header1: xxx\r\nHeader2: yyyy\r\n"
     this.headers = headers;
     
+    /*
     socket = new RFC2817Socket();
             
     // if no proxy information is supplied, it acts like a normal Socket
@@ -66,13 +75,30 @@ public class WebSocket extends EventDispatcher {
     if (proxyHost != null && proxyPort != 0){      
       socket.setProxyInfo(proxyHost, proxyPort);
     } 
-    
-    socket.addEventListener(Event.CLOSE, onSocketClose);
-    socket.addEventListener(Event.CONNECT, onSocketConnect);
-    socket.addEventListener(IOErrorEvent.IO_ERROR, onSocketIoError);
-    socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSocketSecurityError);
-    socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
-    socket.connect(host, port);
+    */
+
+    ExternalInterface.call("console.log", "[WebSocket] scheme: " + scheme);
+    rawSocket = new Socket();
+
+    rawSocket.addEventListener(Event.CLOSE, onSocketClose);
+    rawSocket.addEventListener(Event.CONNECT, onSocketConnect);
+    rawSocket.addEventListener(IOErrorEvent.IO_ERROR, onSocketIoError);
+    rawSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSocketSecurityError);
+    if (scheme == "wss") {
+        tlsConfig= new TLSConfig(TLSEngine.CLIENT,
+            null, null, null, null, null,
+            TLSSecurityParameters.PROTOCOL_VERSION);
+        tlsConfig.trustSelfSignedCertificates = true;
+        tlsConfig.ignoreCommonNameMismatch = true;
+
+        tlsSocket = new TLSSocket();
+        tlsSocket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
+        socket = (tlsSocket as Socket);
+    } else {
+        rawSocket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
+        socket = (rawSocket as Socket);
+    }
+    rawSocket.connect(host, port);
   }
   
   public function send(data:String):int {
@@ -118,6 +144,12 @@ public class WebSocket extends EventDispatcher {
   
   private function onSocketConnect(event:Event):void {
     main.log("connected");
+
+    if (scheme == "wss") {
+        ExternalInterface.call("console.log", "[WebSocket] starting SSL/TLS");
+        tlsSocket.startTLS(rawSocket, host, tlsConfig);
+    }
+    
     var hostValue:String = host + (port == 80 ? "" : ":" + port);
     var cookie:String = "";
     if (main.getCallerHost() == host) {
diff --git a/include/web-socket-js/flash-src/WebSocketMain.swf b/include/web-socket-js/flash-src/WebSocketMain.swf
new file mode 100644
index 0000000000000000000000000000000000000000..91da2f8c3ba57291b042aab9a749a3f3e3c60cbb
Binary files /dev/null and b/include/web-socket-js/flash-src/WebSocketMain.swf differ
diff --git a/include/web-socket-js/flash-src/com/hurlant b/include/web-socket-js/flash-src/com/hurlant
new file mode 120000
index 0000000000000000000000000000000000000000..f9f4c84c5c708410054bd531de276572698ae378
--- /dev/null
+++ b/include/web-socket-js/flash-src/com/hurlant
@@ -0,0 +1 @@
+../../../as3crypto_patched/src/com/hurlant
\ No newline at end of file
diff --git a/links b/links
new file mode 100644
index 0000000000000000000000000000000000000000..93deb3d9a4245ccaa3bdc71ab64012a835887185
--- /dev/null
+++ b/links
@@ -0,0 +1,21 @@
+Canvas Browser Compatibility:
+    http://philip.html5.org/tests/canvas/suite/tests/results.html
+
+WebSockets API standard:
+    http://dev.w3.org/html5/websockets/
+
+Browser Keyboard Events detailed:
+    http://unixpapa.com/js/key.html
+
+ActionScript (Flash) WebSocket implementation:
+    http://github.com/gimite/web-socket-js
+
+ActionScript (Flash) crypto/TLS library:
+    http://code.google.com/p/as3crypto
+    http://github.com/lyokato/as3crypto_patched
+
+TLS Protocol:
+    http://en.wikipedia.org/wiki/Transport_Layer_Security
+
+Generate self-signed certificate:
+    http://docs.python.org/dev/library/ssl.html#certificates
diff --git a/vnc.html b/vnc.html
index ea66975d556c6954386c975c885c06c28330c465..c577068d44a214297f3e3d802fc7495898b7eb2a 100644
--- a/vnc.html
+++ b/vnc.html
@@ -7,6 +7,7 @@
         Host: <input id='host' style='width:100'>&nbsp;
         Port: <input id='port' style='width:50'>&nbsp;
         Password: <input id='password' type='password' style='width:80'>&nbsp;
+        Encrypt: <input id='encrypt' type='checkbox'>&nbsp;
         <input id='connectButton' type='button' value='Loading'
             style='width:100px' disabled>&nbsp;
         <br><br>
@@ -75,6 +76,7 @@
                 $('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
                 $('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
                 $('password').value = (url.match(/password=([^&#]*)/) || ['',''])[1];
+                $('encrypt').checked = (url.match(/encrypt=([^&#]*)/) || ['',''])[1];
             }
         }
     </script>
diff --git a/vnc.js b/vnc.js
index b46aaacfad8c426c32c6a7206971fb5e8da85e5e..cc0692d76a0c3cf3eeecb40b00d4b4562cc187d1 100644
--- a/vnc.js
+++ b/vnc.js
@@ -906,7 +906,11 @@ updateState: function(state, statusMsg) {
 init_ws: function () {
 
     console.log(">> init_ws");
-    var uri = "ws://" + RFB.host + ":" + RFB.port + "/?b64encode";
+    var scheme = "ws://";
+    if ($('encrypt').checked) {
+        scheme = "wss://";
+    }
+    var uri = scheme + RFB.host + ":" + RFB.port + "/?b64encode";
     if (RFB.use_seq) {
         uri += "&seq_num";
     }
diff --git a/webs.py b/webs.py
new file mode 100755
index 0000000000000000000000000000000000000000..f0bffe2087dbdfd476749d009fb15c6be4183825
--- /dev/null
+++ b/webs.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+'''
+A super simple HTTP/HTTPS webserver for python. Automatically detect
+
+You can make a cert/key with openssl using:
+openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
+as taken from http://docs.python.org/dev/library/ssl.html#certificates
+
+'''
+
+import traceback, sys
+import socket
+import ssl
+#import http.server as server      # python 3.X
+import SimpleHTTPServer as server  # python 2.X
+
+def do_request(connstream, from_addr):
+    x = object()
+    server.SimpleHTTPRequestHandler(connstream, from_addr, x)
+
+def serve():
+    bindsocket = socket.socket()
+    #bindsocket.bind(('localhost', PORT))
+    bindsocket.bind(('', PORT))
+    bindsocket.listen(5)
+
+    print("serving on port", PORT)
+
+    while True:
+        try:
+            newsocket, from_addr = bindsocket.accept()
+            peek = newsocket.recv(1024, socket.MSG_PEEK)
+            if peek.startswith("\x16"):
+                connstream = ssl.wrap_socket(
+                        newsocket,
+                        server_side=True,
+                        certfile='self.pem',
+                        ssl_version=ssl.PROTOCOL_TLSv1)
+            else:
+                connstream = newsocket
+
+            do_request(connstream, from_addr)
+
+        except Exception:
+            traceback.print_exc()
+
+try:
+    PORT = int(sys.argv[1])
+except:
+    print "%s port" % sys.argv[0]
+    sys.exit(2)
+
+serve()
diff --git a/wsproxy.py b/wsproxy.py
index a1710b19ede5de47c13f9d3c5a26bcd8e564094b..6f6296a088f6e563acdada124c57bac4bd9ef0fb 100755
--- a/wsproxy.py
+++ b/wsproxy.py
@@ -1,5 +1,14 @@
 #!/usr/bin/python
 
+'''
+A WebSocket to TCP socket proxy with support for "wss://" encryption.
+
+You can make a cert/key with openssl using:
+openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
+as taken from http://docs.python.org/dev/library/ssl.html#certificates
+
+'''
+
 import sys, os, socket, ssl, time, traceback, re
 from base64 import b64encode, b64decode
 from select import select
@@ -129,7 +138,7 @@ def do_handshake(sock):
         retsock = ssl.wrap_socket(
                 sock,
                 server_side=True,
-                certfile='wsproxy.pem',
+                certfile='self.pem',
                 ssl_version=ssl.PROTOCOL_TLSv1)
         scheme = "wss"
         print "Using SSL/TLS"