From 78ddb2f2f2b96fd62243403b2e74001e8e4b083e Mon Sep 17 00:00:00 2001 From: coffeedogs Date: Wed, 10 Oct 2018 13:00:53 +0100 Subject: [PATCH] Changes based on style and lint checks. (final_code_quality_12) --- {src => examples}/api_client.py | 0 src/addresses.py | 68 ++++++++++-------- src/bitmessageqt/address_dialogs.py | 46 ++++++++---- src/class_smtpDeliver.py | 37 ++++++---- src/fallback/umsgpack/umsgpack.py | 26 ++++--- src/pyelliptic/ecc.py | 107 +++++++++++++++++----------- src/randomtrackingdict.py | 54 +++++++++----- 7 files changed, 216 insertions(+), 122 deletions(-) rename {src => examples}/api_client.py (100%) diff --git a/src/api_client.py b/examples/api_client.py similarity index 100% rename from src/api_client.py rename to examples/api_client.py diff --git a/src/addresses.py b/src/addresses.py index ed07436f..510b0ce6 100644 --- a/src/addresses.py +++ b/src/addresses.py @@ -1,20 +1,28 @@ +""" +src/addresses.py +================ + +""" +# pylint: disable=redefined-outer-name,inconsistent-return-statements + +from __future__ import print_function import hashlib -from struct import pack, unpack -from pyelliptic import arithmetic from binascii import hexlify, unhexlify +from struct import pack, unpack from debug import logger +from pyelliptic import arithmetic -# There is another copy of this function in Bitmessagemain.py def convertIntToString(n): + """.. todo:: There is another copy of this function in Bitmessagemain.py""" a = __builtins__.hex(n) if a[-1:] == 'L': a = a[:-1] - if (len(a) % 2) == 0: + if len(a) % 2 == 0: return unhexlify(a[2:]) - else: - return unhexlify('0'+a[2:]) + return unhexlify('0' + a[2:]) + ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" @@ -25,7 +33,7 @@ def encodeBase58(num, alphabet=ALPHABET): `num`: The number to encode `alphabet`: The alphabet to use for encoding """ - if (num == 0): + if num == 0: return alphabet[0] arr = [] base = len(alphabet) @@ -59,6 +67,7 @@ def decodeBase58(string, alphabet=ALPHABET): def encodeVarint(integer): + """Convert integer into varint bytes""" if integer < 0: logger.error('varint cannot be < 0') raise SystemExit @@ -76,6 +85,7 @@ def encodeVarint(integer): class varintDecodeError(Exception): + """Exception class for decoding varint data""" pass @@ -87,7 +97,7 @@ def decodeVarint(data): Returns a tuple: (theEncodedValue, theSizeOfTheVarintInBytes) """ - if len(data) == 0: + if not data: return (0, 0) firstByte, = unpack('>B', data[0:1]) if firstByte < 253: @@ -135,6 +145,7 @@ def decodeVarint(data): def calculateInventoryHash(data): + """Calculate inventory hash from object data""" sha = hashlib.new('sha512') sha2 = hashlib.new('sha512') sha.update(data) @@ -143,6 +154,7 @@ def calculateInventoryHash(data): def encodeAddress(version, stream, ripe): + """Convert ripe to address""" if version >= 2 and version < 4: if len(ripe) != 20: raise Exception( @@ -175,8 +187,11 @@ def encodeAddress(version, stream, ripe): def decodeAddress(address): - # returns (status, address version number, stream number, - # data (almost certainly a ripe hash)) + """ + returns (status, address version number, stream number, + data (almost certainly a ripe hash)) + """ + # pylint: disable=too-many-return-statements,too-many-statements,too-many-return-statements,too-many-branches address = str(address).strip() @@ -194,24 +209,18 @@ def decodeAddress(address): if len(hexdata) % 2 != 0: hexdata = '0' + hexdata - # print 'hexdata', hexdata - data = unhexlify(hexdata) checksum = data[-4:] sha = hashlib.new('sha512') sha.update(data[:-4]) currentHash = sha.digest() - # print 'sha after first hashing: ', sha.hexdigest() sha = hashlib.new('sha512') sha.update(currentHash) - # print 'sha after second hashing: ', sha.hexdigest() if checksum != sha.digest()[0:4]: status = 'checksumfailed' return status, 0, 0, '' - # else: - # print 'checksum PASSED' try: addressVersionNumber, bytesUsedByVersionNumber = decodeVarint(data[:9]) @@ -219,8 +228,6 @@ def decodeAddress(address): logger.error(str(e)) status = 'varintmalformed' return status, 0, 0, '' - # print 'addressVersionNumber', addressVersionNumber - # print 'bytesUsedByVersionNumber', bytesUsedByVersionNumber if addressVersionNumber > 4: logger.error('cannot decode address version numbers this high') @@ -233,36 +240,35 @@ def decodeAddress(address): try: streamNumber, bytesUsedByStreamNumber = \ - decodeVarint(data[bytesUsedByVersionNumber:]) + decodeVarint(data[bytesUsedByVersionNumber:]) except varintDecodeError as e: logger.error(str(e)) status = 'varintmalformed' return status, 0, 0, '' - # print streamNumber + status = 'success' if addressVersionNumber == 1: return status, addressVersionNumber, streamNumber, data[-24:-4] elif addressVersionNumber == 2 or addressVersionNumber == 3: embeddedRipeData = \ - data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4] + data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4] if len(embeddedRipeData) == 19: return status, addressVersionNumber, streamNumber, \ - '\x00'+embeddedRipeData + '\x00' + embeddedRipeData elif len(embeddedRipeData) == 20: return status, addressVersionNumber, streamNumber, \ - embeddedRipeData + embeddedRipeData elif len(embeddedRipeData) == 18: return status, addressVersionNumber, streamNumber, \ - '\x00\x00' + embeddedRipeData + '\x00\x00' + embeddedRipeData elif len(embeddedRipeData) < 18: return 'ripetooshort', 0, 0, '' elif len(embeddedRipeData) > 20: return 'ripetoolong', 0, 0, '' - else: - return 'otherproblem', 0, 0, '' + return 'otherproblem', 0, 0, '' elif addressVersionNumber == 4: embeddedRipeData = \ - data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4] + data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4] if embeddedRipeData[0:1] == '\x00': # In order to enforce address non-malleability, encoded # RIPE data must have NULL bytes removed from the front @@ -271,13 +277,13 @@ def decodeAddress(address): return 'ripetoolong', 0, 0, '' elif len(embeddedRipeData) < 4: return 'ripetooshort', 0, 0, '' - else: - x00string = '\x00' * (20 - len(embeddedRipeData)) - return status, addressVersionNumber, streamNumber, \ - x00string + embeddedRipeData + x00string = '\x00' * (20 - len(embeddedRipeData)) + return status, addressVersionNumber, streamNumber, \ + x00string + embeddedRipeData def addBMIfNotPresent(address): + """Prepend BM- to an address if it doesn't already have it""" address = str(address).strip() return address if address[:3] == 'BM-' else 'BM-' + address diff --git a/src/bitmessageqt/address_dialogs.py b/src/bitmessageqt/address_dialogs.py index 2ea5cef8..60c10369 100644 --- a/src/bitmessageqt/address_dialogs.py +++ b/src/bitmessageqt/address_dialogs.py @@ -1,29 +1,39 @@ +""" +src/bitmessageqt/address_dialogs.py +=================================== + +""" +# pylint: disable=attribute-defined-outside-init + +import hashlib + from PyQt4 import QtCore, QtGui -from addresses import decodeAddress, encodeVarint, addBMIfNotPresent -from account import ( - GatewayAccount, MailchuckAccount, AccountMixin, accountClass, - getSortedAccounts -) -from tr import _translate -from retranslateui import RetranslateMixin -import widgets import queues -import hashlib +import widgets +from account import AccountMixin, GatewayAccount, MailchuckAccount, accountClass, getSortedAccounts +from addresses import addBMIfNotPresent, decodeAddress, encodeVarint from inventory import Inventory +from retranslateui import RetranslateMixin +from tr import _translate class AddressCheckMixin(object): + """Base address validation class for QT UI""" + # pylint: disable=too-few-public-methods def __init__(self): self.valid = False - QtCore.QObject.connect(self.lineEditAddress, QtCore.SIGNAL( - "textChanged(QString)"), self.addressChanged) + QtCore.QObject.connect( # pylint: disable=no-member + self.lineEditAddress, + QtCore.SIGNAL("textChanged(QString)"), + self.addressChanged) def _onSuccess(self, addressVersion, streamNumber, ripe): pass def addressChanged(self, QString): + """Address validation callback, performs validation and gives feedback""" status, addressVersion, streamNumber, ripe = decodeAddress( str(QString)) self.valid = status == 'success' @@ -71,11 +81,14 @@ class AddressCheckMixin(object): class AddressDataDialog(QtGui.QDialog, AddressCheckMixin): + """QDialog with Bitmessage address validation""" + def __init__(self, parent): super(AddressDataDialog, self).__init__(parent) self.parent = parent def accept(self): + """Callback for QDIalog accepting value""" if self.valid: self.data = ( addBMIfNotPresent(str(self.lineEditAddress.text())), @@ -90,6 +103,7 @@ class AddressDataDialog(QtGui.QDialog, AddressCheckMixin): class AddAddressDialog(AddressDataDialog, RetranslateMixin): + """QDialog for adding a new address, with validation and translation""" def __init__(self, parent=None, address=None): super(AddAddressDialog, self).__init__(parent) @@ -100,6 +114,7 @@ class AddAddressDialog(AddressDataDialog, RetranslateMixin): class NewAddressDialog(QtGui.QDialog, RetranslateMixin): + """QDialog for generating a new address, with translation""" def __init__(self, parent=None): super(NewAddressDialog, self).__init__(parent) @@ -115,6 +130,7 @@ class NewAddressDialog(QtGui.QDialog, RetranslateMixin): self.show() def accept(self): + """accept callback""" self.hide() # self.buttonBox.enabled = False if self.radioButtonRandomAddress.isChecked(): @@ -160,6 +176,7 @@ class NewAddressDialog(QtGui.QDialog, RetranslateMixin): class NewSubscriptionDialog(AddressDataDialog, RetranslateMixin): + """QDialog for subscribing to an address, with validation and translation""" def __init__(self, parent=None): super(NewSubscriptionDialog, self).__init__(parent) @@ -202,6 +219,7 @@ class NewSubscriptionDialog(AddressDataDialog, RetranslateMixin): class RegenerateAddressesDialog(QtGui.QDialog, RetranslateMixin): + """QDialog for regenerating deterministic addresses, with translation""" def __init__(self, parent=None): super(RegenerateAddressesDialog, self).__init__(parent) widgets.load('regenerateaddresses.ui', self) @@ -210,6 +228,7 @@ class RegenerateAddressesDialog(QtGui.QDialog, RetranslateMixin): class SpecialAddressBehaviorDialog(QtGui.QDialog, RetranslateMixin): + """QDialog for special address behaviour (e.g. mailing list functionality), with translation""" def __init__(self, parent=None, config=None): super(SpecialAddressBehaviorDialog, self).__init__(parent) @@ -250,6 +269,7 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog, RetranslateMixin): self.show() def accept(self): + """Accept callback""" self.hide() if self.address_is_chan: return @@ -267,7 +287,7 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog, RetranslateMixin): self.config.set(str(self.address), 'mailinglistname', str( self.lineEditMailingListName.text().toUtf8())) self.parent.setCurrentItemColor( - QtGui.QColor(137, 04, 177)) # magenta + QtGui.QColor(137, 4, 177)) # magenta self.parent.rerenderComboBoxSendFrom() self.parent.rerenderComboBoxSendFromBroadcast() self.config.save() @@ -275,6 +295,7 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog, RetranslateMixin): class EmailGatewayDialog(QtGui.QDialog, RetranslateMixin): + """QDialog for email gateway control, with translation""" def __init__(self, parent, config=None, account=None): super(EmailGatewayDialog, self).__init__(parent) widgets.load('emailgateway.ui', self) @@ -315,6 +336,7 @@ class EmailGatewayDialog(QtGui.QDialog, RetranslateMixin): QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) def accept(self): + """Accept callback""" self.hide() # no chans / mailinglists if self.acct.type != AccountMixin.NORMAL: diff --git a/src/class_smtpDeliver.py b/src/class_smtpDeliver.py index f46a61b3..ef7a4363 100644 --- a/src/class_smtpDeliver.py +++ b/src/class_smtpDeliver.py @@ -1,52 +1,59 @@ -from email.mime.text import MIMEText -from email.header import Header +""" +src/class_smtpDeliver.py +======================== +""" +# pylint: disable=unused-variable + import smtplib import sys import threading import urlparse +from email.header import Header +from email.mime.text import MIMEText -from bmconfigparser import BMConfigParser -from debug import logger -from helper_threading import * import queues import state +from bmconfigparser import BMConfigParser +from debug import logger +from helper_threading import StoppableThread SMTPDOMAIN = "bmaddr.lan" + class smtpDeliver(threading.Thread, StoppableThread): + """SMTP client thread for delivery""" _instance = None - def __init__(self, parent=None): + def __init__(self): threading.Thread.__init__(self, name="smtpDeliver") self.initStop() def stopThread(self): try: - queues.UISignallerQueue.put(("stopThread", "data")) + queues.UISignallerQueue.put(("stopThread", "data")) # pylint: disable=no-member except: pass super(smtpDeliver, self).stopThread() @classmethod def get(cls): + """(probably) Singleton functionality""" if not cls._instance: cls._instance = smtpDeliver() return cls._instance def run(self): + # pylint: disable=too-many-branches,too-many-statements,too-many-locals while state.shutdown == 0: command, data = queues.UISignalQueue.get() if command == 'writeNewAddressToTable': label, address, streamNumber = data - pass elif command == 'updateStatusBar': pass elif command == 'updateSentItemStatusByToAddress': toAddress, message = data - pass elif command == 'updateSentItemStatusByAckdata': ackData, message = data - pass elif command == 'displayNewInboxMessage': inventoryHash, toAddress, fromAddress, subject, body = data dest = BMConfigParser().safeGet("bitmessagesettings", "smtpdeliver", '') @@ -59,8 +66,12 @@ class smtpDeliver(threading.Thread, StoppableThread): msg = MIMEText(body, 'plain', 'utf-8') msg['Subject'] = Header(subject, 'utf-8') msg['From'] = fromAddress + '@' + SMTPDOMAIN - toLabel = map (lambda y: BMConfigParser().safeGet(y, "label"), filter(lambda x: x == toAddress, BMConfigParser().addresses())) - if len(toLabel) > 0: + toLabel = map( # pylint: disable=deprecated-lambda + lambda y: BMConfigParser().safeGet(y, "label"), + filter( # pylint: disable=deprecated-lambda + lambda x: x == toAddress, BMConfigParser().addresses()) + ) + if toLabel: msg['To'] = "\"%s\" <%s>" % (Header(toLabel[0], 'utf-8'), toAddress + '@' + SMTPDOMAIN) else: msg['To'] = toAddress + '@' + SMTPDOMAIN @@ -74,7 +85,6 @@ class smtpDeliver(threading.Thread, StoppableThread): logger.error("smtp delivery error", exc_info=True) elif command == 'displayNewSentMessage': toAddress, fromLabel, fromAddress, subject, message, ackdata = data - pass elif command == 'updateNetworkStatusTab': pass elif command == 'updateNumberOfMessagesProcessed': @@ -103,7 +113,6 @@ class smtpDeliver(threading.Thread, StoppableThread): pass elif command == 'alert': title, text, exitAfterUserClicksOk = data - pass elif command == 'stopThread': break else: diff --git a/src/fallback/umsgpack/umsgpack.py b/src/fallback/umsgpack/umsgpack.py index d196b7f8..34938614 100644 --- a/src/fallback/umsgpack/umsgpack.py +++ b/src/fallback/umsgpack/umsgpack.py @@ -31,6 +31,9 @@ # THE SOFTWARE. # """ +src/fallback/umsgpack/umsgpack.py +================================= + u-msgpack-python v2.4.1 - v at sergeev.io https://github.com/vsergeev/u-msgpack-python @@ -43,10 +46,13 @@ types. License: MIT """ -import struct +# pylint: disable=too-many-lines,too-many-branches,too-many-statements,global-statement,too-many-return-statements +# pylint: disable=unused-argument + import collections -import sys import io +import struct +import sys __version__ = "2.4.1" "Module version string" @@ -60,7 +66,7 @@ version = (2, 4, 1) ############################################################################## # Extension type for application-defined types and data -class Ext: +class Ext: # pylint: disable=old-style-class """ The Ext class facilitates creating a serializable extension object to store an application-defined type and data byte array. @@ -87,6 +93,8 @@ class Ext: Ext Object (Type: 0x05, Data: 01 02 03) >>> """ + # pylint:disable=redefined-builtin + # Application ext type should be 0 <= type <= 127 if not isinstance(type, int) or not (type >= 0 and type <= 127): raise TypeError("ext type out of range") @@ -412,7 +420,7 @@ def _pack2(obj, fp, **options): _pack_ext(ext_handlers[obj.__class__](obj), fp, options) elif isinstance(obj, bool): _pack_boolean(obj, fp, options) - elif isinstance(obj, int) or isinstance(obj, long): + elif isinstance(obj, (int, long)): _pack_integer(obj, fp, options) elif isinstance(obj, float): _pack_float(obj, fp, options) @@ -424,7 +432,7 @@ def _pack2(obj, fp, **options): _pack_string(obj, fp, options) elif isinstance(obj, str): _pack_binary(obj, fp, options) - elif isinstance(obj, list) or isinstance(obj, tuple): + elif isinstance(obj, (list, tuple)): _pack_array(obj, fp, options) elif isinstance(obj, dict): _pack_map(obj, fp, options) @@ -494,7 +502,7 @@ def _pack3(obj, fp, **options): _pack_string(obj, fp, options) elif isinstance(obj, bytes): _pack_binary(obj, fp, options) - elif isinstance(obj, list) or isinstance(obj, tuple): + elif isinstance(obj, (list, tuple)): _pack_array(obj, fp, options) elif isinstance(obj, dict): _pack_map(obj, fp, options) @@ -723,7 +731,7 @@ def _unpack_array(code, fp, options): else: raise Exception("logic error, not array: 0x%02x" % ord(code)) - return [_unpack(fp, options) for i in xrange(length)] + return [_unpack(fp, options) for _ in xrange(length)] def _deep_list_to_tuple(obj): @@ -957,6 +965,8 @@ def _unpackb3(s, **options): def __init(): + # pylint: disable=global-variable-undefined + global pack global packb global unpack @@ -989,7 +999,7 @@ def __init(): unpackb = _unpackb3 load = _unpack3 loads = _unpackb3 - xrange = range + xrange = range # pylint: disable=redefined-builtin else: pack = _pack2 packb = _packb2 diff --git a/src/pyelliptic/ecc.py b/src/pyelliptic/ecc.py index 9395a855..fb0d6773 100644 --- a/src/pyelliptic/ecc.py +++ b/src/pyelliptic/ecc.py @@ -1,17 +1,23 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +""" +src/pyelliptic/ecc.py +===================== +""" +# pylint: disable=protected-access # Copyright (C) 2011 Yann GUIBET # See LICENSE for details. from hashlib import sha512 -from pyelliptic.openssl import OpenSSL -from pyelliptic.cipher import Cipher -from pyelliptic.hash import hmac_sha256, equals from struct import pack, unpack +from pyelliptic.cipher import Cipher +from pyelliptic.hash import equals, hmac_sha256 +from pyelliptic.openssl import OpenSSL -class ECC: + +class ECC(object): """ Asymmetric encryption with Elliptic Curve Cryptography (ECC) ECDH, ECDSA and ECIES @@ -40,13 +46,21 @@ class ECC: >>> print bob.get_ecdh_key(alice.get_pubkey()).encode('hex') """ - def __init__(self, pubkey=None, privkey=None, pubkey_x=None, - pubkey_y=None, raw_privkey=None, curve='sect283r1'): + + def __init__( + self, + pubkey=None, + privkey=None, + pubkey_x=None, + pubkey_y=None, + raw_privkey=None, + curve='sect283r1', + ): # pylint: disable=too-many-arguments """ For a normal and High level use, specifie pubkey, privkey (if you need) and the curve """ - if type(curve) == str: + if isinstance(curve, str): self.curve = OpenSSL.get_curve(curve) else: self.curve = curve @@ -54,9 +68,9 @@ class ECC: if pubkey_x is not None and pubkey_y is not None: self._set_keys(pubkey_x, pubkey_y, raw_privkey) elif pubkey is not None: - curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey) + curve, pubkey_x, pubkey_y, _ = ECC._decode_pubkey(pubkey) if privkey is not None: - curve2, raw_privkey, i = ECC._decode_privkey(privkey) + curve2, raw_privkey, _ = ECC._decode_privkey(privkey) if curve != curve2: raise Exception("Bad ECC keys ...") self.curve = curve @@ -83,9 +97,11 @@ class ECC: return OpenSSL.curves.keys() def get_curve(self): + """Encryption object from curve name""" return OpenSSL.get_curve_by_id(self.curve) def get_curve_id(self): + """Currently used curve""" return self.curve def get_pubkey(self): @@ -93,22 +109,24 @@ class ECC: High level function which returns : curve(2) + len_of_pubkeyX(2) + pubkeyX + len_of_pubkeyY + pubkeyY """ - return b''.join((pack('!H', self.curve), - pack('!H', len(self.pubkey_x)), - self.pubkey_x, - pack('!H', len(self.pubkey_y)), - self.pubkey_y - )) + return b''.join(( + pack('!H', self.curve), + pack('!H', len(self.pubkey_x)), + self.pubkey_x, + pack('!H', len(self.pubkey_y)), + self.pubkey_y, + )) def get_privkey(self): """ High level function which returns curve(2) + len_of_privkey(2) + privkey """ - return b''.join((pack('!H', self.curve), - pack('!H', len(self.privkey)), - self.privkey - )) + return b''.join(( + pack('!H', self.curve), + pack('!H', len(self.privkey)), + self.privkey, + )) @staticmethod def _decode_pubkey(pubkey): @@ -153,12 +171,9 @@ class ECC: group = OpenSSL.EC_KEY_get0_group(key) pub_key = OpenSSL.EC_KEY_get0_public_key(key) - if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, pub_key, - pub_key_x, - pub_key_y, 0 - )) == 0: - raise Exception( - "[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ...") + if OpenSSL.EC_POINT_get_affine_coordinates_GFp( + group, pub_key, pub_key_x, pub_key_y, 0) == 0: + raise Exception("[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ...") privkey = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(priv_key)) pubkeyx = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_x)) @@ -183,12 +198,13 @@ class ECC: High level function. Compute public key with the local private key and returns a 512bits shared key """ - curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey) + curve, pubkey_x, pubkey_y, _ = ECC._decode_pubkey(pubkey) if curve != self.curve: raise Exception("ECC keys must be from the same curve !") return sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() def raw_get_ecdh_key(self, pubkey_x, pubkey_y): + """ECDH key as binary data""" try: ecdh_keybuffer = OpenSSL.malloc(0, 32) @@ -248,20 +264,22 @@ class ECC: Check the public key and the private key. The private key is optional (replace by None) """ - curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey) + curve, pubkey_x, pubkey_y, _ = ECC._decode_pubkey(pubkey) if privkey is None: raw_privkey = None curve2 = curve else: - curve2, raw_privkey, i = ECC._decode_privkey(privkey) + curve2, raw_privkey, _ = ECC._decode_privkey(privkey) if curve != curve2: raise Exception("Bad public and private key") return self.raw_check_key(raw_privkey, pubkey_x, pubkey_y, curve) def raw_check_key(self, privkey, pubkey_x, pubkey_y, curve=None): + """Check key validity, key is supplied as binary data""" + # pylint: disable=too-many-branches if curve is None: curve = self.curve - elif type(curve) == str: + elif isinstance(curve, str): curve = OpenSSL.get_curve(curve) else: curve = curve @@ -306,6 +324,7 @@ class ECC: """ Sign the input with ECDSA method and returns the signature """ + # pylint: disable=too-many-branches,too-many-locals try: size = len(inputb) buff = OpenSSL.malloc(inputb, size) @@ -369,13 +388,13 @@ class ECC: OpenSSL.EVP_MD_CTX_free(md_ctx) else: OpenSSL.EVP_MD_CTX_destroy(md_ctx) - pass def verify(self, sig, inputb, digest_alg=OpenSSL.digest_ecdsa_sha1): """ Verify the signature with the input and the local public key. Returns a boolean """ + # pylint: disable=too-many-branches try: bsig = OpenSSL.malloc(sig, len(sig)) binputb = OpenSSL.malloc(inputb, len(inputb)) @@ -419,12 +438,9 @@ class ECC: if ret == -1: return False # Fail to Check - else: - if ret == 0: - return False # Bad signature ! - else: - return True # Good - return False + if ret == 0: + return False # Bad signature ! + return True # Good finally: OpenSSL.EC_KEY_free(key) @@ -441,13 +457,21 @@ class ECC: """ Encrypt data with ECIES method using the public key of the recipient. """ - curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey) + curve, pubkey_x, pubkey_y, _ = ECC._decode_pubkey(pubkey) return ECC.raw_encrypt(data, pubkey_x, pubkey_y, curve=curve, ephemcurve=ephemcurve, ciphername=ciphername) @staticmethod - def raw_encrypt(data, pubkey_x, pubkey_y, curve='sect283r1', - ephemcurve=None, ciphername='aes-256-cbc'): + def raw_encrypt( + data, + pubkey_x, + pubkey_y, + curve='sect283r1', + ephemcurve=None, + ciphername='aes-256-cbc', + ): # pylint: disable=too-many-arguments + """ECHD encryption, keys supplied in binary data format""" + if ephemcurve is None: ephemcurve = curve ephem = ECC(curve=ephemcurve) @@ -464,12 +488,13 @@ class ECC: """ Decrypt data with ECIES method using the local private key """ + # pylint: disable=too-many-locals blocksize = OpenSSL.get_cipher(ciphername).get_blocksize() iv = data[:blocksize] i = blocksize - curve, pubkey_x, pubkey_y, i2 = ECC._decode_pubkey(data[i:]) + _, pubkey_x, pubkey_y, i2 = ECC._decode_pubkey(data[i:]) i += i2 - ciphertext = data[i:len(data)-32] + ciphertext = data[i:len(data) - 32] i += len(ciphertext) mac = data[i:] key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest() diff --git a/src/randomtrackingdict.py b/src/randomtrackingdict.py index 2bd6e257..4d85708f 100644 --- a/src/randomtrackingdict.py +++ b/src/randomtrackingdict.py @@ -1,12 +1,29 @@ +""" +src/randomtrackingdict.py +========================= +""" + import random from threading import RLock from time import time + import helper_random + class RandomTrackingDict(object): + """ + Dict with randomised order and tracking. + + Keeps a track of how many items have been requested from the dict, and timeouts. Resets after all objects have been + retrieved and timed out. The main purpose of this isn't as much putting related code together as performance + optimisation and anonymisation of downloading of objects from other peers. If done using a standard dict or array, + it takes too much CPU (and looks convoluted). Randomisation helps with anonymity. + """ + # pylint: disable=too-many-instance-attributes maxPending = 10 pendingTimeout = 60 - def __init__(self): # O(1) + + def __init__(self): self.dictionary = {} self.indexDict = [] self.len = 0 @@ -46,7 +63,7 @@ class RandomTrackingDict(object): self.len += 1 def __delitem__(self, key): - if not key in self.dictionary: + if key not in self.dictionary: raise KeyError with self.lock: index = self.dictionary[key][0] @@ -67,9 +84,14 @@ class RandomTrackingDict(object): self.len -= 1 def setMaxPending(self, maxPending): + """ + Sets maximum number of objects that can be retrieved from the class simultaneously as long as there is no + timeout + """ self.maxPending = maxPending def setPendingTimeout(self, pendingTimeout): + """Sets how long to wait for a timeout if max pending is reached (or all objects have been retrieved)""" self.pendingTimeout = pendingTimeout def setLastObject(self): @@ -77,10 +99,13 @@ class RandomTrackingDict(object): self.lastObject = time() def randomKeys(self, count=1): + """Retrieve count random keys from the dict that haven't already been retrieved""" if self.len == 0 or ((self.pendingLen >= self.maxPending or - self.pendingLen == self.len) and self.lastPoll + - self.pendingTimeout > time()): + self.pendingLen == self.len) and self.lastPoll + + self.pendingTimeout > time()): raise KeyError + + # pylint: disable=redefined-outer-name with self.lock: # reset if we've requested all # or if last object received too long time ago @@ -99,43 +124,40 @@ class RandomTrackingDict(object): self.lastPoll = time() return retval + if __name__ == '__main__': + + # pylint: disable=redefined-outer-name def randString(): + """helper function for tests, generates a random string""" retval = b'' for _ in range(32): - retval += chr(random.randint(0,255)) + retval += chr(random.randint(0, 255)) return retval a = [] k = RandomTrackingDict() d = {} - -# print "populating normal dict" -# a.append(time()) -# for i in range(50000): -# d[randString()] = True -# a.append(time()) + print "populating random tracking dict" a.append(time()) for i in range(50000): k[randString()] = True a.append(time()) print "done" - while len(k) > 0: + + while k: retval = k.randomKeys(1000) if not retval: print "error getting random keys" - #a.append(time()) try: k.randomKeys(100) print "bad" except KeyError: pass - #a.append(time()) for i in retval: del k[i] - #a.append(time()) a.append(time()) for x in range(len(a) - 1): - print "%i: %.3f" % (x, a[x+1] - a[x]) + print "%i: %.3f" % (x, a[x + 1] - a[x])