コード例 #1
0
    def __init__(self, walletMessageType, entity, coins):
        self.walletMessageType = walletMessageType
        self.entity = entity

        #self.isMessageType = isMessageType
        if not self.walletMessageType.globals.status.can(
                MessageStatuses.PrivilegeClient):
            raise MessageError(
                'given messageType does not have PrivilegeClient')

        class messages:
            pass

        self.walletMessages = messages()
        self.isMessages = messages()
        del messages

        # All the responses we can get from the IS
        self.isMessages.DKP = DSDBKeyPass(self.resumeConversation)

        # All the responses we can get from the other wallet
        self.walletMessages.BR = BlankReject(self.resumeConversation)
        self.walletMessages.BF = BlankFailure(self.resumeConversation)
        self.walletMessages.BA = BlankAccept(self.resumeConversation)
        self.walletMessages.CR = CoinsReject(self.resumeConversation)
        self.walletMessages.CA = CoinsAccept(self.resumeConversation)

        # Add handlers for all the messages using walletMessages if continues conversation
        self.walletMessageType.addMessageHandler(BlankPresent())
        self.walletMessageType.addMessageHandler(self.walletMessages.BR)
        self.walletMessageType.addMessageHandler(self.walletMessages.BF)
        self.walletMessageType.addMessageHandler(self.walletMessages.BA)
        self.walletMessageType.addMessageHandler(CoinsRedeem())
        self.walletMessageType.addMessageHandler(self.walletMessages.CR)
        self.walletMessageType.addMessageHandler(self.walletMessages.CA)

        self.coins = coins

        class state:
            pass

        self.persistant = state()
        del state

        self.lastMessageIdentifier = None
コード例 #2
0
    def checkValidObfuscatedBlanksAndKnownIssuers(self, blanks, cdds,
                                                  mintingKeysKeyID):
        failure = False
        failures = []

        if len(blanks) == 0:
            raise MessageError('Need atleast one blank!')

        for b in blanks:
            if not self.checkValidObfuscatedBlank(b, cdds, mintingKeysKeyID):
                failure = True
                failures.append((b, 'Malformed blank'))
            elif not self.checkKnownIssuer(b, self.manager.entity.cdds):
                failure = True
                failures.append((b, 'Unknown issuer'))

        if failure:
            return 'FAILED', failures
        else:
            return 'PASS', None
コード例 #3
0
    def __init__(self, messageType, entity):
        self.messageType = messageType
        self.entity = entity

        if not self.messageType.globals.status.can(MessageStatuses.PrivilegeServer):
            raise MessageError('given messageType does not have PrivilegeServer')
        
        class messages: pass
        self.messages = messages
        del messages

        #create conversation starting messages to trigger self.startConversation
        self.messages.DKR = DSDBKeyRequest(self.startConversation)
        self.messages.FMR = FetchMintedRequest(self.startConversation)
        self.messages.MR = MintRequest(self.startConversation)
        self.messages.MKFD = MintingKeyFetchDenomination(self.startConversation)
        self.messages.MKFK = MintingKeyFetchKeyID(self.startConversation)
        self.messages.RCR = RedeemCoinsRequest(self.startConversation)

        #add all of our special mesasges as MessageHandlers
        self.messageType.addMessageHandler(self.messages.DKR)
        self.messageType.addMessageHandler(self.messages.FMR)
        self.messageType.addMessageHandler(self.messages.MR)
        self.messageType.addMessageHandler(self.messages.MKFD)
        self.messageType.addMessageHandler(self.messages.MKFK)
        self.messageType.addMessageHandler(self.messages.RCR)
        
        #everything that can't start a conversation
        self.messageType.addMessageHandler(MintingKeyPass())
        self.messageType.addMessageHandler(MintingKeyFailure())
        self.messageType.addMessageHandler(MintReject())
        self.messageType.addMessageHandler(MintAccept())
        self.messageType.addMessageHandler(FetchMintedFailure())
        self.messageType.addMessageHandler(FetchMintedWait())
        self.messageType.addMessageHandler(FetchMintedAccept())
        self.messageType.addMessageHandler(DSDBKeyPass())
        self.messageType.addMessageHandler(RedeemCoinsReject())
        self.messageType.addMessageHandler(RedeemCoinsAccept())

        self.manager = None
コード例 #4
0
    def request(self, request_id, blinds, minting_keys_key_id, now):
        failure = False
        failures = []

        if len(blinds) == 0:
            raise MessageError('request %s has no blinds' % request_id)

        for b in blinds:
            type, result = self.testBlind(b, minting_keys_key_id, now)
            if type == 'ACCEPT':
                pass
            elif type == 'REJECT':
                failure = True
                key_id, blind = b
                failures.append( (blind, result) )

        if failure:
            return 'REJECT', failures

        self.acceptBlinds(request_id, blinds)

        return 'ACCEPT', request_id
コード例 #5
0
    def testBlank(self, blank, dsdb_key_id, dsdb_key, dsdb_database,
                  dsdb_requests, minting_keys_key_id, now):
        mint_key_id, obfuscated = blank

        serial = self.unobfuscate(obfuscated, dsdb_key)
        if serial == 'Decryption of serial failed':
            return 'REJECT', 'Decryption of serial failed'

        if not minting_keys_key_id.has_key(
                mint_key_id
        ) or not minting_keys_key_id[mint_key_id].verify_time(now):
            return 'REJECT', 'Key ID of blank is unknown or expired'

        if dsdb_database.has_key(mint_key_id):
            if dsdb_database[mint_key_id].has_key(serial):
                result = dsdb_database[mint_key_id][serial]
                if result[0] == 'Spent':
                    return 'REJECT', 'Serial already redeemed'
                elif result[0] == 'Locked':
                    string, time_lock_expires, transaction_id = result
                    if self.timeNow() <= time_lock_expires:
                        return 'REJECT', 'Serial locked (not spent)'
                    else:
                        # the serial is no longer locked. unlock it
                        time_transaction_lock_expires, keysAndSerials = dsdb_requests[
                            transaction_id]
                        for key, ser in keysAndSerials:
                            del dsdb_database[key][ser]
                        del dsdb_requests[trasaction_id]
                        return 'ACCEPT', serial
                else:
                    raise MessageError('Got an impossible state: %s' %
                                       result[0])
            else:  # we have never seen this serial
                return 'ACCEPT', serial
        else:  # we have never seen this valid mint_key_id
            return 'ACCEPT', serial
コード例 #6
0
    def handle(self, message):
        if not isinstance(message, CoinsRedeem) and not isinstance(
                message, CoinsAccept) and not isinstance(message, CoinsReject):
            if message.messageLayer.globals.lastState == MessageHello:  # we are now on a different message. Oops.
                raise MessageError(
                    'Coins should have already been removed. It was not. Very odd. Message: %s LastMessage: %s'
                    % (message.identifier,
                       message.messageLayer.globals.lastState))
            else:
                raise MessageError(
                    'We somehow called Coins.handle() but cannot be there. Message: %s'
                    % message.identifier)

        if isinstance(message, CoinsRedeem):
            self.coins = self.manager.walletMessageType.persistant.coins
            self.manager.persistant.coins = self.coins

            type, result = self.verifyCoins(
                self.coins, self.manager.entity.minting_keys_key_id,
                self.manager.persistant.blanks,
                self.manager.persistant.dsdb_certificate,
                self.manager.entity.cdds)

            if type == 'ACCEPT':
                self.dsdb_lock = self.manager.persistant.dsdb_lock
                if not self.validDSDBLock(self.dsdb_lock, self.timeNow()):
                    raise MessageError(
                        'Invalid DSDB lock. You are an idiot for letting this happen.'
                    )

                self._createAndOutputWallet(CoinsAccept)

            elif type == 'REJECT':
                self.manager.walletMessageType.persistant.reason = result

                self._createAndOutputWallet(CoinsReject)

            else:
                raise MessageError('Went to an impossible type: %s' % type)

        elif isinstance(message, CoinsReject):
            # We are done. We should be nice though and Unlock the coins
            if self.validDSDBLock(
                    self.manager.dsdbMessageType.persistant.dsdb_lock,
                    self.timeNow()):

                # FIXME: The else below removes two callbacks. Which one of them is wrong?
                self.manager.walletMessageType.removeCallback(self.handle)
                self._createAndOutputDSDB(UnlockCoinsRequest)
            else:  # the DSDB lock has already expired.
                self.manager.walletMessageType.removeCallback(self.handle)
                self.manager.isMessageType.removeCallback(self.handle)
                self.manager.failure(self, message)

        elif isinstance(message, CoinsAccept):

            #figure out what request ID we will be using
            self.manager.persistant.mintRequestID = self.newRequestID()
            self.manager.persistant.target = self.manager.persistant.mintRequestID  # the target and the mint request should be the same methinks
            #self.manager.persistant.target = self.newTarget()

            if self.isRequiresMRbeforeRCR:
                self.manager.isMessageType.persistant.request_id = self.manager.persistant.mintRequestID

                # setup blinds only for the MintRequest message
                blinds = []
                for b in self.manager.persistant.mintBlanks:
                    b.blind_blank(
                        self.manager.entity.cdds,
                        self.manager.entity.minting_keys_key_id
                    )  # XXX should this be in makeBlanks() instead?
                    blinds.append((b.key_identifier, b.blind_value))
                self.manager.isMessageType.persistant.blinds = blinds

                self.manager.walletMessageType.removeCallback(self.handle)
                self._createAndOutputIS(MintRequest)

            else:
                self.manager.isMessageType.persistant.trasaction_id = self.manager.persistant.mintRequestID
                self.manager.isMessageType.persistant.target = self.manager.persistant.target
                self.manager.isMessageType.persistant.coins = self.manager.persistant.coins

                self.manager.isMessageType.removeCallback(self.handle)
                self._createAndOutput(RedeemCoinsRequest)

        self._setLastState(message.identifier)
コード例 #7
0
    def __init__(self, walletMessageType, entity):

        # isMessageType, dsdbMessageType, amount):
        self.walletMessageType = walletMessageType
        self.entity = entity

        #self.isMessageType = isMessageType
        #self.dsdbMessageType = dsdbMessageType
        if not self.walletMessageType.globals.status.can(
                MessageStatuses.PrivilegeServer):
            raise MessageError(
                'given messageType does not have PrivilegeServer')

        class messages:
            pass

        self.walletMessages = messages()
        self.isMessages = messages()
        self.dsdbMessages = messages()
        del messages

        # All the responses we can get from the IS (we are client)
        #self.isMessages.MKP = MintingKeyPass(self.resumeConversation) # this are being handled elsewhere (BlankAndMintingKey)
        #self.isMessages.MKF = MintingKeyFailure(self.resumeConversation) # this is being handled elsewhere (BlankAndMintingKey)
        self.isMessages.MA = MintAccept(self.resumeConversation)
        self.isMessages.MR = MintReject(self.resumeConversation)
        self.isMessages.FMF = FetchMintedFailure(self.resumeConversation)
        self.isMessages.FMW = FetchMintedWait(self.resumeConversation)
        self.isMessages.FMA = FetchMintedAccept(self.resumeConversation)
        self.isMessages.RCR = RedeemCoinsReject(self.resumeConversation)
        self.isMessages.RCA = RedeemCoinsAccept(self.resumeConversation)

        # All messages can get from the other wallet (we are server)
        self.walletMessages.CR = CoinsRedeem(self.resumeConversation)
        self.walletMessages.BP = BlankPresent(self.resumeConversation)

        # All the responses we can get from the DSDB
        self.dsdbMessages.LCA = LockCoinsAccept(self.resumeConversation)
        self.dsdbMessages.LCF = LockCoinsFailure(self.resumeConversation)
        self.dsdbMessages.UCP = UnlockCoinsPass(self.resumeConversation)
        self.dsdbMessages.UCF = UnlockCoinsFailure(self.resumeConversation)

        # Add handlers for all the messages using walletMessages if starts conversation
        self.walletMessageType.addMessageHandler(self.walletMessages.BP)
        self.walletMessageType.addMessageHandler(BlankReject())
        self.walletMessageType.addMessageHandler(BlankFailure())
        self.walletMessageType.addMessageHandler(BlankAccept())
        self.walletMessageType.addMessageHandler(self.walletMessages.CR)
        self.walletMessageType.addMessageHandler(CoinsReject())
        self.walletMessageType.addMessageHandler(CoinsAccept())

        class state:
            __slots__ = (
                'blanks',  # the blanks given in BlankPresent
                'dsdb_certificate',  # the dsdb certificate given in BlankPresent
                'mintBlanks',  # blanks we created for use with a MintRequest (to make new coins)
                'dsdb_lock',  # the lock we receive when we perform a LockRequest
                'coins',  # the coins received from the other wallet with a CoinsRedeem
                'mintingKeysKeyID',  # the minting key certificates for all coins received
                'mintingKeysDenomination',  # the minting key certificates for all denominations of all coins received
                'mintRequestID',  # the request id generated for the MintRequest
                'target',  # the target for the MintRequest
                'signatures',  # the signatures returned from IS via FetchMintedRequest
                'newCoins',  # our newly minted coins after
                'mintingFailures'  # any coins where the signature was invalid. Nothing we can really do with this though.
            )

        self.persistant = state()
        del state

        self.lastMessageIdentifier = None
コード例 #8
0
    def getMintingKeyAndContinue(self):
        if len(self.neededKeyIDs) > 0:  # Get a key_id
            self.mkfType = self.mintingKeysKeyID
            self.mkfSearch = self.neededKeyIDs.pop()
            self.mkfReturn = self.getMintingKeyAndContinue

            self.manager.isMessageType.persistant.key_id = self.mkfSearch
            self._createAndOutputIS(MintingKeyFetchKeyID)

        elif len(self.neededDenominations) > 0:  #get a denomination
            self.mkfType = self.mintingKeysDenomination
            self.mkfSearch = self.neededDenominations.pop()
            self.mkfReturn = self.getMintingKeyAndContinue

            self.manager.isMessageType.persistant.denomination = self.mkfSearch
            self._createAndOutputIS(MintingKeyFetchDenomination)

        else:  # We have all the keys we need. Make new blanks. Verify blanks against DSDB (For now, we don't support trying to do a MintRequest right now
            # Add all the keys to the entity
            self.manager.entity.addMintingKeys(
                self.collapseMintingKeys(self.mintingKeysKeyID,
                                         self.mintingKeysDenomination))

            # Make blanks
            self.manager.persistant.mintBlanks = self.makeBlanks(
                self.blanks, self.minting_denominations,
                self.mintingKeysDenomination)
            self.manager.persistant.mintingKeysDenomination = self.mintingKeysDenomination
            self.manager.persistant.mintingKeysKeyID = self.mintingKeysKeyID

            #Verify blanks
            type, result = self.checkValidObfuscatedBlanksAndKnownIssuers(
                self.blanks, self.manager.entity.cdds,
                self.manager.entity.minting_keys_key_id)
            if type == 'PASS':
                # setup the requirements for the LockCoinsRequest
                self.manager.dsdbMessageType.persistant.key_id = self.dsdb_certificate.key_identifier
                self.manager.dsdbMessageType.persistant.transaction_id = self.makeTransactionID(
                )

                # the message to the dsdb, LOCK_COINS_REQUEST only gets sent the obfuscated serial and the minting_key. Get that information
                self.lockRequestBlanks = []
                for b in self.blanks:
                    self.lockRequestBlanks.append((b.key_identifier, b.serial))
                self.manager.dsdbMessageType.persistant.blanks = self.lockRequestBlanks

                # setup future minting
                self.manager.isMessageType.persistant.transaction_id = self.manager.dsdbMessageType.persistant.transaction_id  # it's the same id for a different thing
                self.manager.isMessageType.persistant.blanks = self.manager.persistant.mintBlanks

                # The result will be handled by a different Handler. Remove ourselves as a callback
                self.manager.walletMessageType.removeCallback(self.handle)
                self.manager.isMessageType.removeCallback(self.handle)

                # And finally output
                self._createAndOutputDSDB(LockCoinsRequest)
            elif type == 'FAILED':  # Send a BlankReject
                self.manager.walletMessageType.persistant.reason = result
                self._createAndOutputWallet(BlankReject)
            else:
                raise MessageError('Received an impossible type: %s' % type)
コード例 #9
0
    def handle(self, message):
        if not isinstance(message, BlankPresent) and not isinstance(message, MintingKeyFetchDenomination) and not \
                isinstance(message, MintingKeyFailure) and not isinstance(message, MintingKeyPass) and not isinstance(message, MintingKeyFetchKeyID):
            if message.messageLayer.globals.lastState == MessageHello:  # we are now on a different message. Oops.
                raise MessageError(
                    'BlankAndMintingKey should have already been removed. It was not. Very odd. Message: %s LastWalletMessage: %s LastISMessage: %s'
                    % (message.identifier,
                       self.manager.walletMessageType.globals.lastState,
                       self.manager.isMessageType.globals.lastState))
            else:
                raise MessageError(
                    'We somehow called BlankAndMintingKey.handle() but cannot be there. Message: %s'
                    % message.identifier)

        if isinstance(message, BlankPresent):
            self._verifyLastState([None])

            self.dsdb_certificate = self.manager.walletMessageType.persistant.dsdb_certificate
            self.blanks = self.manager.walletMessageType.persistant.blanks

            self.manager.persistant.blanks = self.blanks
            self.manager.persistant.dsdb_certificate = self.dsdb_certificate

            # connect to IS
            # FIXME: Gah. What a hack. Only supports one IS
            result = self.getCDD(self.manager.entity.cdds, self.blanks)
            if result != 'Unknown issuer':
                self.manager.connectToIS(result)

                # add the required callback
                self.manager.isMessageType.addCallback(self.handle)

                # connect to dsdb
                self.manager.connectToDSDB(
                    self.manager.persistant.dsdb_certificate)

                # get list of denominations we are minting
                #FIXME: This is a spot where we assume only one cdd
                self.minting_denominations = self.getMintingDenominations(
                    self.blanks, self.manager.entity.cdds)

                # self.performMagic is a special function doing anything we want.
                self.performMagic(self.blanks, self.dsdb_certificate,
                                  self.minting_denominations)
            else:
                self.manager.walletMessageType.persistant.reason = result
                self._createAndOutputWallet(BlankReject)

        elif isinstance(message, MintingKeyPass):  # we've received a key
            minting_certificate = self.manager.isMessageType.persistant.minting_certificate
            print 'received minting_certificate: %s' % str(minting_certificate)
            self.mkfType[self.mkfSearch] = minting_certificate

            self.mkfReturn()

        elif isinstance(message, MintingKeyFailure):
            self.reason = message.messageLayer.persistant.reason
            self.manager.failure(message, self)

        elif isinstance(message, MintingKeyFetchKeyID) or isinstance(
                message, MintingKeyFetchDenomination):
            self._verifyLastState(['BlankAndMintingKey'
                                   ])  # make sure we started in here
            # but we did send these messages, so do nothing else

        self._setLastState(
            'BlankAndMintingKey'
        )  # There are many different ways to exit this. Just cover them all.