Bmng dev master #687
|
@ -48,7 +48,7 @@ import time
|
||||||
|
|
||||||
# OSX python version check
|
# OSX python version check
|
||||||
import sys
|
import sys
|
||||||
if sys.platform == 'darwin':
|
if 'win' in sys.platform:
|
||||||
if float("{1}.{2}".format(*sys.version_info)) < 7.5:
|
if float("{1}.{2}".format(*sys.version_info)) < 7.5:
|
||||||
msg = "You should use python 2.7.5 or greater. Your version: %s", "{0}.{1}.{2}".format(*sys.version_info)
|
msg = "You should use python 2.7.5 or greater. Your version: %s", "{0}.{1}.{2}".format(*sys.version_info)
|
||||||
logger.critical(msg)
|
logger.critical(msg)
|
||||||
|
|
|
@ -79,11 +79,11 @@ class addressGenerator(threading.Thread):
|
||||||
startTime = time.time()
|
startTime = time.time()
|
||||||
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
|
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
|
||||||
potentialPrivSigningKey = OpenSSL.rand(32)
|
potentialPrivSigningKey = OpenSSL.rand(32)
|
||||||
potentialPubSigningKey = pointMult(potentialPrivSigningKey)
|
potentialPubSigningKey = highlevelcrypto.pointMult(potentialPrivSigningKey)
|
||||||
while True:
|
while True:
|
||||||
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
|
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
|
||||||
potentialPrivEncryptionKey = OpenSSL.rand(32)
|
potentialPrivEncryptionKey = OpenSSL.rand(32)
|
||||||
potentialPubEncryptionKey = pointMult(
|
potentialPubEncryptionKey = highlevelcrypto.pointMult(
|
||||||
potentialPrivEncryptionKey)
|
potentialPrivEncryptionKey)
|
||||||
# print 'potentialPubSigningKey', potentialPubSigningKey.encode('hex')
|
# print 'potentialPubSigningKey', potentialPubSigningKey.encode('hex')
|
||||||
# print 'potentialPubEncryptionKey',
|
# print 'potentialPubEncryptionKey',
|
||||||
|
@ -175,9 +175,9 @@ class addressGenerator(threading.Thread):
|
||||||
deterministicPassphrase + encodeVarint(signingKeyNonce)).digest()[:32]
|
deterministicPassphrase + encodeVarint(signingKeyNonce)).digest()[:32]
|
||||||
potentialPrivEncryptionKey = hashlib.sha512(
|
potentialPrivEncryptionKey = hashlib.sha512(
|
||||||
deterministicPassphrase + encodeVarint(encryptionKeyNonce)).digest()[:32]
|
deterministicPassphrase + encodeVarint(encryptionKeyNonce)).digest()[:32]
|
||||||
potentialPubSigningKey = pointMult(
|
potentialPubSigningKey = highlevelcrypto.pointMult(
|
||||||
potentialPrivSigningKey)
|
potentialPrivSigningKey)
|
||||||
potentialPubEncryptionKey = pointMult(
|
potentialPubEncryptionKey = highlevelcrypto.pointMult(
|
||||||
potentialPrivEncryptionKey)
|
potentialPrivEncryptionKey)
|
||||||
# print 'potentialPubSigningKey', potentialPubSigningKey.encode('hex')
|
# print 'potentialPubSigningKey', potentialPubSigningKey.encode('hex')
|
||||||
# print 'potentialPubEncryptionKey',
|
# print 'potentialPubEncryptionKey',
|
||||||
|
@ -280,32 +280,3 @@ class addressGenerator(threading.Thread):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Error in the addressGenerator thread. Thread was given a command it could not understand: " + command)
|
"Error in the addressGenerator thread. Thread was given a command it could not understand: " + command)
|
||||||
|
|
||||||
|
|
||||||
# Does an EC point multiplication; turns a private key into a public key.
|
|
||||||
def pointMult(secret):
|
|
||||||
# ctx = OpenSSL.BN_CTX_new() #This value proved to cause Seg Faults on
|
|
||||||
# Linux. It turns out that it really didn't speed up EC_POINT_mul anyway.
|
|
||||||
k = OpenSSL.EC_KEY_new_by_curve_name(OpenSSL.get_curve('secp256k1'))
|
|
||||||
priv_key = OpenSSL.BN_bin2bn(secret, 32, 0)
|
|
||||||
group = OpenSSL.EC_KEY_get0_group(k)
|
|
||||||
pub_key = OpenSSL.EC_POINT_new(group)
|
|
||||||
|
|
||||||
OpenSSL.EC_POINT_mul(group, pub_key, priv_key, None, None, None)
|
|
||||||
OpenSSL.EC_KEY_set_private_key(k, priv_key)
|
|
||||||
OpenSSL.EC_KEY_set_public_key(k, pub_key)
|
|
||||||
# print 'priv_key',priv_key
|
|
||||||
# print 'pub_key',pub_key
|
|
||||||
|
|
||||||
size = OpenSSL.i2o_ECPublicKey(k, 0)
|
|
||||||
mb = ctypes.create_string_buffer(size)
|
|
||||||
OpenSSL.i2o_ECPublicKey(k, ctypes.byref(ctypes.pointer(mb)))
|
|
||||||
# print 'mb.raw', mb.raw.encode('hex'), 'length:', len(mb.raw)
|
|
||||||
# print 'mb.raw', mb.raw, 'length:', len(mb.raw)
|
|
||||||
|
|
||||||
OpenSSL.EC_POINT_free(pub_key)
|
|
||||||
# OpenSSL.BN_CTX_free(ctx)
|
|
||||||
OpenSSL.BN_free(priv_key)
|
|
||||||
OpenSSL.EC_KEY_free(k)
|
|
||||||
return mb.raw
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1150,25 +1150,27 @@ class objectProcessor(threading.Thread):
|
||||||
shared.workerQueue.put(('sendmessage', ''))
|
shared.workerQueue.put(('sendmessage', ''))
|
||||||
|
|
||||||
def ackDataHasAVaildHeader(self, ackData):
|
def ackDataHasAVaildHeader(self, ackData):
|
||||||
if len(ackData) < 24:
|
if len(ackData) < shared.Header.size:
|
||||||
logger.info('The length of ackData is unreasonably short. Not sending ackData.')
|
logger.info('The length of ackData is unreasonably short. Not sending ackData.')
|
||||||
return False
|
return False
|
||||||
if ackData[0:4] != '\xe9\xbe\xb4\xd9':
|
|
||||||
|
magic,command,payload_length,checksum = shared.Header.unpack(ackData[:shared.Header.size])
|
||||||
|
if magic != 0xE9BEB4D9:
|
||||||
logger.info('Ackdata magic bytes were wrong. Not sending ackData.')
|
logger.info('Ackdata magic bytes were wrong. Not sending ackData.')
|
||||||
return False
|
return False
|
||||||
ackDataPayloadLength, = unpack('>L', ackData[16:20])
|
payload = ackData[shared.Header.size:]
|
||||||
if len(ackData) - 24 != ackDataPayloadLength:
|
if len(payload) != payload_length:
|
||||||
logger.info('ackData payload length doesn\'t match the payload length specified in the header. Not sending ackdata.')
|
logger.info('ackData payload length doesn\'t match the payload length specified in the header. Not sending ackdata.')
|
||||||
return False
|
return False
|
||||||
if ackData[20:24] != hashlib.sha512(ackData[24:]).digest()[0:4]: # test the checksum in the message.
|
if payload_length > 180000000: # If the size of the message is greater than 180MB, ignore it.
|
||||||
|
return False
|
||||||
|
if checksum != hashlib.sha512(payload).digest()[0:4]: # test the checksum in the message.
|
||||||
logger.info('ackdata checksum wrong. Not sending ackdata.')
|
logger.info('ackdata checksum wrong. Not sending ackdata.')
|
||||||
return False
|
return False
|
||||||
if ackDataPayloadLength > 180000000: # If the size of the message is greater than 180MB, ignore it.
|
if (command != addDataPadding('getpubkey') and
|
||||||
return False
|
command != addDataPadding('pubkey') and
|
||||||
if (ackData[4:16] != addDataPadding('getpubkey') and
|
command != addDataPadding('msg') and
|
||||||
ackData[4:16] != addDataPadding('pubkey') and
|
command != addDataPadding('broadcast')):
|
||||||
ackData[4:16] != addDataPadding('msg') and
|
|
||||||
ackData[4:16] != addDataPadding('broadcast')):
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -1211,4 +1213,4 @@ class objectProcessor(threading.Thread):
|
||||||
# Throw away any extra lines (headers) after the subject.
|
# Throw away any extra lines (headers) after the subject.
|
||||||
if subject:
|
if subject:
|
||||||
subject = subject.splitlines()[0]
|
subject = subject.splitlines()[0]
|
||||||
return subject, body
|
return subject, body
|
||||||
|
|
|
@ -47,7 +47,6 @@ class receiveDataThread(threading.Thread):
|
||||||
self.sock = sock
|
self.sock = sock
|
||||||
self.peer = shared.Peer(HOST, port)
|
self.peer = shared.Peer(HOST, port)
|
||||||
self.streamNumber = streamNumber
|
self.streamNumber = streamNumber
|
||||||
self.payloadLength = 0 # This is the protocol payload length thus it doesn't include the 24 byte message header
|
|
||||||
self.objectsThatWeHaveYetToGetFromThisPeer = {}
|
self.objectsThatWeHaveYetToGetFromThisPeer = {}
|
||||||
self.selfInitiatedConnections = selfInitiatedConnections
|
self.selfInitiatedConnections = selfInitiatedConnections
|
||||||
self.sendDataThreadQueue = sendDataThreadQueue # used to send commands and data to the sendDataThread
|
self.sendDataThreadQueue = sendDataThreadQueue # used to send commands and data to the sendDataThread
|
||||||
|
@ -113,28 +112,39 @@ class receiveDataThread(threading.Thread):
|
||||||
# with shared.printLock:
|
# with shared.printLock:
|
||||||
# print 'self.data is currently ', repr(self.data)
|
# print 'self.data is currently ', repr(self.data)
|
||||||
#
|
#
|
||||||
if len(self.data) < 24: # if so little of the data has arrived that we can't even read the checksum then wait for more data.
|
if len(self.data) < shared.Header.size: # if so little of the data has arrived that we can't even read the checksum then wait for more data.
|
||||||
return
|
return
|
||||||
if self.data[0:4] != '\xe9\xbe\xb4\xd9':
|
#Use a memoryview so we don't copy data unnecessarily
|
||||||
|
view = memoryview(self.data)
|
||||||
|
magic,command,payloadLength,checksum = shared.Header.unpack(view[:shared.Header.size])
|
||||||
|
view = view[shared.Header.size:]
|
||||||
|
if magic != 0xE9BEB4D9:
|
||||||
#if shared.verbose >= 1:
|
#if shared.verbose >= 1:
|
||||||
# with shared.printLock:
|
# with shared.printLock:
|
||||||
# print 'The magic bytes were not correct. First 40 bytes of data: ' + repr(self.data[0:40])
|
# print 'The magic bytes were not correct. First 40 bytes of data: ' + repr(self.data[0:40])
|
||||||
|
|
||||||
self.data = ""
|
self.data = ""
|
||||||
return
|
return
|
||||||
self.payloadLength, = unpack('>L', self.data[16:20])
|
if payloadLength > 20000000:
|
||||||
if self.payloadLength > 20000000:
|
logger.info('The incoming message, which we have not yet download, is too large. Ignoring it. (unfortunately there is no way to tell the other node to stop sending it except to disconnect.) Message size: %s' % payloadLength)
|
||||||
logger.info('The incoming message, which we have not yet download, is too large. Ignoring it. (unfortunately there is no way to tell the other node to stop sending it except to disconnect.) Message size: %s' % self.payloadLength)
|
self.data = view[payloadLength:].tobytes()
|
||||||
self.data = self.data[self.payloadLength + 24:]
|
del view,magic,command,payloadLength,checksum # we don't need these anymore and better to clean them now before the recursive call rather than after
|
||||||
self.processData()
|
self.processData()
|
||||||
return
|
return
|
||||||
if len(self.data) < self.payloadLength + 24: # check if the whole message has arrived yet.
|
if len(view) < payloadLength: # check if the whole message has arrived yet.
|
||||||
return
|
return
|
||||||
if self.data[20:24] != hashlib.sha512(self.data[24:self.payloadLength + 24]).digest()[0:4]: # test the checksum in the message. If it is correct...
|
payload = view[:payloadLength]
|
||||||
|
if checksum != hashlib.sha512(payload).digest()[0:4]: # test the checksum in the message.
|
||||||
print 'Checksum incorrect. Clearing this message.'
|
print 'Checksum incorrect. Clearing this message.'
|
||||||
self.data = self.data[self.payloadLength + 24:]
|
self.data = view[payloadLength:].tobytes()
|
||||||
|
del view,magic,command,payloadLength,checksum,payload #again better to clean up before the recursive call
|
||||||
self.processData()
|
self.processData()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
#We can now revert back to bytestrings and take this message out
|
||||||
|
payload = payload.tobytes()
|
||||||
|
self.data = view[payloadLength:].tobytes()
|
||||||
|
del view,magic,payloadLength,checksum
|
||||||
# The time we've last seen this node is obviously right now since we
|
# The time we've last seen this node is obviously right now since we
|
||||||
# just received valid data from it. So update the knownNodes list so
|
# just received valid data from it. So update the knownNodes list so
|
||||||
# that other peers can be made aware of its existance.
|
# that other peers can be made aware of its existance.
|
||||||
|
@ -143,37 +153,39 @@ class receiveDataThread(threading.Thread):
|
||||||
shared.knownNodes[self.streamNumber][self.peer] = int(time.time())
|
shared.knownNodes[self.streamNumber][self.peer] = int(time.time())
|
||||||
shared.knownNodesLock.release()
|
shared.knownNodesLock.release()
|
||||||
|
|
||||||
remoteCommand = self.data[4:16]
|
#Strip the nulls
|
||||||
|
command = command.rstrip('\x00')
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'remoteCommand', repr(remoteCommand.replace('\x00', '')), ' from', self.peer
|
print 'remoteCommand', repr(command), ' from', self.peer
|
||||||
|
|
||||||
|
#TODO: Use a dispatcher here
|
||||||
|
if not self.connectionIsOrWasFullyEstablished:
|
||||||
|
if command == 'version':
|
||||||
|
self.recversion(payload)
|
||||||
|
elif command == 'verack':
|
||||||
|
self.recverack()
|
||||||
|
else:
|
||||||
|
if command == 'addr':
|
||||||
|
self.recaddr(payload)
|
||||||
|
elif command == 'getpubkey':
|
||||||
|
shared.checkAndSharegetpubkeyWithPeers(payload)
|
||||||
|
elif command == 'pubkey':
|
||||||
|
self.recpubkey(payload)
|
||||||
|
elif command == 'inv':
|
||||||
|
self.recinv(payload)
|
||||||
|
elif command == 'getdata':
|
||||||
|
self.recgetdata(payload)
|
||||||
|
elif command == 'msg':
|
||||||
|
self.recmsg(payload)
|
||||||
|
elif command == 'broadcast':
|
||||||
|
self.recbroadcast(payload)
|
||||||
|
elif command == 'ping':
|
||||||
|
self.sendpong(payload)
|
||||||
|
#elif command == 'pong':
|
||||||
|
# pass
|
||||||
|
#elif command == 'alert':
|
||||||
|
# pass
|
||||||
|
|
||||||
if remoteCommand == addDataPadding('version') and not self.connectionIsOrWasFullyEstablished:
|
|
||||||
self.recversion(self.data[24:self.payloadLength + 24])
|
|
||||||
elif remoteCommand == addDataPadding('verack') and not self.connectionIsOrWasFullyEstablished:
|
|
||||||
self.recverack()
|
|
||||||
elif remoteCommand == addDataPadding('addr') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
self.recaddr(self.data[24:self.payloadLength + 24])
|
|
||||||
elif remoteCommand == addDataPadding('getpubkey') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
shared.checkAndSharegetpubkeyWithPeers(self.data[24:self.payloadLength + 24])
|
|
||||||
elif remoteCommand == addDataPadding('pubkey') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
self.recpubkey(self.data[24:self.payloadLength + 24])
|
|
||||||
elif remoteCommand == addDataPadding('inv') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
self.recinv(self.data[24:self.payloadLength + 24])
|
|
||||||
elif remoteCommand == addDataPadding('getdata') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
self.recgetdata(self.data[24:self.payloadLength + 24])
|
|
||||||
elif remoteCommand == addDataPadding('msg') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
self.recmsg(self.data[24:self.payloadLength + 24])
|
|
||||||
elif remoteCommand == addDataPadding('broadcast') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
self.recbroadcast(self.data[24:self.payloadLength + 24])
|
|
||||||
elif remoteCommand == addDataPadding('ping') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
self.sendpong()
|
|
||||||
elif remoteCommand == addDataPadding('pong') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
pass
|
|
||||||
elif remoteCommand == addDataPadding('alert') and self.connectionIsOrWasFullyEstablished:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.data = self.data[
|
|
||||||
self.payloadLength + 24:] # take this message out and then process the next message
|
|
||||||
if self.data == '':
|
if self.data == '':
|
||||||
while len(self.objectsThatWeHaveYetToGetFromThisPeer) > 0:
|
while len(self.objectsThatWeHaveYetToGetFromThisPeer) > 0:
|
||||||
shared.numberOfInventoryLookupsPerformed += 1
|
shared.numberOfInventoryLookupsPerformed += 1
|
||||||
|
@ -226,7 +238,7 @@ class receiveDataThread(threading.Thread):
|
||||||
|
|
||||||
def sendpong(self):
|
def sendpong(self):
|
||||||
print 'Sending pong'
|
print 'Sending pong'
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', '\xE9\xBE\xB4\xD9\x70\x6F\x6E\x67' + addDataPadding('') + '\xcf\x83\xe1\x35'))
|
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('pong')))
|
||||||
|
|
||||||
|
|
||||||
def recverack(self):
|
def recverack(self):
|
||||||
|
@ -297,7 +309,7 @@ class receiveDataThread(threading.Thread):
|
||||||
for hash, storedValue in bigInvList.items():
|
for hash, storedValue in bigInvList.items():
|
||||||
payload += hash
|
payload += hash
|
||||||
numberOfObjectsInInvMessage += 1
|
numberOfObjectsInInvMessage += 1
|
||||||
if numberOfObjectsInInvMessage >= 50000: # We can only send a max of 50000 items per inv message but we may have more objects to advertise. They must be split up into multiple inv messages.
|
if numberOfObjectsInInvMessage == 50000: # We can only send a max of 50000 items per inv message but we may have more objects to advertise. They must be split up into multiple inv messages.
|
||||||
self.sendinvMessageToJustThisOnePeer(
|
self.sendinvMessageToJustThisOnePeer(
|
||||||
numberOfObjectsInInvMessage, payload)
|
numberOfObjectsInInvMessage, payload)
|
||||||
payload = ''
|
payload = ''
|
||||||
|
@ -311,13 +323,9 @@ class receiveDataThread(threading.Thread):
|
||||||
# function for broadcasting invs to everyone in our stream.
|
# function for broadcasting invs to everyone in our stream.
|
||||||
def sendinvMessageToJustThisOnePeer(self, numberOfObjects, payload):
|
def sendinvMessageToJustThisOnePeer(self, numberOfObjects, payload):
|
||||||
payload = encodeVarint(numberOfObjects) + payload
|
payload = encodeVarint(numberOfObjects) + payload
|
||||||
headerData = '\xe9\xbe\xb4\xd9' # magic bits, slighly different from Bitcoin's magic bits.
|
|
||||||
headerData += addDataPadding('inv')
|
|
||||||
headerData += pack('>L', len(payload))
|
|
||||||
headerData += hashlib.sha512(payload).digest()[:4]
|
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Sending huge inv message with', numberOfObjects, 'objects to just this one peer'
|
print 'Sending huge inv message with', numberOfObjects, 'objects to just this one peer'
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', headerData + payload))
|
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('inv', payload)))
|
||||||
|
|
||||||
def _sleepForTimingAttackMitigation(self, sleepTime):
|
def _sleepForTimingAttackMitigation(self, sleepTime):
|
||||||
# We don't need to do the timing attack mitigation if we are
|
# We don't need to do the timing attack mitigation if we are
|
||||||
|
@ -455,14 +463,8 @@ class receiveDataThread(threading.Thread):
|
||||||
def sendgetdata(self, hash):
|
def sendgetdata(self, hash):
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'sending getdata to retrieve object with hash:', hash.encode('hex')
|
print 'sending getdata to retrieve object with hash:', hash.encode('hex')
|
||||||
|
|
||||||
payload = '\x01' + hash
|
payload = '\x01' + hash
|
||||||
headerData = '\xe9\xbe\xb4\xd9' # magic bits, slighly different from Bitcoin's magic bits.
|
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('getdata', payload)))
|
||||||
headerData += addDataPadding('getdata')
|
|
||||||
headerData += pack('>L', len(
|
|
||||||
payload)) # payload length. Note that we add an extra 8 for the nonce.
|
|
||||||
headerData += hashlib.sha512(payload).digest()[:4]
|
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', headerData + payload))
|
|
||||||
|
|
||||||
|
|
||||||
# We have received a getdata request from our peer
|
# We have received a getdata request from our peer
|
||||||
|
@ -499,43 +501,17 @@ class receiveDataThread(threading.Thread):
|
||||||
|
|
||||||
# Our peer has requested (in a getdata message) that we send an object.
|
# Our peer has requested (in a getdata message) that we send an object.
|
||||||
def sendData(self, objectType, payload):
|
def sendData(self, objectType, payload):
|
||||||
headerData = '\xe9\xbe\xb4\xd9' # magic bits, slighly different from Bitcoin's magic bits.
|
if (objectType != 'pubkey' and
|
||||||
if objectType == 'pubkey':
|
objectType != 'getpubkey' and
|
||||||
with shared.printLock:
|
objectType != 'msg' and
|
||||||
print 'sending pubkey'
|
objectType != 'broadcast'):
|
||||||
|
|
||||||
headerData += addDataPadding('pubkey')
|
|
||||||
elif objectType == 'getpubkey' or objectType == 'pubkeyrequest':
|
|
||||||
with shared.printLock:
|
|
||||||
print 'sending getpubkey'
|
|
||||||
|
|
||||||
headerData += addDataPadding('getpubkey')
|
|
||||||
elif objectType == 'msg':
|
|
||||||
with shared.printLock:
|
|
||||||
print 'sending msg'
|
|
||||||
|
|
||||||
headerData += addDataPadding('msg')
|
|
||||||
elif objectType == 'broadcast':
|
|
||||||
with shared.printLock:
|
|
||||||
print 'sending broadcast'
|
|
||||||
|
|
||||||
headerData += addDataPadding('broadcast')
|
|
||||||
else:
|
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
'Error: sendData has been asked to send a strange objectType: %s\n' % str(objectType))
|
'Error: sendData has been asked to send a strange objectType: %s\n' % str(objectType))
|
||||||
return
|
return
|
||||||
headerData += pack('>L', len(payload)) # payload length.
|
|
||||||
headerData += hashlib.sha512(payload).digest()[:4]
|
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', headerData + payload))
|
|
||||||
|
|
||||||
|
|
||||||
# Advertise this object to all of our peers
|
|
||||||
"""def broadcastinv(self, hash):
|
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'broadcasting inv with hash:', hash.encode('hex')
|
print 'sending', objectType
|
||||||
|
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket(objectType, payload)))
|
||||||
|
|
||||||
shared.broadcastToSendDataQueues((self.streamNumber, 'advertiseobject', hash))
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _checkIPv4Address(self, host, hostFromAddrMessage):
|
def _checkIPv4Address(self, host, hostFromAddrMessage):
|
||||||
# print 'hostFromAddrMessage', hostFromAddrMessage
|
# print 'hostFromAddrMessage', hostFromAddrMessage
|
||||||
|
@ -545,7 +521,7 @@ class receiveDataThread(threading.Thread):
|
||||||
if host[0] == '\x0A':
|
if host[0] == '\x0A':
|
||||||
print 'Ignoring IP address in private range:', hostFromAddrMessage
|
print 'Ignoring IP address in private range:', hostFromAddrMessage
|
||||||
return False
|
return False
|
||||||
if host[0:2] == '\xC0A8':
|
if host[0:2] == '\xC0\xA8':
|
||||||
print 'Ignoring IP address in private range:', hostFromAddrMessage
|
print 'Ignoring IP address in private range:', hostFromAddrMessage
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
@ -745,11 +721,7 @@ class receiveDataThread(threading.Thread):
|
||||||
payload += pack('>H', PORT) # remote port
|
payload += pack('>H', PORT) # remote port
|
||||||
|
|
||||||
payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
|
payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
|
||||||
datatosend = '\xE9\xBE\xB4\xD9' + addDataPadding('addr')
|
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('addr', payload)))
|
||||||
datatosend = datatosend + pack('>L', len(payload)) # payload length
|
|
||||||
datatosend = datatosend + hashlib.sha512(payload).digest()[0:4]
|
|
||||||
datatosend = datatosend + payload
|
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', datatosend))
|
|
||||||
|
|
||||||
|
|
||||||
# We have received a version message
|
# We have received a version message
|
||||||
|
@ -832,7 +804,7 @@ class receiveDataThread(threading.Thread):
|
||||||
def sendverack(self):
|
def sendverack(self):
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Sending verack'
|
print 'Sending verack'
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', '\xE9\xBE\xB4\xD9\x76\x65\x72\x61\x63\x6B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcf\x83\xe1\x35'))
|
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('verack')))
|
||||||
self.verackSent = True
|
self.verackSent = True
|
||||||
if self.verackReceived:
|
if self.verackReceived:
|
||||||
self.connectionFullyEstablished()
|
self.connectionFullyEstablished()
|
||||||
|
|
|
@ -109,13 +109,9 @@ class sendDataThread(threading.Thread):
|
||||||
payload += pack('>H', port)
|
payload += pack('>H', port)
|
||||||
|
|
||||||
payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
|
payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
|
||||||
datatosend = '\xE9\xBE\xB4\xD9' + addDataPadding('addr')
|
packet = shared.CreatePacket('addr', payload)
|
||||||
datatosend = datatosend + pack('>L', len(payload)) # payload length
|
|
||||||
datatosend = datatosend + hashlib.sha512(payload).digest()[0:4]
|
|
||||||
datatosend = datatosend + payload
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.sock.sendall(datatosend)
|
self.sock.sendall(packet)
|
||||||
self.lastTimeISentData = int(time.time())
|
self.lastTimeISentData = int(time.time())
|
||||||
except:
|
except:
|
||||||
print 'sendaddr: self.sock.sendall failed'
|
print 'sendaddr: self.sock.sendall failed'
|
||||||
|
@ -132,12 +128,9 @@ class sendDataThread(threading.Thread):
|
||||||
payload += hash
|
payload += hash
|
||||||
if payload != '':
|
if payload != '':
|
||||||
payload = encodeVarint(len(payload)/32) + payload
|
payload = encodeVarint(len(payload)/32) + payload
|
||||||
headerData = '\xe9\xbe\xb4\xd9' # magic bits, slighly different from Bitcoin's magic bits.
|
packet = shared.CreatePacket('inv', payload)
|
||||||
headerData += addDataPadding('inv')
|
|
||||||
headerData += pack('>L', len(payload))
|
|
||||||
headerData += hashlib.sha512(payload).digest()[:4]
|
|
||||||
try:
|
try:
|
||||||
self.sock.sendall(headerData + payload)
|
self.sock.sendall(packet)
|
||||||
self.lastTimeISentData = int(time.time())
|
self.lastTimeISentData = int(time.time())
|
||||||
except:
|
except:
|
||||||
print 'sendinv: self.sock.sendall failed'
|
print 'sendinv: self.sock.sendall failed'
|
||||||
|
@ -148,10 +141,9 @@ class sendDataThread(threading.Thread):
|
||||||
# Send out a pong message to keep the connection alive.
|
# Send out a pong message to keep the connection alive.
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Sending pong to', self.peer, 'to keep connection alive.'
|
print 'Sending pong to', self.peer, 'to keep connection alive.'
|
||||||
|
packet = shared.CreatePacket('pong')
|
||||||
try:
|
try:
|
||||||
self.sock.sendall(
|
self.sock.sendall(packet)
|
||||||
'\xE9\xBE\xB4\xD9' + addDataPadding('pong') + '\x00\x00\x00\x00\xcf\x83\xe1\x35') # Magic bytes + pong command + zero data length + checksum
|
|
||||||
self.lastTimeISentData = int(time.time())
|
self.lastTimeISentData = int(time.time())
|
||||||
except:
|
except:
|
||||||
print 'send pong failed'
|
print 'send pong failed'
|
||||||
|
|
|
@ -8,7 +8,6 @@ from addresses import *
|
||||||
import highlevelcrypto
|
import highlevelcrypto
|
||||||
import proofofwork
|
import proofofwork
|
||||||
import sys
|
import sys
|
||||||
from class_addressGenerator import pointMult
|
|
||||||
import tr
|
import tr
|
||||||
from debug import logger
|
from debug import logger
|
||||||
from helper_sql import *
|
from helper_sql import *
|
||||||
|
@ -305,7 +304,7 @@ class singleWorker(threading.Thread):
|
||||||
addressVersionNumber) + encodeVarint(streamNumber) + hash).digest()).digest()
|
addressVersionNumber) + encodeVarint(streamNumber) + hash).digest()).digest()
|
||||||
payload += doubleHashOfAddressData[32:] # the tag
|
payload += doubleHashOfAddressData[32:] # the tag
|
||||||
privEncryptionKey = doubleHashOfAddressData[:32]
|
privEncryptionKey = doubleHashOfAddressData[:32]
|
||||||
pubEncryptionKey = pointMult(privEncryptionKey)
|
pubEncryptionKey = highlevelcrypto.pointMult(privEncryptionKey)
|
||||||
payload += highlevelcrypto.encrypt(
|
payload += highlevelcrypto.encrypt(
|
||||||
dataToEncrypt, pubEncryptionKey.encode('hex'))
|
dataToEncrypt, pubEncryptionKey.encode('hex'))
|
||||||
|
|
||||||
|
@ -416,7 +415,7 @@ class singleWorker(threading.Thread):
|
||||||
else:
|
else:
|
||||||
privEncryptionKey = doubleHashOfAddressData[:32]
|
privEncryptionKey = doubleHashOfAddressData[:32]
|
||||||
|
|
||||||
pubEncryptionKey = pointMult(privEncryptionKey)
|
pubEncryptionKey = highlevelcrypto.pointMult(privEncryptionKey)
|
||||||
payload += highlevelcrypto.encrypt(
|
payload += highlevelcrypto.encrypt(
|
||||||
dataToEncrypt, pubEncryptionKey.encode('hex'))
|
dataToEncrypt, pubEncryptionKey.encode('hex'))
|
||||||
|
|
||||||
|
@ -950,8 +949,4 @@ class singleWorker(threading.Thread):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
payload = pack('>Q', nonce) + payload
|
payload = pack('>Q', nonce) + payload
|
||||||
headerData = '\xe9\xbe\xb4\xd9' # magic bits, slighly different from Bitcoin's magic bits.
|
return shared.CreatePacket('msg', payload)
|
||||||
headerData += addDataPadding('msg')
|
|
||||||
headerData += pack('>L', len(payload))
|
|
||||||
headerData += hashlib.sha512(payload).digest()[:4]
|
|
||||||
return headerData + payload
|
|
||||||
|
|
|
@ -1,33 +1,56 @@
|
||||||
import pyelliptic
|
import pyelliptic
|
||||||
from pyelliptic import arithmetic as a
|
from pyelliptic import arithmetic as a, OpenSSL
|
||||||
def makeCryptor(privkey):
|
def makeCryptor(privkey):
|
||||||
privkey_bin = '\x02\xca\x00 '+a.changebase(privkey,16,256,minlen=32)
|
private_key = a.changebase(privkey, 16, 256, minlen=32)
|
||||||
pubkey = a.changebase(a.privtopub(privkey),16,256,minlen=65)[1:]
|
public_key = pointMult(private_key)
|
||||||
pubkey_bin = '\x02\xca\x00 '+pubkey[:32]+'\x00 '+pubkey[32:]
|
privkey_bin = '\x02\xca\x00\x20' + private_key
|
||||||
cryptor = pyelliptic.ECC(curve='secp256k1',privkey=privkey_bin,pubkey=pubkey_bin)
|
pubkey_bin = '\x02\xca\x00\x20' + public_key[1:-32] + '\x00\x20' + public_key[-32:]
|
||||||
return cryptor
|
cryptor = pyelliptic.ECC(curve='secp256k1',privkey=privkey_bin,pubkey=pubkey_bin)
|
||||||
|
return cryptor
|
||||||
def hexToPubkey(pubkey):
|
def hexToPubkey(pubkey):
|
||||||
pubkey_raw = a.changebase(pubkey[2:],16,256,minlen=64)
|
pubkey_raw = a.changebase(pubkey[2:],16,256,minlen=64)
|
||||||
pubkey_bin = '\x02\xca\x00 '+pubkey_raw[:32]+'\x00 '+pubkey_raw[32:]
|
pubkey_bin = '\x02\xca\x00 '+pubkey_raw[:32]+'\x00 '+pubkey_raw[32:]
|
||||||
return pubkey_bin
|
return pubkey_bin
|
||||||
def makePubCryptor(pubkey):
|
def makePubCryptor(pubkey):
|
||||||
pubkey_bin = hexToPubkey(pubkey)
|
pubkey_bin = hexToPubkey(pubkey)
|
||||||
return pyelliptic.ECC(curve='secp256k1',pubkey=pubkey_bin)
|
return pyelliptic.ECC(curve='secp256k1',pubkey=pubkey_bin)
|
||||||
# Converts hex private key into hex public key
|
# Converts hex private key into hex public key
|
||||||
def privToPub(privkey):
|
def privToPub(privkey):
|
||||||
return a.privtopub(privkey)
|
private_key = a.changebase(privkey, 16, 256, minlen=32)
|
||||||
|
public_key = pointMult(private_key)
|
||||||
|
return public_key.encode('hex')
|
||||||
# Encrypts message with hex public key
|
# Encrypts message with hex public key
|
||||||
def encrypt(msg,hexPubkey):
|
def encrypt(msg,hexPubkey):
|
||||||
return pyelliptic.ECC(curve='secp256k1').encrypt(msg,hexToPubkey(hexPubkey))
|
return pyelliptic.ECC(curve='secp256k1').encrypt(msg,hexToPubkey(hexPubkey))
|
||||||
# Decrypts message with hex private key
|
# Decrypts message with hex private key
|
||||||
def decrypt(msg,hexPrivkey):
|
def decrypt(msg,hexPrivkey):
|
||||||
return makeCryptor(hexPrivkey).decrypt(msg)
|
return makeCryptor(hexPrivkey).decrypt(msg)
|
||||||
# Decrypts message with an existing pyelliptic.ECC.ECC object
|
# Decrypts message with an existing pyelliptic.ECC.ECC object
|
||||||
def decryptFast(msg,cryptor):
|
def decryptFast(msg,cryptor):
|
||||||
return cryptor.decrypt(msg)
|
return cryptor.decrypt(msg)
|
||||||
# Signs with hex private key
|
# Signs with hex private key
|
||||||
def sign(msg,hexPrivkey):
|
def sign(msg,hexPrivkey):
|
||||||
return makeCryptor(hexPrivkey).sign(msg)
|
return makeCryptor(hexPrivkey).sign(msg)
|
||||||
# Verifies with hex public key
|
# Verifies with hex public key
|
||||||
def verify(msg,sig,hexPubkey):
|
def verify(msg,sig,hexPubkey):
|
||||||
return makePubCryptor(hexPubkey).verify(sig,msg)
|
return makePubCryptor(hexPubkey).verify(sig,msg)
|
||||||
|
|
||||||
|
# Does an EC point multiplication; turns a private key into a public key.
|
||||||
|
def pointMult(secret):
|
||||||
|
k = OpenSSL.EC_KEY_new_by_curve_name(OpenSSL.get_curve('secp256k1'))
|
||||||
|
priv_key = OpenSSL.BN_bin2bn(secret, 32, None)
|
||||||
|
group = OpenSSL.EC_KEY_get0_group(k)
|
||||||
|
pub_key = OpenSSL.EC_POINT_new(group)
|
||||||
|
|
||||||
|
OpenSSL.EC_POINT_mul(group, pub_key, priv_key, None, None, None)
|
||||||
|
OpenSSL.EC_KEY_set_private_key(k, priv_key)
|
||||||
|
OpenSSL.EC_KEY_set_public_key(k, pub_key)
|
||||||
|
|
||||||
|
size = OpenSSL.i2o_ECPublicKey(k, None)
|
||||||
|
mb = OpenSSL.create_string_buffer(size)
|
||||||
|
OpenSSL.i2o_ECPublicKey(k, OpenSSL.byref(OpenSSL.pointer(mb)))
|
||||||
|
|
||||||
|
OpenSSL.EC_POINT_free(pub_key)
|
||||||
|
OpenSSL.BN_free(priv_key)
|
||||||
|
OpenSSL.EC_KEY_free(k)
|
||||||
|
return mb.raw
|
||||||
|
|
|
@ -21,6 +21,7 @@ import stat
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from os import path, environ
|
from os import path, environ
|
||||||
|
from struct import Struct
|
||||||
|
|
||||||
# Project imports.
|
# Project imports.
|
||||||
from addresses import *
|
from addresses import *
|
||||||
|
@ -104,6 +105,23 @@ frozen = getattr(sys,'frozen', None)
|
||||||
# security.
|
# security.
|
||||||
trustedPeer = None
|
trustedPeer = None
|
||||||
|
|
||||||
|
#Compiled struct for packing/unpacking headers
|
||||||
|
#New code should use CreatePacket instead of Header.pack
|
||||||
|
Header = Struct('!L12sL4s')
|
||||||
|
|
||||||
|
#Create a packet
|
||||||
|
def CreatePacket(command, payload=''):
|
||||||
|
payload_length = len(payload)
|
||||||
|
if payload_length == 0:
|
||||||
|
checksum = '\xCF\x83\xE1\x35'
|
||||||
|
else:
|
||||||
|
checksum = hashlib.sha512(payload).digest()[0:4]
|
||||||
|
|
||||||
|
b = bytearray(Header.size + payload_length)
|
||||||
|
Header.pack_into(b, 0, 0xE9BEB4D9, command, payload_length, checksum)
|
||||||
|
b[Header.size:] = payload
|
||||||
|
return bytes(b)
|
||||||
|
|
||||||
def isInSqlInventory(hash):
|
def isInSqlInventory(hash):
|
||||||
queryreturn = sqlQuery('''select hash from inventory where hash=?''', hash)
|
queryreturn = sqlQuery('''select hash from inventory where hash=?''', hash)
|
||||||
return queryreturn != []
|
return queryreturn != []
|
||||||
|
@ -141,11 +159,7 @@ def assembleVersionMessage(remoteHost, remotePort, myStreamNumber):
|
||||||
1) # The number of streams about which I care. PyBitmessage currently only supports 1 per connection.
|
1) # The number of streams about which I care. PyBitmessage currently only supports 1 per connection.
|
||||||
payload += encodeVarint(myStreamNumber)
|
payload += encodeVarint(myStreamNumber)
|
||||||
|
|
||||||
datatosend = '\xe9\xbe\xb4\xd9' # magic bits, slighly different from Bitcoin's magic bits.
|
return CreatePacket('version', payload)
|
||||||
datatosend = datatosend + 'version\x00\x00\x00\x00\x00' # version command
|
|
||||||
datatosend = datatosend + pack('>L', len(payload)) # payload length
|
|
||||||
datatosend = datatosend + hashlib.sha512(payload).digest()[0:4]
|
|
||||||
return datatosend + payload
|
|
||||||
|
|
||||||
def lookupAppdataFolder():
|
def lookupAppdataFolder():
|
||||||
APPNAME = "PyBitmessage"
|
APPNAME = "PyBitmessage"
|
||||||
|
|
Reference in New Issue
Block a user