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:
commit
283154e508
|
@ -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')
|
||||
|
@ -238,7 +245,7 @@ def decodeAddress(address):
|
|||
logger.error(str(e))
|
||||
status = 'varintmalformed'
|
||||
return status, 0, 0, ''
|
||||
# print streamNumber
|
||||
|
||||
status = 'success'
|
||||
if addressVersionNumber == 1:
|
||||
return status, addressVersionNumber, streamNumber, data[-24:-4]
|
||||
|
@ -247,7 +254,7 @@ def decodeAddress(address):
|
|||
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
|
||||
|
@ -258,7 +265,6 @@ def decodeAddress(address):
|
|||
return 'ripetooshort', 0, 0, ''
|
||||
elif len(embeddedRipeData) > 20:
|
||||
return 'ripetoolong', 0, 0, ''
|
||||
else:
|
||||
return 'otherproblem', 0, 0, ''
|
||||
elif addressVersionNumber == 4:
|
||||
embeddedRipeData = \
|
||||
|
@ -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
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,11 +109,12 @@ 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),
|
||||
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
|
||||
self.pubkey_y,
|
||||
))
|
||||
|
||||
def get_privkey(self):
|
||||
|
@ -105,9 +122,10 @@ class ECC:
|
|||
High level function which returns
|
||||
curve(2) + len_of_privkey(2) + privkey
|
||||
"""
|
||||
return b''.join((pack('!H', self.curve),
|
||||
return b''.join((
|
||||
pack('!H', self.curve),
|
||||
pack('!H', len(self.privkey)),
|
||||
self.privkey
|
||||
self.privkey,
|
||||
))
|
||||
|
||||
@staticmethod
|
||||
|
@ -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
|
||||
|
||||
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()
|
||||
|
|
|
@ -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()):
|
||||
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])
|
||||
|
|
Loading…
Reference in New Issue
Block a user