Last active
May 15, 2022 16:34
-
-
Save jramseygreen/7da60a232656f10fbf1367db67e7ed86 to your computer and use it in GitHub Desktop.
websocket connection python <--> javascript with RSA encrypted tunnel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import base64 | |
from Crypto.PublicKey import RSA | |
from Crypto.Cipher import PKCS1_v1_5 | |
# pass in the public key of the client to communicate with | |
class Crypt: | |
def __init__(self): | |
# 1024 means the keysize will be 1024 bits | |
key_pair = RSA.generate(1024) | |
self.__public_key = key_pair.publickey().exportKey().decode() | |
self.__private_key = key_pair.exportKey().decode() | |
self.__foreign_public_key = "" | |
# returns key to send to others | |
def get_public_key(self) -> str: | |
return self.__public_key | |
# key received from others to encrypt data with | |
def set_foreign_public_key(self, key: str): | |
self.__foreign_public_key = key | |
def has_foreign_public_key(self) -> bool: | |
return bool(self.__foreign_public_key) | |
# decrypt using private key | |
def decrypt(self, message: str) -> str: | |
priv_key = RSA.importKey(self.__private_key.encode()) | |
cipher = PKCS1_v1_5.new(priv_key) | |
return cipher.decrypt(base64.b64decode(message.encode()), "dummy text").decode() | |
# encrypt using foreign public key | |
def encrypt(self, message) -> str: | |
pub_key = RSA.importKey(self.__foreign_public_key.encode()) | |
cipher = PKCS1_v1_5.new(pub_key) | |
return base64.b64encode(cipher.encrypt(message.encode())).decode() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<!-- jsencrypt --> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsencrypt/2.3.1/jsencrypt.min.js" integrity="sha512-zDvrqenA0eFJZCxBsryzUZcvihvNlEXbteMv62yRxdhR4s7K1aaz+LjsRyfk6M+YJLyAJEuuquIAI8I8GgLC8A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> | |
<script type="module"> | |
const host = "localhost" | |
const port = "8080" | |
const testText = "hello there you stallion you" | |
// crypt instance + personal private key / personal public key | |
const crypt = new JSEncrypt({default_key_size: 1024}) | |
const privateKey = crypt.getPrivateKey() | |
const publicKey = crypt.getPublicKey() | |
var connection = null | |
var foreignPublicKey = "" // will be sent by server | |
window.onload = function() { | |
// connect to ws server | |
connection = new WebSocket("ws://" + host + ":" + port) | |
connection.onopen = function () { | |
console.log("connected to websocket server") | |
// send key immediately on open | |
connection.send(publicKey) // sent in naitive function not wrapper | |
}; | |
connection.onerror = function (error) { | |
console.log('WebSocket Error ' + error) | |
}; | |
connection.onmessage = function (e) { | |
console.log('received raw: ' + e.data) | |
// first message will be foreign public key | |
if (!foreignPublicKey) { | |
foreignPublicKey = e.data | |
// send some text through the wrapper after setting the key | |
send(testText) | |
return | |
} | |
crypt.setPrivateKey(privateKey) | |
var message = crypt.decrypt(e.data) | |
console.log("received decrypted: " + message) | |
} | |
} | |
// send wrapper for every message apart from key | |
function send(message) { | |
console.log("sent raw: " + message) | |
if (foreignPublicKey) { | |
crypt.setPublicKey(foreignPublicKey) | |
message = crypt.encrypt(message) | |
} | |
connection.send(message) | |
console.log("sent encrypted: " + message) | |
} | |
</script> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ws_server | |
import crypt | |
def on_message(client, server, message): | |
print("received raw:", message) | |
# first message will be foreign public key | |
if not crypt.has_foreign_public_key(): | |
crypt.set_foreign_public_key(message) | |
return | |
message = crypt.decrypt(message) | |
print("received decrypted: " + message) | |
send_message(client, "message received: " + message) | |
def on_new_client(client, server): | |
print(client, "joined the server") | |
# send public key on new connection | |
server.send_message(client, crypt.get_public_key()) # sent in naitive function not wrapper | |
def on_client_left(client, server): | |
print(client, "left the server") | |
# send wrapper for every message apart from key | |
def send_message(client, message): | |
print("sent raw:", message) | |
message = crypt.encrypt(message) | |
websocket_server.send_message(client, message) | |
print("sent encrypted:", message) | |
host = "localhost" | |
port = 8080 | |
# start ws server | |
websocket_server = ws_server.start_server(host, port) | |
# set event methods | |
websocket_server.set_fn_message_received(on_message) | |
websocket_server.set_fn_new_client(on_new_client) | |
websocket_server.set_fn_client_left(on_client_left) | |
print("started ws server") | |
# make crypt instance | |
crypt = crypt.Crypt() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from websocket_server import WebsocketServer | |
def start_server(host, port): | |
websocket_server = WebsocketServer(host=host, port=port) | |
websocket_server.run_forever(threaded=True) | |
return websocket_server |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uses pycryptodome and websocket-server pip modules (pip install pycryptodome, pip install websocket-server) - jsencrypt on the front end