From 6a108f93e6170f4fec8cb6f5c6298960b5ae5542 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Sat, 28 May 2016 18:19:45 -0700 Subject: [PATCH] switch most everything to use new utility functions --- src/wormhole/cli/cmd_receive.py | 13 +++++------ src/wormhole/cli/cmd_send.py | 15 +++++++------ src/wormhole/server/rendezvous_websocket.py | 7 +++--- src/wormhole/wormhole.py | 24 ++++++++++----------- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/wormhole/cli/cmd_receive.py b/src/wormhole/cli/cmd_receive.py index 38a7afc..d421c5c 100644 --- a/src/wormhole/cli/cmd_receive.py +++ b/src/wormhole/cli/cmd_receive.py @@ -1,5 +1,5 @@ from __future__ import print_function -import os, sys, json, binascii, six, tempfile, zipfile, hashlib +import os, sys, six, tempfile, zipfile, hashlib from tqdm import tqdm from twisted.internet import reactor from twisted.internet.defer import inlineCallbacks, returnValue @@ -7,6 +7,7 @@ from twisted.python import log from ..wormhole import wormhole from ..transit import TransitReceiver from ..errors import TransferError, WormholeClosedError +from ..util import dict_to_bytes, bytes_to_dict, bytes_to_hexstr APPID = u"lothar.com/wormhole/text-or-file-xfer" @@ -100,14 +101,14 @@ class TwistedReceiver: log.msg("unrecognized message %r" % (them_d,)) def _send_data(self, data, w): - data_bytes = json.dumps(data).encode("utf-8") + data_bytes = dict_to_bytes(data) w.send(data_bytes) @inlineCallbacks def _get_data(self, w): # this may raise WrongPasswordError them_bytes = yield w.get() - them_d = json.loads(them_bytes.decode("utf-8")) + them_d = bytes_to_dict(them_bytes) if "error" in them_d: raise TransferError(them_d["error"]) returnValue(them_d) @@ -125,7 +126,7 @@ class TwistedReceiver: self.args.code_length) def _show_verifier(self, verifier): - verifier_hex = binascii.hexlify(verifier).decode("ascii") + verifier_hex = bytes_to_hexstr(verifier) if self.args.verify: self._msg(u"Verifier %s." % verifier_hex) @@ -298,9 +299,9 @@ class TwistedReceiver: @inlineCallbacks def _close_transit(self, record_pipe, datahash): - datahash_hex = binascii.hexlify(datahash).decode("ascii") + datahash_hex = bytes_to_hexstr(datahash) ack = {u"ack": u"ok", u"sha256": datahash_hex} - ack_bytes = json.dumps(ack).encode("utf-8") + ack_bytes = dict_to_bytes(ack) with self.args.timing.add("send ack"): yield record_pipe.send_record(ack_bytes) yield record_pipe.close() diff --git a/src/wormhole/cli/cmd_send.py b/src/wormhole/cli/cmd_send.py index 2341115..672afb1 100644 --- a/src/wormhole/cli/cmd_send.py +++ b/src/wormhole/cli/cmd_send.py @@ -1,5 +1,5 @@ from __future__ import print_function -import os, sys, json, binascii, six, tempfile, zipfile, hashlib +import os, sys, six, tempfile, zipfile, hashlib from tqdm import tqdm from twisted.python import log from twisted.protocols import basic @@ -8,6 +8,7 @@ from twisted.internet.defer import inlineCallbacks, returnValue from ..errors import TransferError, WormholeClosedError from ..wormhole import wormhole from ..transit import TransitSender +from ..util import dict_to_bytes, bytes_to_dict, bytes_to_hexstr APPID = u"lothar.com/wormhole/text-or-file-xfer" @@ -52,7 +53,7 @@ class Sender: yield d def _send_data(self, data, w): - data_bytes = json.dumps(data).encode("utf-8") + data_bytes = dict_to_bytes(data) w.send(data_bytes) @inlineCallbacks @@ -86,14 +87,14 @@ class Sender: # TODO: don't stall on w.verify() unless they want it verifier_bytes = yield w.verify() # this may raise WrongPasswordError if args.verify: - verifier = binascii.hexlify(verifier_bytes).decode("ascii") + verifier = bytes_to_hexstr(verifier_bytes) while True: ok = six.moves.input("Verifier %s. ok? (yes/no): " % verifier) if ok.lower() == "yes": break if ok.lower() == "no": err = "sender rejected verification check, abandoned transfer" - reject_data = json.dumps({"error": err}).encode("utf-8") + reject_data = dict_to_bytes({"error": err}) w.send(reject_data) raise TransferError(err) @@ -131,7 +132,7 @@ class Sender: returnValue(None) raise TransferError("unexpected close") # TODO: get() fired, so now it's safe to use w.derive_key() - them_d = json.loads(them_d_bytes.decode("utf-8")) + them_d = bytes_to_dict(them_d_bytes) #print("GOT", them_d) recognized = False if u"error" in them_d: @@ -273,12 +274,12 @@ class Sender: transform=_count_and_hash) expected_hash = hasher.digest() - expected_hex = binascii.hexlify(expected_hash).decode("ascii") + expected_hex = bytes_to_hexstr(expected_hash) print(u"File sent.. waiting for confirmation", file=stdout) with self._timing.add("get ack") as t: ack_bytes = yield record_pipe.receive_record() record_pipe.close() - ack = json.loads(ack_bytes.decode("utf-8")) + ack = bytes_to_dict(ack_bytes) ok = ack.get(u"ack", u"") if ok != u"ok": t.detail(ack="failed") diff --git a/src/wormhole/server/rendezvous_websocket.py b/src/wormhole/server/rendezvous_websocket.py index dca5493..c824d43 100644 --- a/src/wormhole/server/rendezvous_websocket.py +++ b/src/wormhole/server/rendezvous_websocket.py @@ -1,8 +1,9 @@ -import json, time +import time from twisted.internet import reactor from twisted.python import log from autobahn.twisted import websocket from .rendezvous import CrowdedError, SidedMessage +from ..util import dict_to_bytes, bytes_to_dict # The WebSocket allows the client to send "commands" to the server, and the # server to send "responses" to the client. Note that commands and responses @@ -101,7 +102,7 @@ class WebSocketRendezvous(websocket.WebSocketServerProtocol): def onMessage(self, payload, isBinary): server_rx = time.time() - msg = json.loads(payload.decode("utf-8")) + msg = bytes_to_dict(payload) try: if "type" not in msg: raise Error("missing 'type'") @@ -227,7 +228,7 @@ class WebSocketRendezvous(websocket.WebSocketServerProtocol): def send(self, mtype, **kwargs): kwargs["type"] = mtype kwargs["server_tx"] = time.time() - payload = json.dumps(kwargs).encode("utf-8") + payload = dict_to_bytes(kwargs) self.sendMessage(payload, False) def onClose(self, wasClean, code, reason): diff --git a/src/wormhole/wormhole.py b/src/wormhole/wormhole.py index efc11c7..090e2dd 100644 --- a/src/wormhole/wormhole.py +++ b/src/wormhole/wormhole.py @@ -1,7 +1,6 @@ from __future__ import print_function, absolute_import -import os, sys, json, re +import os, sys, re from six.moves.urllib_parse import urlparse -from binascii import hexlify, unhexlify from twisted.internet import defer, endpoints, error from twisted.internet.threads import deferToThread, blockingCallFromThread from twisted.internet.defer import inlineCallbacks, returnValue @@ -18,7 +17,8 @@ from . import codes from .errors import (WrongPasswordError, UsageError, WelcomeError, WormholeClosedError) from .timing import DebugTiming -from .util import to_bytes +from .util import (to_bytes, bytes_to_hexstr, hexstr_to_bytes, + dict_to_bytes, bytes_to_dict) from hkdf import Hkdf def HKDF(skm, outlen, salt=None, CTXinfo=b""): @@ -223,7 +223,7 @@ class _Wormhole: self._welcomer = _WelcomeHandler(self._ws_url, __version__, self._signal_error) - self._side = hexlify(os.urandom(5)).decode("ascii") + self._side = bytes_to_hexstr(os.urandom(5)) self._connection_state = CLOSED self._connection_waiters = [] self._started_get_code = False @@ -398,14 +398,14 @@ class _Wormhole: # ACKs we get back from the server (which we otherwise ignore). There # are so few messages, 16 bits is enough to be mostly-unique. if self.DEBUG: print("SEND", mtype) - kwargs["id"] = hexlify(os.urandom(2)).decode("ascii") + kwargs["id"] = bytes_to_hexstr(os.urandom(2)) kwargs["type"] = mtype - payload = json.dumps(kwargs).encode("utf-8") + payload = dict_to_bytes(kwargs) self._timing.add("ws_send", _side=self._side, **kwargs) self._ws.sendMessage(payload, False) def _ws_dispatch_response(self, payload): - msg = json.loads(payload.decode("utf-8")) + msg = bytes_to_dict(payload) if self.DEBUG and msg["type"]!="ack": print("DIS", msg["type"], msg) self._timing.add("ws_receive", _side=self._side, message=msg) mtype = msg["type"] @@ -562,7 +562,7 @@ class _Wormhole: # this is encrypted like a normal phase message, and includes a # dictionary of version flags to let the other Wormhole know what # we're capable of (for future expansion) - plaintext = json.dumps(self._my_versions).encode("utf-8") + plaintext = dict_to_bytes(self._my_versions) phase = u"version" data_key = self._derive_phase_key(self._side, phase) encrypted = self._encrypt_data(data_key, plaintext) @@ -616,7 +616,7 @@ class _Wormhole: if self.DEBUG: print("CONFIRM FAILED") self._signal_error(WrongPasswordError(), u"scary") return - msg = json.loads(plaintext.decode("utf-8")) + msg = bytes_to_dict(plaintext) self._version_received(msg) self._maybe_notify_verify() @@ -681,9 +681,7 @@ class _Wormhole: # TODO: retry on failure, with exponential backoff. We're guarding # against the rendezvous server being temporarily offline. self._timing.add("add", phase=phase) - self._ws_send_command(u"add", phase=phase, - body=hexlify(body).decode("ascii")) - + self._ws_send_command(u"add", phase=phase, body=bytes_to_hexstr(body)) def _event_mailbox_used(self): if self.DEBUG: print("_event_mailbox_used") @@ -708,7 +706,7 @@ class _Wormhole: side = msg["side"] phase = msg["phase"] assert isinstance(phase, type(u"")), type(phase) - body = unhexlify(msg["body"].encode("ascii")) + body = hexstr_to_bytes(msg["body"]) if side == self._side: return self._event_received_peer_message(side, phase, body)