示例#1
0
 def sym_decrypt(self, msg):
     """this is disgusting because we use two different systems for symmetric encryption
 type 0 uses SmmetricKey while
 type 1 uses EncryptedDatagram
 quirks: 
 0 must also update the nonce stored in the db
 1 performs heavy crypto and has non symmetric client/server side encryption/decryption"""
     if not self.symKey:
         msgType, msg = Basic.read_byte(msg)
         if msgType is 0:
             #get the tor fingerprint so we know how to decrypt the message
             (binId, ), msg = Basic.read_message('!20s', msg)
             #convert the tor fingerprint back into hex
             self.hexId = binascii.hexlify(binId).upper()
             #get the symmetric key out of the database:
             sql = "SELECT Owner, Public_Key, Msgnum, auth_blob FROM Relays WHERE Tor_Id = %s"
             inj = (self.hexId, )
             d = db.read(sql, inj)
             #get the sym key from the db and decrypt the msg
             d.addCallback(self.fetch_sym_key, msg)
             #update the message number in the database
             d.addCallback(self.update_db)
         elif msgType is 1:
             self.symKey = EncryptedDatagram.ServerSymKey(
                 Globals.GENERIC_KEY)
             d = threads.deferToThread(self.get_sym_key_value, msg)
         else:
             raise Exception("Unknown msgType:  %s" % (msgType))
     else:
         raise Exception(
             'Passing more than one message per tcp connection is currently not supported'
         )
     return d
示例#2
0
 def datagramReceived(self, datagram, address):
     try:
         self.address = address
         log_msg('Datagram received from %s:%s!' % address, 3)
         msgType, msg = Basic.read_byte(datagram)
         #for compatability really
         if msgType == 1:
             #is it a replay?
             if not cache.has_key(msg):
                 self.request = msg
                 self.symKey = EncryptedDatagram.ServerSymKey(
                     Globals.GENERIC_KEY)
                 msg = self.symKey.decrypt(msg)
                 #for compatability really
                 request_type, msg = Basic.read_byte(msg)
                 if request_type == 3:
                     self.handler = ACoinMessages.Payment(
                         self.reply, self.address)
                     self.handler.on_message(msg)
                 else:
                     raise Exception("Unknown request_type:  %s" %
                                     (request_type))
             else:
                 self.reply(cache[msg], putInQueue=False)
                 return
         else:
             raise Exception("Unknown msgType:  %s" % (msgType))
     except Exception, e:
         self.err(e)
示例#3
0
 def message_arrived(self, msg):
   """Called when a payment message is received via the controller.
   Is responsible for piecing it back together into the actual message.
   @param msg:  the data received from Tor
   @type  msg:  str"""
   self.buffer += msg
   #is the whole message here?
   msgLen, msgData = Basic.read_short(self.buffer)
   if len(msgData) >= msgLen:
     msgData = msgData[:msgLen]
     #we just discard the rest of the cell, two messages are never packed in the same cell currently
     self.buffer = ""
     #what type of message is this?
     msgType, msgData = Basic.read_byte(msgData)
     #ok, now handle that message:
     for msgName in MESSAGE_CODES.keys():
       if msgType == MESSAGE_CODES[msgName]:
         #if we don't know how to handle this message, just close the circuit
         if msgName not in self.messageHandlers:
           log_msg("Remote request for %s, which we do not know how to handle" % (msgName), 1)
           self.close()
           return
         #get the handler:
         handler = self.messageHandlers[msgName]
         #get the handler function:
         funcName = "handle_%s" % (msgName)
         if not hasattr(handler, funcName):
           raise Exception("%s cannot handle %s payment message?" % (handler, msgName))
         f = getattr(handler, funcName)
         f(msgData)
         return
     #uhh, not sure how to handle this message:
     raise Exception("Unknown message type for payment message:  %s" % (msgType))
示例#4
0
 def _send_remote_peer_request(self, infohash, callback):
   #make sure we have a circuit to send it out on:
   if self.circ and self.circ.is_done():
     self.circ = None
   if not self.circ:
     self.circ = self.app.find_or_build_best_circuit(force=True, protocol="DHT")
     if self.circ == None:
       log_msg("Could not build circuit for DHT remote peer request", 0, "dht")
       return
   #generate the message:  (version, infohash, peerList)
   msg = ""
   #header:
   msg += Basic.write_byte(Node.VERSION)
   #infohash:
   msg += infohash
   #peers:
   for host, port in self.knownNodes:
     #is this an IP address?
     if isIPAddress(host):
       msg += Basic.write_byte(0)
       msg += struct.pack("!4sH", socket.inet_aton(host), port)
     #otherwise, it's a URL that has to be resolved remotely
     else:
       msg += Basic.write_byte(1)
       msg += Basic.write_lenstr(host)
       msg += Basic.write_short(port)
   self.circ.send_dht_request(msg, self.make_callback_wrapper(callback))
示例#5
0
 def message_arrived(self, msg):
     """Called when a payment message is received via the controller.
 Is responsible for piecing it back together into the actual message.
 @param msg:  the data received from Tor
 @type  msg:  str"""
     self.buffer += msg
     # is the whole message here?
     msgLen, msgData = Basic.read_short(self.buffer)
     if len(msgData) >= msgLen:
         msgData = msgData[:msgLen]
         # we just discard the rest of the cell, two messages are never packed in the same cell currently
         self.buffer = ""
         # what type of message is this?
         msgType, msgData = Basic.read_byte(msgData)
         # ok, now handle that message:
         for msgName in MESSAGE_CODES.keys():
             if msgType == MESSAGE_CODES[msgName]:
                 # if we don't know how to handle this message, just close the circuit
                 if msgName not in self.messageHandlers:
                     log_msg("Remote request for %s, which we do not know how to handle" % (msgName), 1)
                     self.close()
                     return
                 # get the handler:
                 handler = self.messageHandlers[msgName]
                 # get the handler function:
                 funcName = "handle_%s" % (msgName)
                 if not hasattr(handler, funcName):
                     raise Exception("%s cannot handle %s payment message?" % (handler, msgName))
                 f = getattr(handler, funcName)
                 f(msgData)
                 return
         # uhh, not sure how to handle this message:
         raise Exception("Unknown message type for payment message:  %s" % (msgType))
 def handle_bank_relay(self, msg):
   """Send a message to the bank on behalf of someone else, then send the reply onward
   @param msg:  the message to relay
   @type  msg:  str"""
   version, msg = Basic.read_byte(msg)
   assert version == 1, "only accepts version 1 of PAR protocol"
   responseHop, msg = Basic.read_byte(msg)
   bankMsg, msg = Basic.read_lenstr(msg)
   responseMsg, msg = Basic.read_lenstr(msg)
   payment = UDPPayment.UDPPayment(self.bank, bankMsg)
   paymentDeferred = payment.get_deferred()
   def success(response, responseMsg=responseMsg, responseHop=responseHop):
     responseMsg += response
     if responseHop != 0:
       self.send_direct_tor_message(responseMsg, "payment", True, responseHop)
     else:
       self.handle_payment(responseMsg)
   paymentDeferred.addCallback(success)
   def failure(error):
     if error and hasattr(error, "value") and issubclass(type(error.value), TimeoutError):
       #TODO:  this indicates that the bank is down, or something is wrong with their network?
       log_msg("Relayed payment timed out  :(", 0, "par")
     else:
       log_ex(error, "Relaying payment message failed!")
   paymentDeferred.addErrback(failure)
示例#7
0
    def unpack_and_mint(self, msg):
        """unpacks the request retreiving the number of coins packed and the total value desired.
    Verification: values must be positive!
    """
        self.number, msg = Basic.read_short(msg)
        value, msg = Basic.read_int(msg)
        log_msg('REQUEST:: %s %s' % (self.number, self.hexId), 0)
        if not BankUtil.is_positive_integer(self.number):
            raise ValueError('number of coins must be greater than 0!')
        if value != ACOIN_VALUE or not BankUtil.is_positive_integer(value):
            raise ValueError('coins must have a positive, integer value')

        self.bill = 0
        self.signatures = ""
        for i in range(0, self.number):
            #TODO: move to a worker pool or something
            sig = Globals.ACOIN_KEY.decrypt(msg[:Globals.ACOIN_KEY_BYTES],
                                            False)
            self.signatures += struct.pack('!%ss' % (Globals.ACOIN_KEY_BYTES),
                                           sig)
            msg = msg[Globals.ACOIN_KEY_BYTES:]
            self.bill += value

        #TODO: move this constraint to postgres to get rid of any potential race conditions
        sql = "SELECT balance FROM Accounts WHERE Username = %s"
        inj = (self.user, )
        d = db.read(sql, inj)
        return d
示例#8
0
 def _send_remote_peer_request(self, infohash, callback):
     #make sure we have a circuit to send it out on:
     if self.circ and self.circ.is_done():
         self.circ = None
     if not self.circ:
         self.circ = self.app.find_or_build_best_circuit(force=True,
                                                         protocol="DHT")
         if self.circ == None:
             log_msg("Could not build circuit for DHT remote peer request",
                     0, "dht")
             return
     #generate the message:  (version, infohash, peerList)
     msg = ""
     #header:
     msg += Basic.write_byte(Node.VERSION)
     #infohash:
     msg += infohash
     #peers:
     for host, port in self.knownNodes:
         #is this an IP address?
         if isIPAddress(host):
             msg += Basic.write_byte(0)
             msg += struct.pack("!4sH", socket.inet_aton(host), port)
         #otherwise, it's a URL that has to be resolved remotely
         else:
             msg += Basic.write_byte(1)
             msg += Basic.write_lenstr(host)
             msg += Basic.write_short(port)
     self.circ.send_dht_request(msg, self.make_callback_wrapper(callback))
示例#9
0
 def unpack_and_mint(self, msg):
   """unpacks the request retreiving the number of coins packed and the total value desired.
   Verification: values must be positive!
   """
   self.number, msg = Basic.read_short(msg)
   value, msg = Basic.read_int(msg)
   log_msg('REQUEST:: %s %s'%(self.number, self.hexId), 0)
   if not BankUtil.is_positive_integer(self.number):
     raise ValueError('number of coins must be greater than 0!')
   if value != ACOIN_VALUE or not BankUtil.is_positive_integer(value):
     raise ValueError('coins must have a positive, integer value')
     
   self.bill = 0
   self.signatures = ""
   for i in range(0, self.number):
     #TODO: move to a worker pool or something
     sig = Globals.ACOIN_KEY.decrypt(msg[:Globals.ACOIN_KEY_BYTES], False)
     self.signatures += struct.pack('!%ss'%(Globals.ACOIN_KEY_BYTES), sig)
     msg = msg[Globals.ACOIN_KEY_BYTES:]
     self.bill += value
     
   #TODO: move this constraint to postgres to get rid of any potential race conditions
   sql = "SELECT balance FROM Accounts WHERE Username = %s"
   inj = (self.user,)
   d = db.read(sql, inj)
   return d
示例#10
0
 def sym_decrypt(self, msg):
   """this is disgusting because we use two different systems for symmetric encryption
   type 0 uses SmmetricKey while
   type 1 uses EncryptedDatagram
   quirks: 
   0 must also update the nonce stored in the db
   1 performs heavy crypto and has non symmetric client/server side encryption/decryption"""
   if not self.symKey:
     msgType, msg = Basic.read_byte(msg)
     if msgType is 0:
       #get the tor fingerprint so we know how to decrypt the message
       (binId,), msg = Basic.read_message('!20s', msg)
       #convert the tor fingerprint back into hex
       self.hexId = binascii.hexlify(binId).upper()
       #get the symmetric key out of the database:
       sql = "SELECT Owner, Public_Key, Msgnum, auth_blob FROM Relays WHERE Tor_Id = %s"
       inj = (self.hexId,)
       d = db.read(sql, inj)
       #get the sym key from the db and decrypt the msg
       d.addCallback(self.fetch_sym_key, msg)
       #update the message number in the database
       d.addCallback(self.update_db)
     elif msgType is 1:
       self.symKey = EncryptedDatagram.ServerSymKey(Globals.GENERIC_KEY)
       d = threads.deferToThread(self.get_sym_key_value, msg)
     else:
       raise Exception("Unknown msgType:  %s" % (msgType))
   else:
     raise Exception('Passing more than one message per tcp connection is currently not supported')
   return d
示例#11
0
 def get_prefix(self):
     """@returns:  the beginning of the message from this relay"""
     #send back the PAR version first, so that people can deal with the message intelligently
     msg = Basic.write_byte(self.parVersion)
     #send back our hexid, so they know who this is from:
     msg += Basic.write_hexid(Globals.FINGERPRINT)
     return msg
示例#12
0
  def load_public_key(s=None, fileName=None):
    assert s or fileName, "load_public_key must be passed either a string or file"
    if fileName:
      key = M2Crypto.RSA.load_pub_key(fileName)
      publicKey = PublicKey(key)
      eStr, nStr = key.pub()
      publicKey.e = Basic.bytes_to_long(eStr[4:])
      publicKey.n = Basic.bytes_to_long(nStr[4:])
      return publicKey
    else:
      start = s.find("-----BEGIN RSA PUBLIC KEY-----")
      end = s.find("-----END RSA PUBLIC KEY-----")
      if start == -1:
        raise Exception("Missing PEM prefix")
      if end == -1:
        raise Exception("Missing PEM postfix")
      remainder = s[end+len("-----END RSA PUBLIC KEY-----\n\r"):]
      s = s[start+len("-----BEGIN RSA PUBLIC KEY-----") : end]

      parser = decoder.decode(s.decode("base64"))[0]
      n = long(parser.getComponentByPosition(0))
      e = long(parser.getComponentByPosition(1))
      
      publicKey = PublicKey(n, e)
      return publicKey, remainder
示例#13
0
    def handle_bank_relay(self, msg):
        """Send a message to the bank on behalf of someone else, then send the reply onward
    @param msg:  the message to relay
    @type  msg:  str"""
        version, msg = Basic.read_byte(msg)
        assert version == 1, "only accepts version 1 of PAR protocol"
        responseHop, msg = Basic.read_byte(msg)
        bankMsg, msg = Basic.read_lenstr(msg)
        responseMsg, msg = Basic.read_lenstr(msg)
        payment = UDPPayment.UDPPayment(self.bank, bankMsg)
        paymentDeferred = payment.get_deferred()

        def success(response,
                    responseMsg=responseMsg,
                    responseHop=responseHop):
            responseMsg += response
            if responseHop != 0:
                self.send_direct_tor_message(responseMsg, "payment", True,
                                             responseHop)
            else:
                self.handle_payment(responseMsg)

        paymentDeferred.addCallback(success)

        def failure(error):
            if error and hasattr(error, "value") and issubclass(
                    type(error.value), TimeoutError):
                #TODO:  this indicates that the bank is down, or something is wrong with their network?
                log_msg("Relayed payment timed out  :(", 0, "par")
            else:
                log_ex(error, "Relaying payment message failed!")

        paymentDeferred.addErrback(failure)
示例#14
0
 def stringReceived(self, data):
   """Called when the login response arrives"""
   self.factory.done = True
   self.responseReceived = True
   text = None
   try:
     protocol, data = Basic.read_byte(data)
     if protocol == 1:
       returnCode, data = Basic.read_byte(data)
       if returnCode == 1:
         format = '!IIII4sI'
         (balance, currentACoinInterval, currentACoinIntervalExpiration, nextAcoinIntervalExpiration, host, port), blob = Basic.read_message(format, data)
         size = struct.calcsize(SymmetricKey.MESSAGE_FORMAT)
         authBlob = blob[:size]
         text = blob[size:]
         host = socket.inet_ntoa(host)
         self.factory.bank.on_new_info(balance, currentACoinInterval, currentACoinIntervalExpiration, nextAcoinIntervalExpiration)
         self.factory.bank.on_login_success(balance, authBlob, host, port, text)
       else:
         size = struct.calcsize('!I')
         timeout = struct.unpack('!I', data[:size])[0]
         text = data[size:]
         raise BadLoginPasswordError(timeout)
     else:
       raise Exception('unknown protocol: %s'%(protocol))
   except Exception, error:
     self.factory.bank.on_login_failure(error, text)
示例#15
0
 def stringReceived(self, data):
     """Called when the login response arrives"""
     self.factory.done = True
     self.responseReceived = True
     text = None
     try:
         protocol, data = Basic.read_byte(data)
         if protocol == 1:
             returnCode, data = Basic.read_byte(data)
             if returnCode == 1:
                 format = '!IIII4sI'
                 (balance, currentACoinInterval,
                  currentACoinIntervalExpiration,
                  nextAcoinIntervalExpiration, host,
                  port), blob = Basic.read_message(format, data)
                 size = struct.calcsize(SymmetricKey.MESSAGE_FORMAT)
                 authBlob = blob[:size]
                 text = blob[size:]
                 host = socket.inet_ntoa(host)
                 self.factory.bank.on_new_info(
                     balance, currentACoinInterval,
                     currentACoinIntervalExpiration,
                     nextAcoinIntervalExpiration)
                 self.factory.bank.on_login_success(balance, authBlob, host,
                                                    port, text)
             else:
                 size = struct.calcsize('!I')
                 timeout = struct.unpack('!I', data[:size])[0]
                 text = data[size:]
                 raise BadLoginPasswordError(timeout)
         else:
             raise Exception('unknown protocol: %s' % (protocol))
     except Exception, error:
         self.factory.bank.on_login_failure(error, text)
示例#16
0
 def datagramReceived(self, datagram, address):
   try:
     self.address = address
     log_msg('Datagram received from %s:%s!'%address, 3)
     msgType, msg = Basic.read_byte(datagram)
     #for compatability really
     if msgType == 1:
       #is it a replay?
       if not cache.has_key(msg):
         self.request = msg
         self.symKey = EncryptedDatagram.ServerSymKey(Globals.GENERIC_KEY)
         msg = self.symKey.decrypt(msg)
         #for compatability really
         request_type, msg = Basic.read_byte(msg)
         if request_type == 3:
           self.handler = ACoinMessages.Payment(self.reply, self.address) 
           self.handler.on_message(msg)
         else:
           raise Exception("Unknown request_type:  %s" % (request_type))
       else:
         self.reply(cache[msg], putInQueue=False)
         return
     else:
       raise Exception("Unknown msgType:  %s" % (msgType))
   except Exception, e:
     self.err(e)
示例#17
0
  def start_payment_loop(self):
    coin = Bank.get().get_acoins(1)
    if not coin:
      log_msg("No ACoins left!")
      return
    coin = coin[0]
    #generate ACoin request
    request = BankMessages.make_acoin_request(Bank.get(), Bank.get().currentACoinInterval, 1)
    #make the message:
    bankMsg = Basic.write_byte(1)
    bankMsg += coin.write_binary() + request.msg
    key = EncryptedDatagram.ClientSymKey(Bank.get().PUBLIC_KEY)
    bankMsg = Basic.write_byte(1) + key.encrypt(Basic.write_byte(3) + bankMsg)
    payment = UDPPayment.UDPPayment(Bank.get(), bankMsg)
    paymentDeferred = payment.get_deferred()
    def success(result, request=request):
      log_msg("success")
      self.payments += 1
#      self.start_payment_loop()
      #validate the ACoin
      code, sig = Basic.read_byte(result)
      coin = BankMessages.parse_acoin_response(Bank.get(), sig, request, False)
      if not coin:
        log_msg("Invalid ACoin sent for payment!")
      else:
        Bank.get().on_earned_coin(coin)
    paymentDeferred.addCallback(success)
    def failure(error):
      self.start_payment_loop()
      log_ex(error, "Failure during test?")
      self.failures += 1
    paymentDeferred.addErrback(failure)
示例#18
0
 def stringReceived(self, encryptedMsg):
   self.responseReceived = True
   self.transport.loseConnection()
   blob = self.factory.bank.decrypt_message(encryptedMsg)
   log_msg("ACoin REQUEST response received.", 4)
   responseCode, blob = Basic.read_byte(blob)
   #we had enough credits in our account
   if responseCode == 0:
     (newBalance, number), coins = Basic.read_message('!II', blob)
     #update the balance
     self.factory.bank.on_new_balance_from_bank(newBalance)
     acoinStrFormat = "%ss" % (Globals.ACOIN_KEY_BYTES)
     format = '!' + (acoinStrFormat * number)
     sigs = list(struct.unpack(format, coins))
     while len(self.factory.requests) > 0:
       request = self.factory.requests.pop(0)
       sig = sigs.pop(0)
       coin = BankMessages.parse_acoin_response(self.factory.bank, sig, request, ProgramState.DEBUG)
       if coin:
         self.factory.bank.add_acoin(coin)
       else:
         log_msg("Got an invalid ACoin from the bank!?", 3)
   #the bank could not check out the coins because our account doesn't have enough credits!
   else:
     (newBalance,), blob = Basic.read_message('!I', blob)
     self.factory.bank.on_new_balance_from_bank(newBalance)
示例#19
0
 def died(self, hash):
     if hash in self.torrent_cache:
         log_msg(
             'DIED: "' + Basic.clean(self.torrent_cache[hash]['path']) +
             '"', 1)
     else:
         log_msg('DIED: "' + Basic.clean(hash) + '"', 1)
示例#20
0
 def _reply(self, code):
   """Send an appropriately encoded reply to the client"""
   self.reply_func(Basic.write_byte(1) + Basic.write_byte(code))
   if code == RESPONSE_CODES["SUCCESS"]:
     log_msg("Account %s created for %s" % (self.username, self.ipAddress))
   else:
     log_msg("Account creation attempt failed with code = %s" % (code))
示例#21
0
 def __init__(self, n, e=None):
     """Pass either two arguments (e,n) to build from existing data, or pass one
 argument (n=existing key) to build from an existing key."""
     if e:
         eStrLen = 0
         tmp = 1L
         while tmp < e or eStrLen % 2 != 0:
             tmp *= 256L
             eStrLen += 1
         nStrLen = 0
         #NOTE:  this is completely bizarre.  Why does m2crypto think that we need an odd number of bytes to encode a key?
         nStrLen += 1
         tmp = 1L
         while tmp < n or eStrLen % 2 != 0:
             tmp *= 256L
             nStrLen += 1
         eStr = struct.pack(">I%ss" % (eStrLen), eStrLen,
                            Basic.long_to_bytes(e, eStrLen))
         nStr = struct.pack(">I%ss" % (nStrLen), nStrLen,
                            Basic.long_to_bytes(n, nStrLen))
         self.key = M2Crypto.RSA.new_pub_key((eStr, nStr))
         self.e = long(e)
         self.n = long(n)
     else:
         #validate that this is of the correct type:
         try:
             if n.__class__.__name__ not in ("RSA", "RSA_pub"):
                 raise Exception("Wrong type")
         except:
             raise Exception("n is not the right type:  " + str(n))
         self.key = n
     #: length of the key in bytes (used in blinding/unblinding)
     self.keyLen = len(self.key)
示例#22
0
    def load_public_key(s=None, fileName=None):
        assert s or fileName, "load_public_key must be passed either a string or file"
        if fileName:
            key = M2Crypto.RSA.load_pub_key(fileName)
            publicKey = PublicKey(key)
            eStr, nStr = key.pub()
            publicKey.e = Basic.bytes_to_long(eStr[4:])
            publicKey.n = Basic.bytes_to_long(nStr[4:])
            return publicKey
        else:
            start = s.find("-----BEGIN RSA PUBLIC KEY-----")
            end = s.find("-----END RSA PUBLIC KEY-----")
            if start == -1:
                raise Exception("Missing PEM prefix")
            if end == -1:
                raise Exception("Missing PEM postfix")
            remainder = s[end + len("-----END RSA PUBLIC KEY-----\n\r"):]
            s = s[start + len("-----BEGIN RSA PUBLIC KEY-----"):end]

            parser = decoder.decode(s.decode("base64"))[0]
            n = long(parser.getComponentByPosition(0))
            e = long(parser.getComponentByPosition(1))

            publicKey = PublicKey(n, e)
            return publicKey, remainder
示例#23
0
 def __init__(self, n, e=None):
   """Pass either two arguments (e,n) to build from existing data, or pass one
   argument (n=existing key) to build from an existing key."""
   if e:
     eStrLen = 0
     tmp = 1L
     while tmp < e or eStrLen % 2 != 0:
       tmp *= 256L 
       eStrLen += 1
     nStrLen = 0
     #NOTE:  this is completely bizarre.  Why does m2crypto think that we need an odd number of bytes to encode a key?
     nStrLen += 1
     tmp = 1L
     while tmp < n or eStrLen % 2 != 0:
       tmp *= 256L 
       nStrLen += 1
     eStr = struct.pack(">I%ss" % (eStrLen), eStrLen, Basic.long_to_bytes(e, eStrLen))
     nStr = struct.pack(">I%ss" % (nStrLen), nStrLen, Basic.long_to_bytes(n, nStrLen))
     self.key = M2Crypto.RSA.new_pub_key((eStr, nStr))
     self.e = long(e)
     self.n = long(n)
   else:
     #validate that this is of the correct type:
     try:
       if n.__class__.__name__ not in ("RSA", "RSA_pub"):
         raise Exception("Wrong type")
     except:
       raise Exception("n is not the right type:  " + str(n))
     self.key = n
   #: length of the key in bytes (used in blinding/unblinding)
   self.keyLen = len(self.key)
 def get_prefix(self):
   """@returns:  the beginning of the message from this relay"""
   #send back the PAR version first, so that people can deal with the message intelligently
   msg = Basic.write_byte(self.parVersion)
   #send back our hexid, so they know who this is from:
   msg += Basic.write_hexid(Globals.FINGERPRINT)
   return msg
示例#25
0
 def _reply(self, code):
     """Send an appropriately encoded reply to the client"""
     self.reply_func(Basic.write_byte(1) + Basic.write_byte(code))
     if code == RESPONSE_CODES["SUCCESS"]:
         log_msg("Account %s created for %s" %
                 (self.username, self.ipAddress))
     else:
         log_msg("Account creation attempt failed with code = %s" % (code))
示例#26
0
 def _read_header(self, data, msgName):
   #read the version
   version, data = Basic.read_byte(data)
   assert version == self.VERSION, "Bad version number: %s" % (version)
   #read the message type:
   msgType, data = Basic.read_byte(data)
   assert msgType == self.MESSAGES[msgName], "Bad message type: %s" % (msgType)
   return data
示例#27
0
 def _read_header(self, data, msgName):
     #read the version
     version, data = Basic.read_byte(data)
     assert version == self.VERSION, "Bad version number: %s" % (version)
     #read the message type:
     msgType, data = Basic.read_byte(data)
     assert msgType == self.MESSAGES[msgName], "Bad message type: %s" % (
         msgType)
     return data
示例#28
0
 def _port_test_failure(reason):
     #is this one of the errors that corresponds to unreachability?
     if Basic.exception_is_a(reason, [CannotListenError, TimeoutError]):
         return False
     #otherwise, we do not know the state of reachability (None signals that)
     #and log the error if necessary
     unexpectedException = not Basic.exception_is_a(reason, [ConnectError])
     if unexpectedException:
         log_ex(reason, "Unexpected failure while testing port")
     return None
示例#29
0
 def encrypt(self, msg):
   Basic.validate_type(msg, types.StringType)
   #make hmac
   mac = self.make_hmac(msg)
   
   inbuf = cStringIO.StringIO(mac + msg)
   outbuf = cStringIO.StringIO()
   outbuf.write(self.encryptCipher.update(inbuf.read()))
   outbuf.write(self.encryptCipher.final()) #no idea what this does because it is undocumented
   return outbuf.getvalue()
示例#30
0
 def _port_test_failure(reason):
     # is this one of the errors that corresponds to unreachability?
     if Basic.exception_is_a(reason, [CannotListenError, TimeoutError]):
         return False
     # otherwise, we do not know the state of reachability (None signals that)
     # and log the error if necessary
     unexpectedException = not Basic.exception_is_a(reason, [ConnectError])
     if unexpectedException:
         log_ex(reason, "Unexpected failure while testing port")
     return None
示例#31
0
    def encrypt(self, msg):
        Basic.validate_type(msg, types.StringType)
        #make hmac
        mac = self.make_hmac(msg)

        inbuf = cStringIO.StringIO(mac + msg)
        outbuf = cStringIO.StringIO()
        outbuf.write(self.encryptCipher.update(inbuf.read()))
        outbuf.write(self.encryptCipher.final()
                     )  #no idea what this does because it is undocumented
        return outbuf.getvalue()
示例#32
0
 def decrypt(self, msg, usePadding=True):
   """Decrypt msg (str) with key, return the result (as a string)
   @param msg: message to be decrypted
   @type msg: string
   @param usePadding: use padding if True, otherwise the message isn't padded (as for blinding)
   @type usePadding: bool
   @return: encrypted message as string"""
   Basic.validate_type(msg, types.StringType)
   if usePadding:
     return M2Crypto.m2.rsa_private_decrypt(self.key.rsa, msg, M2Crypto.RSA.pkcs1_padding)
   else:
     return M2Crypto.m2.rsa_private_decrypt(self.key.rsa, msg, M2Crypto.RSA.no_padding)
示例#33
0
 def read_request(self, data, host, transport):
   try:
     #read the header:
     data = self._read_header(data, "request")
     #read the protocol type:
     protocolType, data = Basic.read_byte(data)
     assert protocolType in self.TEST_TYPES, "Unknown echo protocol:  %s" % (protocolType)
     protocol = self.TEST_TYPES[protocolType]
     #read the port:
     port, data = Basic.read_short(data)
   except AssertionError, error:
     raise BadEchoMessageFormat(str(error))
示例#34
0
 def encrypt(self, msg):
   Basic.validate_type(msg, types.StringType)
   #make hmac
   mac = self.make_hmac(msg)
   inbuf = cStringIO.StringIO(mac + msg)
   outbuf = cStringIO.StringIO()
   outbuf.write(self.encryptCipher.update(inbuf.read()))
   outbuf.write(self.encryptCipher.final()) #no idea what this does because it is undocumented
   encryptedKeyConstructor = self.key.encrypt(self.randomData)
   encryptedKeyConstructor = struct.pack('!%ss'% BANK_KEY_LENGTH, encryptedKeyConstructor)
   msg = encryptedKeyConstructor+outbuf.getvalue()
   return msg
 def send_receipt_message(self, theirId, numTokens):
   """Send a new payment request after a successful payment
   @param theirId:  the id that the origin has associated with this payment
   @type  theirId:  int
   @param numTokens:  how many payment requests to send back to the origin
   @type  numTokens:  int
   @returns:  deferred (triggered when message is done sending)"""
   msg = self.get_prefix()
   msg += Basic.write_long(theirId)
   msg += Basic.write_byte(numTokens)
   for i in range(0, numTokens):
     msg += self.generate_payment_request_message()
   return self.send_direct_tor_message(msg, "receipt", False, 3)
示例#36
0
 def read_request(self, data, host, transport):
     try:
         #read the header:
         data = self._read_header(data, "request")
         #read the protocol type:
         protocolType, data = Basic.read_byte(data)
         assert protocolType in self.TEST_TYPES, "Unknown echo protocol:  %s" % (
             protocolType)
         protocol = self.TEST_TYPES[protocolType]
         #read the port:
         port, data = Basic.read_short(data)
     except AssertionError, error:
         raise BadEchoMessageFormat(str(error))
示例#37
0
 def send_receipt_message(self, theirId, numTokens):
     """Send a new payment request after a successful payment
 @param theirId:  the id that the origin has associated with this payment
 @type  theirId:  int
 @param numTokens:  how many payment requests to send back to the origin
 @type  numTokens:  int
 @returns:  deferred (triggered when message is done sending)"""
     msg = self.get_prefix()
     msg += Basic.write_long(theirId)
     msg += Basic.write_byte(numTokens)
     for i in range(0, numTokens):
         msg += self.generate_payment_request_message()
     return self.send_direct_tor_message(msg, "receipt", False, 3)
示例#38
0
 def _on_bank_stopped(self, result):
   Basic.validate_result(result, "bank_stopped")
   #now stop tor:
   log_msg("Waiting for Tor to shut down...", 3)
   d = None
   if self.torApp:
     d = self.torApp.stop()
   if not d:
     d = self._on_tor_stopped(True)
   else:
     d.addCallback(self._on_tor_stopped)
     d.addErrback(self._on_tor_stopped)
   return d
示例#39
0
 def _on_bank_stopped(self, result):
     Basic.validate_result(result, "bank_stopped")
     #now stop tor:
     log_msg("Waiting for Tor to shut down...", 3)
     d = None
     if self.torApp:
         d = self.torApp.stop()
     if not d:
         d = self._on_tor_stopped(True)
     else:
         d.addCallback(self._on_tor_stopped)
         d.addErrback(self._on_tor_stopped)
     return d
示例#40
0
 def decrypt(self, encryptedMsg):
   Basic.validate_type(encryptedMsg, types.StringType)
   #decrypt the message
   inbuf = cStringIO.StringIO(encryptedMsg)
   outbuf = cStringIO.StringIO()
   outbuf.write(self.decryptCipher.update(inbuf.read()))
   outbuf.write(self.decryptCipher.final())
   msg = outbuf.getvalue()
   mac = msg[:32]
   msg = msg[32:]
   #validate the HMAC
   if self.make_hmac(msg) != mac:
     raise Exception('HMAC does not authenticate, is something bad going on?')
   return msg
示例#41
0
 def encrypt(self, msg):
     Basic.validate_type(msg, types.StringType)
     #make hmac
     mac = self.make_hmac(msg)
     inbuf = cStringIO.StringIO(mac + msg)
     outbuf = cStringIO.StringIO()
     outbuf.write(self.encryptCipher.update(inbuf.read()))
     outbuf.write(self.encryptCipher.final()
                  )  #no idea what this does because it is undocumented
     encryptedKeyConstructor = self.key.encrypt(self.randomData)
     encryptedKeyConstructor = struct.pack('!%ss' % BANK_KEY_LENGTH,
                                           encryptedKeyConstructor)
     msg = encryptedKeyConstructor + outbuf.getvalue()
     return msg
示例#42
0
 def _on_applications_stopped(self, result):
     Basic.validate_result(result, "applications_stopped")
     self.isReady = False
     HTTPClient.stop_all()
     #now stop the bank:
     log_msg("Waiting for the bank to shut down...", 3)
     d = None
     if self.bankApp:
         d = self.bankApp.stop()
     if not d:
         d = self._on_bank_stopped(True)
     else:
         d.addCallback(self._on_bank_stopped)
         d.addErrback(self._on_bank_stopped)
     return d
示例#43
0
 def _on_applications_stopped(self, result):
   Basic.validate_result(result, "applications_stopped")
   self.isReady = False
   HTTPClient.stop_all()
   #now stop the bank:
   log_msg("Waiting for the bank to shut down...", 3)
   d = None
   if self.bankApp:
     d = self.bankApp.stop()
   if not d:
     d = self._on_bank_stopped(True)
   else:
     d.addCallback(self._on_bank_stopped)
     d.addErrback(self._on_bank_stopped)
   return d
示例#44
0
 def decrypt(self, encryptedMsg):
     Basic.validate_type(encryptedMsg, types.StringType)
     #decrypt the message
     inbuf = cStringIO.StringIO(encryptedMsg)
     outbuf = cStringIO.StringIO()
     outbuf.write(self.decryptCipher.update(inbuf.read()))
     outbuf.write(self.decryptCipher.final())
     msg = outbuf.getvalue()
     mac = msg[:32]
     msg = msg[32:]
     #validate the HMAC
     if self.make_hmac(msg) != mac:
         raise Exception(
             'HMAC does not authenticate, is something bad going on?')
     return msg
示例#45
0
 def connectionLost(self, reason):
   
   peerId = self.readable_id
   try:
     peerId = peerId.decode("hex")
   #since some peers send in ASCII instead of hex, oh well
   except TypeError:
     pass
     
   if not self.btApp.is_ready() and not self.btApp.is_starting():
     return
   
   if self.read == self._read2:
     stage = 'post handshake'
   elif self.encrypted:
     stage = 'before %s' % (self.next_func)
   else:
     stage = 'during handshake'
   log_msg("Lost connection to %s (%s client -- cm: %s) %s." % (Basic.clean(peerId), self.get_client_name(), self.cryptmode, stage), 3, "btconn")
   
   if self.Encoder:
     if self.Encoder.connections and self in self.Encoder.connections:
       self.sever()
     #maybe we should retry with encryption?
     if self.next_func == self.read_header:
       #did we try connecting via plaintext?
       if not self.supposedlyEncrypted:
         log_msg("Ok, retrying with encryption...", 3, "btconn")
         #ok, lets retry this connection but WITH encryption this time
         self.Encoder.start_connection((self.get_ip(), self.get_port()), self.id, True)
       else:
         log_msg("Failed with encryption too", 3, "btconn")
   else:
     self.closed = True
示例#46
0
 def error(failure):
   if not self.is_done():
     if Basic.exception_is_a(failure, [TorCtl.TorCtlClosed, TorCtl.ErrorReply]):
       log_msg("Failed to create PAR client, closing", 1, "circuit")
     else:
       log_ex(failure, "Unexpected failure while starting circuit")
     self.on_done()
示例#47
0
  def socks_method_CONNECT (self):
    # Check if we have ip address or domain name
    #
    log_msg("socks_method_CONNECT host = " + Basic.clean(self.host), 4, "socks")

    # The FaceTime SOCKS5 proxy treats IP addr the same way as hostname
    # if _ip_regex.match (self.host):
    #     # we have dotted quad IP address
    #     addressType = 1
    #     address = socket.inet_aton (self.host)
    # else:
    #     # we have host name
    #     address = self.host
    #     addressType = 3

    address = self.host
    addressType = 3
    addressLen = len(address)

    #Protocol version=5, Command=1 (CONNECT), Reserved=0
    #command = struct.pack ("!BBBB", 5, 1, 0, addressType)

    command = struct.pack ("!BBBBB", 5, 1, 0, addressType, addressLen)
    portstr = struct.pack ("!H", self.port)

    self.transport.write (command + address + portstr)
    self.state = "gotConnectReply"
示例#48
0
 def on_failure(reason):
     #is this an expected failure for a single UDP reply test?
     if Basic.exception_is_a(
             reason, [CannotListenError, ConnectError, TimeoutError]):
         return
     #otherwise, log the error
     log_ex(reason, "Unexpected failure while testing UDP replies")
示例#49
0
 def get_payment_stream(self, msg):
     """Determine which PaymentStream should handle this message
 @param msg:  the message, reads the hexid off the front
 @type  msg:  str
 @returns:  PaymentStream"""
     hexId, msg = Basic.read_hexid(msg)
     return self.paymentStreams[hexId], msg
示例#50
0
 def stringReceived(self, data):
   self.responseReceived = True
   self.factory.gotResponse = True
   data = self.factory.bank.decrypt_message(data)
   log_msg("ACoin DEPOSIT response received.", 4)
   (newBalance, interval, expiresCurrent, expiresNext), returnSlip = Basic.read_message('!IIII', data)
   self.factory.bank.on_new_info(newBalance, interval, expiresCurrent, expiresNext)
   returnSlip = list(struct.unpack('c'*len(self.factory.coins), returnSlip))
   for i in range(0, len(self.factory.coins)):
     coin = self.factory.coins[i]
     status = returnSlip[i]
     gotAcceptableResponse = True
     badACoin = True
     if status == "0":
       badACoin = False
     elif status == "3":
       log_msg("ACoin deposit failed.  Some node must have double-spent.", 1)
     elif status == "2":
       log_msg("ACoin deposit failed.  You apparently already sent this acoin.", 1)
     elif status == "1":
       log_msg("ACoin deposit failed.  ACoin was not valid?  %s" % (repr(coin.write_binary())), 0)
     else:
       log_msg("Bank returned unknown status message:  %s" % (status), 0)
       gotAcceptableResponse = False
     if badACoin:
       #close the circuit, they're trying to cheat us!
       if coin.originCircuit:
         coin.originCircuit.close()
   self.transport.loseConnection()
示例#51
0
def get_default_gateway():
    #TODO:  execing route print is probably a better idea here
    try:
        strComputer = "."
        objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
        objSWbemServices = objWMIService.ConnectServer(strComputer,
                                                       "root\cimv2")
        colItems = objSWbemServices.ExecQuery(
            "Select * from Win32_NetworkAdapterConfiguration")
        gateways = []
        for objItem in colItems:
            z = objItem.DefaultIPGateway
            if z:
                for x in z:
                    gateways.append(x)
        if len(gateways) > 1:
            log_msg(
                "Why are there multiple gateways?  :(  %s" %
                (Basic.clean(gateways)), 2)
        elif len(gateways) == 0:
            return None
        return gateways.pop(0)
    except Exception, e:
        log_ex(e, "Failed to get default gateway")
        return "192.168.1.1"
示例#52
0
 def connectionMade(self):
   log_msg('Sending login message...', 2)
   signedFingerprint = Globals.PRIVATE_KEY.sign(Globals.FINGERPRINT)
   publicKey = Basic.long_to_bytes(long(Globals.PRIVATE_KEY.n), 128)
   protocol = 1
   msg = struct.pack('!B128s50s50s128s', protocol, signedFingerprint, self.factory.username, self.factory.password, publicKey)
   self.sendString(msg)
示例#53
0
 def on_login_failure(self, bankApp, err, optionalServerResponse=None):
     text = None
     self.dia.window.raise_()
     eType = type(err)
     if eType is BadLoginPasswordError:
         text = str(err)
     elif eType is Failure:
         eType = type(err.value)
         if issubclass(eType, ConnectionDone) or issubclass(
                 eType, ConnectionLost):
             text = "The login server is temporarily offline.  We are sorry for the inconvenience.  Please try again later."
     if not text:
         text = "Login failed for an unknown reason.  Please try again."
     text += "\nNOTE: You must restart the program to change users."
     if optionalServerResponse:
         force, optionalServerResponse = Basic.read_byte(
             optionalServerResponse)
         #concatenate
         if force is 0:
             text += '\n' + optionalServerResponse
         #nuke it
         else:
             text = optionalServerResponse
     self.label.set_text(text)
     self.nameEntry.set_sensitive(True)
     self.pwEntry.set_sensitive(True)
     self.loginButton.set_sensitive(True)
     self.quitButton.set_sensitive(True)
 def get_payment_stream(self, msg):
   """Determine which PaymentStream should handle this message
   @param msg:  the message, reads the hexid off the front
   @type  msg:  str
   @returns:  PaymentStream"""
   hexId, msg = Basic.read_hexid(msg)
   return self.paymentStreams[hexId], msg
 def handle_setup_reply(self, msg):
   """Handle a setup reply.  Send it to the appropriate PaymentStream, then check if they are all done"""
   log_msg("circ=%d:  PAR setup done." % (self.circ.id), 3, "par")
   #unpack the messages:
   forwardParVersion, msg = Basic.read_byte(msg)
   if forwardParVersion < self.parVersion:
     self.parVersion = forwardParVersion
   payStream, msg = self.get_payment_stream(msg)
   payStream.handle_setup_reply(forwardParVersion, msg)
   if self.all_setup_done():
     initialTokensDeferred = self.add_start_tokens()
     #this usually happens if the circuit is already closed, if not, an exception will already be logged
     if not initialTokensDeferred:
       self.circ.on_done()
       return
     def initial_tokens_added(result):
       self.circ.initialTokensAdded = True
       self._add_tokens_callback(result, PaymentMessageHandler.START_READ_TOKENS, PaymentMessageHandler.START_WRITE_TOKENS)
       return result
     initialTokensDeferred.addCallback(initial_tokens_added)
     initialTokensDeferred.addErrback(self.generic_error_handler)
     self.setupDone = True
     #send any payment requests that are waiting on the setup:
     reads = self.queuedReadTokens
     writes = self.queuedWriteTokens
     self.queuedReadTokens = 0
     self.queuedWriteTokens = 0
     if self.queuedReadTokens or self.queuedWriteTokens:
       self.send_payment_request(reads, writes)
     self.circ.on_par_ready()
示例#56
0
 def response(result):
     if result:
         read, write = result
         log_msg(
             "%s paid us %s for exit stream, now %d / %d" %
             (Basic.clean(self.baseCircuit.prevHexId[:4]),
              creditsEarned, read, write), 3, "par")