Merge pull request #1370 from coffeedogs/final_code_quality_12

Changes based on style and lint checks. Some empty docstrings remain …
This commit is contained in:
coffeedogs 2018-10-31 17:03:59 +00:00 committed by GitHub
commit 283154e508
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 216 additions and 122 deletions

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -1,17 +1,23 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
src/pyelliptic/ecc.py
=====================
"""
# pylint: disable=protected-access
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
# 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()

View File

@ -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])