⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chaffing.py

📁 python的加密库
💻 PY
字号:
"""This file implements the chaffing algorithm.Winnowing and chaffing is a technique for enhancing privacy without requiringstrong encryption.  In short, the technique takes a set of authenticatedmessage blocks (the wheat) and adds a number of chaff blocks which haverandomly chosen data and MAC fields.  This means that to an adversary, thechaff blocks look as valid as the wheat blocks, and so the authenticationwould have to be performed on every block.  By tailoring the number of chaffblocks added to the message, the sender can make breaking the messagecomputationally infeasible.  There are many other interesting properties ofthe winnow/chaff technique.For example, say Alice is sending a message to Bob.  She packetizes themessage and performs an all-or-nothing transformation on the packets.  Thenshe authenticates each packet with a message authentication code (MAC).  TheMAC is a hash of the data packet, and there is a secret key which she mustshare with Bob (key distribution is an exercise left to the reader).  She thenadds a serial number to each packet, and sends the packets to Bob.Bob receives the packets, and using the shared secret authentication key,authenticates the MACs for each packet.  Those packets that have bad MACs aresimply discarded.  The remainder are sorted by serial number, and passedthrough the reverse all-or-nothing transform.  The transform means that aneavesdropper (say Eve) must acquire all the packets before any of the data canbe read.  If even one packet is missing, the data is useless.There's one twist: by adding chaff packets, Alice and Bob can make Eve's jobmuch harder, since Eve now has to break the shared secret key, or try everycombination of wheat and chaff packet to read any of the message.  The coolthing is that Bob doesn't need to add any additional code; the chaff packetsare already filtered out because their MACs don't match (in all likelihood --since the data and MACs for the chaff packets are randomly chosen it ispossible, but very unlikely that a chaff MAC will match the chaff data).  AndAlice need not even be the party adding the chaff!  She could be completelyunaware that a third party, say Charles, is adding chaff packets to hermessages as they are transmitted.For more information on winnowing and chaffing see this paper:Ronald L. Rivest, "Chaffing and Winnowing: Confidentiality without Encryption"http://theory.lcs.mit.edu/~rivest/chaffing.txt"""__revision__ = "$Id: Chaffing.py,v 1.7 2003/02/28 15:23:21 akuchling Exp $"from Crypto.Util.number import bytes_to_longclass Chaff:    """Class implementing the chaff adding algorithm.    Methods for subclasses:            _randnum(size):                Returns a randomly generated number with a byte-length equal                to size.  Subclasses can use this to implement better random                data and MAC generating algorithms.  The default algorithm is                probably not very cryptographically secure.  It is most                important that the chaff data does not contain any patterns                that can be used to discern it from wheat data without running                the MAC.    """    def __init__(self, factor=1.0, blocksper=1):        """Chaff(factor:float, blocksper:int)        factor is the number of message blocks to add chaff to,        expressed as a percentage between 0.0 and 1.0.  blocksper is        the number of chaff blocks to include for each block being        chaffed.  Thus the defaults add one chaff block to every        message block.  By changing the defaults, you can adjust how        computationally difficult it could be for an adversary to        brute-force crack the message.  The difficulty is expressed        as:            pow(blocksper, int(factor * number-of-blocks))        For ease of implementation, when factor < 1.0, only the first        int(factor*number-of-blocks) message blocks are chaffed.        """        if not (0.0<=factor<=1.0):            raise ValueError, "'factor' must be between 0.0 and 1.0"        if blocksper < 0:            raise ValueError, "'blocksper' must be zero or more"        self.__factor = factor        self.__blocksper = blocksper    def chaff(self, blocks):        """chaff( [(serial-number:int, data:string, MAC:string)] )        : [(int, string, string)]        Add chaff to message blocks.  blocks is a list of 3-tuples of the        form (serial-number, data, MAC).        Chaff is created by choosing a random number of the same        byte-length as data, and another random number of the same        byte-length as MAC.  The message block's serial number is        placed on the chaff block and all the packet's chaff blocks        are randomly interspersed with the single wheat block.  This        method then returns a list of 3-tuples of the same form.        Chaffed blocks will contain multiple instances of 3-tuples        with the same serial number, but the only way to figure out        which blocks are wheat and which are chaff is to perform the        MAC hash and compare values.        """        chaffedblocks = []        # count is the number of blocks to add chaff to.  blocksper is the        # number of chaff blocks to add per message block that is being        # chaffed.        count = len(blocks) * self.__factor        blocksper = range(self.__blocksper)        for i, wheat in map(None, range(len(blocks)), blocks):            # it shouldn't matter which of the n blocks we add chaff to, so for            # ease of implementation, we'll just add them to the first count            # blocks            if i < count:                serial, data, mac = wheat                datasize = len(data)                macsize = len(mac)                addwheat = 1                # add chaff to this block                for j in blocksper:                    import sys                    chaffdata = self._randnum(datasize)                    chaffmac = self._randnum(macsize)                    chaff = (serial, chaffdata, chaffmac)                    # mix up the order, if the 5th bit is on then put the                    # wheat on the list                    if addwheat and bytes_to_long(self._randnum(16)) & 0x40:                        chaffedblocks.append(wheat)                        addwheat = 0                    chaffedblocks.append(chaff)                if addwheat:                    chaffedblocks.append(wheat)            else:                # just add the wheat                chaffedblocks.append(wheat)        return chaffedblocks    def _randnum(self, size):        # TBD: Not a very secure algorithm.        # TBD: size * 2 to work around possible bug in RandomPool        from Crypto.Util import randpool        import time        pool = randpool.RandomPool(size * 2)        while size > pool.entropy:            pass        # we now have enough entropy in the pool to get size bytes of random        # data... well, probably        return pool.get_bytes(size)if __name__ == '__main__':    text = """\We hold these truths to be self-evident, that all men are created equal, thatthey are endowed by their Creator with certain unalienable Rights, that amongthese are Life, Liberty, and the pursuit of Happiness. That to secure theserights, Governments are instituted among Men, deriving their just powers fromthe consent of the governed. That whenever any Form of Government becomesdestructive of these ends, it is the Right of the People to alter or toabolish it, and to institute new Government, laying its foundation on suchprinciples and organizing its powers in such form, as to them shall seem mostlikely to effect their Safety and Happiness."""    print 'Original text:\n=========='    print text    print '=========='    # first transform the text into packets    blocks = [] ; size = 40    for i in range(0, len(text), size):        blocks.append( text[i:i+size] )    # now get MACs for all the text blocks.  The key is obvious...    print 'Calculating MACs...'    from Crypto.Hash import HMAC, SHA    key = 'Jefferson'    macs = [HMAC.new(key, block, digestmod=SHA).digest()            for block in blocks]    assert len(blocks) == len(macs)    # put these into a form acceptable as input to the chaffing procedure    source = []    m = map(None, range(len(blocks)), blocks, macs)    print m    for i, data, mac in m:        source.append((i, data, mac))    # now chaff these    print 'Adding chaff...'    c = Chaff(factor=0.5, blocksper=2)    chaffed = c.chaff(source)    from base64 import encodestring    # print the chaffed message blocks.  meanwhile, separate the wheat from    # the chaff    wheat = []    print 'chaffed message blocks:'    for i, data, mac in chaffed:        # do the authentication        h = HMAC.new(key, data, digestmod=SHA)        pmac = h.digest()        if pmac == mac:            tag = '-->'            wheat.append(data)        else:            tag = '   '        # base64 adds a trailing newline        print tag, '%3d' % i, \              repr(data), encodestring(mac)[:-1]    # now decode the message packets and check it against the original text    print 'Undigesting wheat...'    newtext = "".join(wheat)    if newtext == text:        print 'They match!'    else:        print 'They differ!'

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -