Mask & Unmask websocket data in python - python

I'm trying to create a python websocket class that can connect to a websocket server and I need help writing a function that can mask and unmask data. I have an similar websocket class in PHP that looks like this:
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
function mask($text){
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
So I tried to create the same thing in Python:
def mask(text):
b1 = 0x80 | (0x1 & 0x0f)
length = len(text)
if length <= 125:
header = struct.pack('CC', b1, length)
if length > 125 & length < 65536:
header = struct.pack('CCn', b1, 126, length)
if length <= 65536:
header = struct.pack('CCNN', b1, 127, length)
return header + text
And it returns an error:
Bad char in struct format
If anyone could help me write the function that would be great. Thanks!

I found an really helpful script that did exactly what i needed.
http://sidekick.windforwings.com/2013/03/minimal-websocket-broadcast-server-in.html

Related

How to pass a string inside a function in python which is exported from cpp using the library ctypes

cpp code snippet where i am exporting the function encrypt which takes argument like below
#include <iostream>
using namespace std;
string Function(char* str)
{
string temp = str;
int length = temp.length();
int disp = length,i=0;
char printChar;
char *store = (char *)malloc(sizeof(char)*100);
while(disp > 0) {
printChar = *(str + length - disp);
if ((printChar >= 65) && (printChar <= 90)) {
if (printChar+disp > 90) {
printChar = ((printChar+disp) % 90) + 64;
store[i] = printChar;
}else{
printChar += disp;
store[i] = printChar;
};
}
else if ((printChar >= 97) && (printChar <= 122)) {
if (printChar+disp > 122) {
printChar = ((printChar+disp) % 122) + 96;
store[i] = printChar;
}else{
printChar += disp;
store[i] = printChar;
};
}
else {
store[i] = printChar;
};
disp -= 1;
i += 1;
};
return store;
}
// The part where i am exporting
extern "C" {
string encrypt(char* str) // this is the functionName(in this case encrypt) which i am giving when exporting
{
return Function(str);
}
}
What should be my python code to pass a string in this exported function somewhat like:
userString = input()
result = encrypt(userstring) // this is function created in cpp
print(result)
I don't know how to use ctypes properly. So please can someone help with this question?

Not able to connect in socket programming in C++ whereas in python, it works

I have a piece of code in python. It is related to client Socket programming. I want to get the NTRIP data from "www.rtk2go.com". The code written in python works well and serves the purpose.
import socket
import base64
server = "www.rtk2go.com"
port = "2101"
mountpoint = "leedgps"
username = ""
password = ""
def getHTTPBasicAuthString(username, password):
inputstring = username + ':' + password
pwd_bytes = base64.standard_b64encode(inputstring.encode("utf-8"))
pwd = pwd_bytes.decode("utf-8").replace('\n', '')
return pwd
pwd = getHTTPBasicAuthString(username, password)
print(pwd)
header = "GET /{} HTTP/1.0\r\n".format(mountpoint) + \
"User-Agent: NTRIP u-blox\r\n" + \
"Accept: */*\r\n" + \
"Authorization: Basic {}\r\n".format(pwd) + \
"Connection: close\r\n\r\n"
print(header)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((server, int(port)))
s.sendto(header.encode('utf-8'), (server, int(port)))
resp = s.recv(1024)
try:
while True:
try:
data = s.recv(2048)
except:
pass
finally:
s.close()
I wanted to implement the same thing in c++ code and after going through few online tutorials, I wrote the following code in C++ (I am very new to C++)
#include <iostream>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>
using namespace std;
#define SIZE 1000
#define PORT 2101
string base64Encoder(string input_str, int len_str) {
char char_set[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *res_str = (char *) malloc(SIZE * sizeof(char));
int index, no_of_bits = 0, padding = 0, val = 0, count = 0, temp;
int i, j, k = 0;
for (i = 0; i < len_str; i += 3) {
val = 0, count = 0, no_of_bits = 0;
for (j = i; j < len_str && j <= i + 2; j++) {
val = val << 8;
val = val | input_str[j];
count++;
}
no_of_bits = count * 8;
padding = no_of_bits % 3;
while (no_of_bits != 0) {
// retrieve the value of each block
if (no_of_bits >= 6) {
temp = no_of_bits - 6;
// binary of 63 is (111111) f
index = (val >> temp) & 63;
no_of_bits -= 6;
} else {
temp = 6 - no_of_bits;
// append zeros to right if bits are less than 6
index = (val << temp) & 63;
no_of_bits = 0;
}
res_str[k++] = char_set[index];
}
}
for (i = 1; i <= padding; i++) {
res_str[k++] = '=';
}
res_str[k] = '\0';
string a = res_str;
return a;
}
int main() {
string input_str = ":";
int len_str;
len_str = input_str.length();
string pwd = base64Encoder(input_str, len_str);
string mountpoint = "leedgps";
string header = "GET /" + mountpoint + " HTTP/1.0\r\n" + \
"User-Agent: NTRIP u-blox\r\n" + \
"Accept: */*\r\n" + \
"Authorization: Basic " + pwd + "\r\n" + \
"Connection: close\r\n\r\n";
struct hostent *h;
if ((h = gethostbyname("www.rtk2go.com")) == NULL) { // Lookup the hostname
cout << "cannot look up hostname" << endl;
}
struct sockaddr_in saddr;
int sockfd, connfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0) < 0;
if (sockfd) {
printf("Error creating socket\n");
}
saddr.sin_family = AF_INET;
saddr.sin_port = htons(2101);
if(inet_pton(AF_INET, "3.23.52.207", &saddr.sin_addr)<=0) //
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
cout << connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) << endl;
return 0;
}
But the connect method always returns -1 (in C++). Any idea what am I doing wrong?
sockfd = socket(AF_INET, SOCK_STREAM, 0) < 0;
means that sockfd is either 0 or 1, which is not a valid socket.
Do this instead:
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket\n");
}

Python: Socket communication with Arduino MKR1000 not working properly

I got a system where I would send a command from my host computer using Python Socket (the computer is the server) and the MKR1000 (client) would send back information depends on the command sent.
Unfortunately, the bidirectional communication is unstable. I can guarantee the MKR1000 received the command and (maybe) sending information back, but for some reason, my host computer would not receive the command.
Anyway, this is my first time trying out socket, so I would like some guru to review my code and maybe spot the mistake in here? Thanks a lot.
Python:
import socket
import time
def coor2bytes(coor_fnc):
coorByte = [0, 0, 0, 0, 0, 0]
if (coor_fnc[0] >= 0):
coorByte[0] = (coor_fnc[0] >> 8) & 0xFF # High byte of X
coorByte[1] = coor_fnc[0] & 0xFF # Low byte of X
else:
coor_fnc[0] = coor_fnc[0]*(-1)
coorByte[0] = (coor_fnc[0] >> 8) & 0xFF # High byte of X
coorByte[0] = coorByte[0] ^ 0x80
coorByte[1] = coor_fnc[0] & 0xFF # Low byte of X
if (coor_fnc[1] >= 0):
coorByte[2] = (coor_fnc[1] >> 8) & 0xFF # High byte of Y
coorByte[3] = coor_fnc[1] & 0xFF # Low byte of Y
else:
coor_fnc[1] = coor_fnc[1]*(-1)
coorByte[2] = (coor_fnc[1] >> 8) & 0xFF # High byte of X
coorByte[2] = coorByte[2] ^ 0x80
coorByte[3] = coor_fnc[1] & 0xFF # Low byte of X
if (coor_fnc[2] >= 0):
coorByte[4] = (coor_fnc[2] >> 8) & 0xFF # High byte of Phi
coorByte[5] = coor_fnc[2] & 0xFF # Low byte of Phi
else:
coor_fnc[2] = coor_fnc[2]*(-1)
coorByte[4] = (coor_fnc[2] >> 8) & 0xFF # High byte of Phi
coorByte[4] = coorByte[4] ^ 0x80
coorByte[5] = coor_fnc[2] & 0xFF # Low byte of Phi
return coorByte
def bytes2coor(byte_fnc):
receivedCoor_fnc = [0, 0, 0]
receivedCoor_fnc[0] = ((-1)**(byte_fnc[0]>>7)) * ((byte_fnc[1]) | (((byte_fnc[0]&0x7f)<<8)))
receivedCoor_fnc[1] = ((-1)**(byte_fnc[2]>>7)) * ((byte_fnc[3]) | (((byte_fnc[2]&0x7f)<<8)))
receivedCoor_fnc[2] = ((-1)**(byte_fnc[4]>>7)) * ((byte_fnc[5]) | (((byte_fnc[4]&0x7f)<<8)))
return receivedCoor_fnc
if __name__ == '__main__':
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1234)) # bind(ip, port)
print("Done binding.")
s.listen(2)
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
clientsocket.settimeout(1)
while True:
print();
print("What you want to do?")
print("0. Send target")
print("1. Get current coordinate")
print("2. Set current coordinate (not yet implement)")
try:
a = int(input("I choose: "))
except Exception:
print("Error.")
a = -1;
if (a == 0):
coor = [0, 0, 0]
try:
coor[0] = int(input("X: "))
coor[1] = -int(input("y: "))
coor[2] = int(input("phi: "))
coorByte = coor2bytes(coor)
clientsocket.send(bytes([0]))
clientsocket.send(bytes(coorByte))
print("I already sent the target.")
except Exception:
print("Error.")
elif (a == 1):
receive = 0
while (not receive):
try:
clientsocket.send(bytes([1]))
bytesReceived = []
full_msg = []
while (len(full_msg) < 8):
bytesReceived = clientsocket.recv(8)
for x in range(len(bytesReceived)):
full_msg.append(bytesReceived[x])
receivedCoor = bytes2coor(full_msg)
print("coordinate received: " + str(receivedCoor))
receive = 1
except socket.timeout:
print("Time out. Will try again.")
elif (a == 2):
setCoor = [0, 0, 0]
try:
setCoor[0] = int(input("X: "))
setCoor[1] = -int(input("y: "))
setCoor[2] = int(input("phi: "))
setcoorByte = coor2bytes(setCoor)
clientsocket.send(bytes([2]))
clientsocket.send(bytes(setcoorByte))
print("I already sent the new coordinate.")
except Exception:
print("Error.")
else:
print("Not yet implement.")
Arduino:
#include <WiFi101.h>
#include <SPI.h>
// To connect to the server on laptop
char ssid[] = "iPhone";
char pass[] = "00000000";
int status = WL_IDLE_STATUS;
IPAddress server(172,20,10,3);
WiFiClient client;
// Random variable
int a, i, j, k, m;
byte buf0[7];
byte buf1[7];
byte buf2[7];
long start = millis();
int elapsedTime = 0;
int timeout = 0;
void setup() {
// put your setup code here, to run once:
// Serial.begin(115200);
Serial.begin(115200);
Serial1.begin(115200);
// status = WiFi.begin(ssid, pass);
while (status != WL_CONNECTED) {
status = WiFi.begin(ssid, pass);
}
j = client.connect(server, 1234);
while (j != 1) {
j = client.connect(server, 1234);
}
}
void loop()
{
if (client.available()) {
a = client.read();
Serial.print("I got: ");
Serial.println(a);
if (a == 0) { // Send new target to Due
Serial.println("I send target.");
j = 0;
start = millis();
while(j<6) {
elapsedTime = millis() - start;
if (elapsedTime > 1000) {
timeout = 1;
break;
}
if (client.available()>0) {
buf0[j] = client.read();
Serial.println(buf0[j]);
j++;
}
}
if (timeout != 1) {
Serial1.write((byte) 0);
// Send coordinate back to Due
for (i = 0; i<6; i++) {
Serial1.write(buf0[i]);
}
} else {
timeout = 0;
}
} else if (a == 1) {
// Get the coordinate from the Due
Serial.println("I receive coordinate.");
Serial1.write((byte) 1);
k = 0;
start = millis();
while(k < 6) {
elapsedTime = millis() - start;
if (elapsedTime > 1000) {
timeout = 1;
break;
}
if (Serial1.available() > 0) {
buf1[k] = Serial1.read();
Serial.println(buf1[k]);
k++;
}
}
if (timeout != 1) {
for (i=0;i<6;i++) {
client.write(buf1[i]);
delay(10);
}
client.write((byte) 0); // fill in the blank size
delay(10);
client.write((byte) 0);
} else {
timeout = 0;
}
// for (int i = 0; i<8; i++) {
// client.write((byte) 0);
// }
} else if (a == 2) { // set the current coordinnate to be something else.
Serial.println("I set coordinate.");
m = 0;
while(m<6) {
if (client.available()>0) {
buf2[m] = client.read();
Serial.println(buf2[m]);
m++;
}
}
Serial1.write((byte) 2);
// Send coordinate back to Due
for (i = 0; i<6; i++) {
Serial1.write(buf2[i]);
}
} else if (a == 3) { // identify yourself
Serial.println("Identify myself.");
client.write((byte) 1);
}
}
}
If you have time to read through the Arduino code, then you would see that I actually have serial communication between my MKR and Due too. I also can guarantee that the MKR can receive all those data from the Due and not stuck in some infinite loop.
Thank you!
Ok so for some reason if I added a delay right after the MKR connecting to WiFi, before connecting to the server, then everything just works.

Rewrite c++ text encoder to python

I have the following code in c++:
for(const char *x = r.ptr, *end = r.ptr + r.len; x != end; ++x) {
switch(*x) {
case 0x5c:
case 0x22:
pc->output[0] = '\\'; pc->output[1] = *x; pc->output += 2;
break;
case 0xa:
pc->output[0] = '\\'; pc->output[1] = 'n'; pc->output += 2;
break;
case 0xd:
pc->output[0] = '\\'; pc->output[1] = 'r'; pc->output += 2;
break;
default:
if(str_escape_2_hex(*x)) {
impl::escape_char_hex(pc->output, *x);
} else {
*pc->output = *x; pc->output++;
}
}
}
And I want to rewrite it to python 2 because I need the same encoder there. I tried with this:
def encode_akv_fields(data):
hexlify = codecs.getencoder('hex')
for i, el in enumerate(str(data)):
if hexlify(el)[0] in ('5c', '22'): # \\ or "
data[i].encode('hex') = '\\' + hexlify(el)[0]
elif hexlify(el)[0] == '0a': # \n
data[i].encode('hex') = '\\n'
elif hexlify(el)[0] == '0d': # \r
data[i].encode('hex') = '\\r'
elif '1f' >= hexlify(el)[0] >= '7f':
tmp3 = (hexlify(el)[0] >> 4) & '0f'.decode('hex')
data[i].encode('hex') = '\\x'
return data
but it doesn't work - I got
SyntaxError: can't assign to function call
Data is a string or dict with values that I want to log. Those logs needs to be in AKV format (Apache key value). And for this to work I need some hex values to be encoded like it is in c++ (the code in c++ works).
How should I create the same encoder in python as I did in c++?

python RSA implemention with PKCS1

I got the following code in javascript for RSA implementionhttp://www-cs-students.stanford.edu/~tjw/jsbn/:
// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
function RSAEncrypt(text) {
var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
if(m == null) return null;
var c = this.doPublic(m);
if(c == null) return null;
var h = c.toString(16);
if((h.length & 1) == 0) return h; else return "0" + h;
}
// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
function pkcs1pad2(s,n) {
if(n < s.length + 11) { // TODO: fix for utf-8
alert("Message too long for RSA");
return null;
}
var ba = new Array();
var i = s.length - 1;
while(i >= 0 && n > 0) {
var c = s.charCodeAt(i--);
if(c < 128) { // encode using utf-8
ba[--n] = c;
}
else if((c > 127) && (c < 2048)) {
ba[--n] = (c & 63) | 128;
ba[--n] = (c >> 6) | 192;
}
else {
ba[--n] = (c & 63) | 128;
ba[--n] = ((c >> 6) & 63) | 128;
ba[--n] = (c >> 12) | 224;
}
}
ba[--n] = 0;
var rng = new SecureRandom();
var x = new Array();
while(n > 2) { // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];
}
ba[--n] = 2;
ba[--n] = 0;
return new BigInteger(ba);
}
In the snippets above, it seems that the pkcs1pad2 function is used for padding the message with some random bytes(maybe sth like 0|2|random|0 ) in front of the message.
I'm using the python rsa package (http://stuvel.eu/rsa) for imitating the javascript result, i'm a newbie to python world and have no idea to traslate javascript algorithm code to the python code.
Any help would be appreciated.
Jiee
I know it's a bit late, but in a few days I'll release a new version of my Python-RSA package. That version will include PKCS#1 v1.5 padding, so it should be compatible with your JavaScript code ;-)

Categories