Esempio n. 1
0
    def processBuffer(self, buffer):
        done = False

        if (len(buffer) * 8 < self.numObservationBits):
            print "ERROR: Received an incomplete buffer (%d), expexting (%d)" \
              %( ( len( buffer ) * 8 ), self.numObservationBits )

            done = True
        else:
            part = []
            bufferedSamples = BitStream(buffer)

            numObservationSamples = len(
                self.spreadingCode) * Receiver.MULTIPLIER

            for sampleIndex in range(numObservationSamples):
                sampleValue = bufferedSamples.read(self.bitDepth)

                for channelIndex in range(self.numberOfChannels - 1):
                    bufferedSamples.read(self.bitDepth)

                sampleValue = struct.pack("!I", sampleValue)
                sampleValue = struct.unpack("i", sampleValue)[0]

                part.append(sampleValue * 1.0)

            if (part != None and 0 < len(part)):
                self.detectTrainingSequence(part)

            self.numProcessedObservations += 1

            done = (self.numProcessedObservations >=
                    self.maxNumberOfObservations)

        return (done)
Esempio n. 2
0
    def extractSymbols(self, symbols, offset):
        bitPacker = BitPacker()
        bitStream = BitStream(False, bitPacker)

        for i in range(offset, len(symbols)):
            bitPacker.writeByte(symbols[i], 1)

        data = bitStream.getRawBytes()

        print "Data (%d):" % (len(data))
        for i in range(len(data)):
            if(i != 0 and i % 8 == 0):
                print

            print "0x%02x " % (ord(data[i])),
        print

        decodedData = self.decodeData(data)

        print "Decoded data (%d):" % (len(decodedData))
        for i in range(len(decodedData)):
            if(i != 0 and i % 8 == 0):
                print

            print "0x%02x " % (ord(decodedData[i])),
        print

        print "Decoded string: '%s'" % (decodedData)

        decodedSymbols = \
            SymbolTracker.toList(self.bitsPerSymbol, decodedData)

        return(decodedSymbols)
Esempio n. 3
0
    def encode(self, data):
        if(self.checkParamterIsString(data)):
            bitPacker = BitPacker()
            bitStream = BitStream(False, bitPacker)
            symbolTracker = SymbolTracker(
                ManchesterEncoder.MESSAGE_LENGTH, data)
            symbol = symbolTracker.getNextSymbol()

            while(symbol is not None):
                if(symbol == 1):
                    bitPacker.writeByte(
                        ManchesterEncoder.HI_SYMBOL,
                        ManchesterEncoder.BLOCK_LENGTH
                    )
                elif(symbol == 0):
                    bitPacker.writeByte(
                        ManchesterEncoder.LO_SYMBOL,
                        ManchesterEncoder.BLOCK_LENGTH
                    )
                else:
                    print "ERROR: Received unknown symbol (%d)." % (symbol)

                symbol = symbolTracker.getNextSymbol()

            return(bitStream.getRawBytes())
        else:
            return(None)
    def decode(self, data, errorPositions=None):
        if(self.codec and self.checkParamterIsString(data)):
            bitPacker = BitPacker()
            bitStream = BitStream(False, bitPacker)
            symbolTracker = BitStream(False, data)
            numberOfBlocks = \
                int(
                    math.ceil(
                        float(symbolTracker.getSize()) /
                        float(self.blockLength)
                    )
                )

            for i in range(numberOfBlocks):
                blockValues = [0 for j in range(self.numberOfBlockSymbols)]

                buffer = symbolTracker.readBytes(self.blockLength)

                for j in range(len(buffer)):
                    index = (i * self.numberOfBlockSymbols) + j
                    blockValues[j] = ord(buffer[j])

                    if (
                        errorPositions is not None and
                        index < len(errorPositions) and
                        errorPositions[index]
                    ):
                        blockValues[j] = -1

                message =  \
                    self.codec.RSDecode(
                        blockValues,
                        (
                            self.numberOfBlockSymbols -
                            self.numberOfMessageSymbols
                        )
                    )

                if(message is not None):
                    map(
                        lambda x:
                        bitPacker.writeByte(
                            x,
                            ReedSolomonEncoder.SYMBOL_SIZE_IN_BITS
                        ),
                        message[0: self.numberOfMessageSymbols]
                    )
                else:
                    for i in range(self.numberOfMessageSymbols):
                        bitPacker.writeByte(
                            0,
                            ReedSolomonEncoder.SYMBOL_SIZE_IN_BITS
                        )

            return(bitStream.getRawBytes())
        else:
            print "ERROR: Codec was not initialized."

            return(None)
Esempio n. 5
0
 def test_bit_extension(self):
     """
     The real test function. I don't know how it works, but I think it will be cool
     :return: dunno
     """
     bit_stream = BitStream([])
     test1 = bit_stream.extend_count(3)
     test2 = bit_stream.extend_count(4)
     self.assertEqual(len(test1), 8)
     self.assertEqual(len(test2), 16)
Esempio n. 6
0
    def decode(self, fname):
        self._qr.decode(fname)

        bits = BitStream()
        print(self._qr.data)

        binData = base64.b64decode(self._qr.data)

        for uint8 in binData:
            byte = ord(uint8)
            bits.write(8, byte)

        print(bits)

        self._processPolygons(bits)
Esempio n. 7
0
    def record(self, device):
        if  (                               \
          device.hasAppropriateStream (     \
                CAHAL_DEVICE_INPUT_STREAM,  \
                self.numberOfChannels,      \
                self.bitDepth,              \
                self.sampleRate             \
                                      )     \
            ):
            flags =                                   \
              CAHAL_AUDIO_FORMAT_FLAGISSIGNEDINTEGER  \
              | CAHAL_AUDIO_FORMAT_FLAGISPACKED

            BaseRecorder.bitPacker = BitPacker()
            BaseRecorder.lock = _threading.Lock()
            BaseRecorder.semaphore = _threading.Semaphore(0)

            self.signal = BitStream(BaseRecorder.bitPacker)

            if  (
              start_recording (               \
                device.struct,                \
                CAHAL_AUDIO_FORMAT_LINEARPCM, \
                self.numberOfChannels,        \
                self.sampleRate,              \
                self.bitDepth,                \
                bufferSamples,                \
                flags                         \
                              )               \
                ):
                print "Starting recording..."

                self.processObservations()

                print "Stopping recording..."

                cahal_stop_recording()

                print "Stopped recording."
            else:
                print "ERROR: Could not start recording."
        else:
            print "ERROR: Could not find an appropriate stream."

        BaseRecorder.bitPacker = None
        BaseRecorder.lock = None
        BaseRecorder.semaphore = None
    def encode(self, data):
        if(self.codec and self.checkParamterIsString(data)):
            bitPacker = BitPacker()
            bitStream = BitStream(False, bitPacker)
            symbolTracker = BitStream(False, data)
            numberOfBlocks = \
                int(
                    math.ceil(
                        float(symbolTracker.getSize()) /
                        float(self.messageLength)
                    )
                )

            for i in range(numberOfBlocks):
                blockValues = [chr(0)
                               for i in range(self.numberOfMessageSymbols)]

                buffer = symbolTracker.readBytes(self.messageLength)

                for i in range(len(buffer)):
                    blockValues[i] = buffer[i]

                codeword =  \
                    self.codec.RSEncode(
                        blockValues,
                        (
                            self.numberOfBlockSymbols -
                            self.numberOfMessageSymbols
                        )
                    )

                map(
                    lambda x:
                    bitPacker.writeByte(
                        x,
                        ReedSolomonEncoder.SYMBOL_SIZE_IN_BITS
                    ),
                    codeword
                )

            return(bitStream.getRawBytes())
        else:
            print "ERROR: Codec was not initialized."

            return(None)
 def encrypt_text(self, text, pad_to=None, task_monitor=None):
     """
     Encrypts the given string into a ciphertext object.
     
     Arguments:
         text::string            -- A string to encrypt.
         pad_to::int            -- Minimum size (in bytes) of the resulting 
                                ciphertext. Data will be padded before 
                                encryption to match this size.
         task_monitor::TaskMonitor    -- A task monitor for this task.
     
     Returns:
         ciphertext:Ciphertext    -- A ciphertext object encapsulating the 
                                    encrypted data.
     """
     bitstream = BitStream()
     bitstream.put_string(text)
     return self.encrypt_bitstream(bitstream, pad_to, task_monitor)
Esempio n. 10
0
 def encrypt_text(self, text, pad_to=None, task_monitor=None):
     """
     Encrypts the given string into a ciphertext object.
     
     Arguments:
         text::string            -- A string to encrypt.
         pad_to::int            -- Minimum size (in bytes) of the resulting 
                                ciphertext. Data will be padded before 
                                encryption to match this size.
         task_monitor::TaskMonitor    -- A task monitor for this task.
     
     Returns:
         ciphertext:Ciphertext    -- A ciphertext object encapsulating the 
                                    encrypted data.
     """
     bitstream = BitStream()
     bitstream.put_string(text)
     return self.encrypt_bitstream(bitstream, pad_to, task_monitor)
Esempio n. 11
0
  def transmit( self, device, message ):
    if  (                               \
        device.hasAppropriateStream (   \
            CAHAL_DEVICE_OUTPUT_STREAM, \
            self.numberOfChannels,      \
            self.bitDepth,              \
            self.sampleRate             \
                                    )   \
        ):
      print "Preparing signal for message: %s." %( message )

      symbolTracker = BitStream( message )
      bitPacker     = BitPacker() 

      numSymbols  = symbolTracker.getSize() / self.bitsPerSymbol
      numSamples  = numSymbols * self.samplesPerSymbol
      duration    = math.ceil( numSamples / self.sampleRate )

      print "Buffering up to 5 seconds of audio."

      numSymbolsToRead =  \
        math.ceil( self.sampleRate / self.samplesPerSymbol * 5 )

      print "Symbols to read per iteration is 0x%x." %( numSymbolsToRead )

      hasRemaining = \
        self.bufferSymbols  (
          symbolTracker,
          bitPacker,
          numSymbolsToRead
                            )

      self.sendSignal (
        device,
        symbolTracker,
        bitPacker,
        duration,
        hasRemaining,
        numSymbolsToRead
                      )
    else:
      print "ERROR: Could not find an appropriate stream."
Esempio n. 12
0
    def _encrypted_data_as_bitstream(self):
        """
        Returns the contents of this ciphertext as a BitStream object.

        This includes only the encrypted data (gamma and delta components), not
        the nbits and public key fingerprint metadata.

        The components are encoded alternating as follows:
            [gamma[0], delta[0], gamma[1], delta[1], ...]
        with each component represented as a nbits long number.

        Returns:
            bitstream::BitStream    -- The gamma and delta components of this
                                       ciphertext as a bitstream.
        """
        bitstream = BitStream()
        for i in range(0, self.get_length()):
            bitstream.put_num(self.gamma[i], self.nbits)
            bitstream.put_num(self.delta[i], self.nbits)
        return bitstream
Esempio n. 13
0
    def _encrypted_data_as_bitstream(self):
        """
        Returns the contents of this ciphertext as a BitStream object.

        This includes only the encrypted data (gamma and delta components), not
        the nbits and public key fingerprint metadata.

        The components are encoded alternating as follows:
            [gamma[0], delta[0], gamma[1], delta[1], ...]
        with each component represented as a nbits long number.

        Returns:
            bitstream::BitStream    -- The gamma and delta components of this
                                       ciphertext as a bitstream.
        """
        bitstream = BitStream()
        for i in range(0, self.get_length()):
            bitstream.put_num(self.gamma[i], self.nbits)
            bitstream.put_num(self.delta[i], self.nbits)
        return bitstream
Esempio n. 14
0
    def processBuffer(self, buffer):
        done = False

        if len(buffer) * 8 < self.numObservationBits:
            print "ERROR: Received an incomplete buffer (%d), expexting (%d)" % (
                (len(buffer) * 8),
                self.numObservationBits,
            )

            done = True
        else:
            part = []
            bufferedSamples = BitStream(buffer)

            for sampleIndex in range(self.numObservationSamples):
                sampleValue = bufferedSamples.read(self.bitDepth)

                for channelIndex in range(self.numberOfChannels - 1):
                    bufferedSamples.read(self.bitDepth)

                sampleValue = struct.pack("!I", sampleValue)
                sampleValue = struct.unpack("i", sampleValue)[0]

                part.append(sampleValue * 1.0)

            if 0 < len(part):
                if self.applyFilter:
                    part = python_filter_signal(self.widebandFilter, part)

                if 0 == (self.numProcessedObservations % int(self.graphPeriod)):
                    self.graphFFT(part)

                self.calculateEnergy(part)

            self.numProcessedObservations += 1

            done = self.numProcessedObservations >= self.numObservations

        return done
Esempio n. 15
0
    def decode(self, data, errorPositions=None):
        if(self.checkParamterIsString(data)):
            bitPacker = BitPacker()
            bitStream = BitStream(False, bitPacker)
            symbolTracker = SymbolTracker(ManchesterEncoder.BLOCK_LENGTH, data)
            symbol = symbolTracker.getNextSymbol()
            errorBitPositions = []

            while(symbol is not None):
                if(symbol == ManchesterEncoder.HI_SYMBOL):
                    bitPacker.writeByte(1, 1)
                elif(symbol == ManchesterEncoder.LO_SYMBOL):
                    bitPacker.writeByte(0, 1)
                else:
                    print   \
                        "WARN: Received unknown symbol (0x%x) at position %d."\
                        % (symbol, bitStream.getSize())

                    errorBitPositions.append(bitStream.getSize())

                    bitPacker.writeByte(1, 1)

                symbol = symbolTracker.getNextSymbol()

            buffer = bitStream.getRawBytes()

            if(errorPositions is not None):
                for i in range(len(buffer)):
                    errorPositions.append(False)
                for bitPosition in errorBitPositions:
                    bytePosition = int(math.floor(bitPosition / 8))

                    errorPositions[bytePosition] = True

            return(buffer)
        else:
            return(None)
Esempio n. 16
0
  def processBuffer( self, buffer ):
    done = False

    if( len( buffer ) * 8 < self.numObservationBits ):
      print "ERROR: Received an incomplete buffer (%d), expexting (%d)" \
        %( ( len( buffer ) * 8 ), self.numObservationBits )

      done = True
    else:
      part            = []
      bufferedSamples = BitStream( buffer )

      for sampleIndex in range( self.numObservationSamples ):
        sampleValue = bufferedSamples.read( self.bitDepth )            

        for channelIndex in range( self.numberOfChannels - 1 ):
          bufferedSamples.read( self.bitDepth )

        sampleValue = struct.pack( "!I", sampleValue )
        sampleValue = struct.unpack( "i", sampleValue )[ 0 ]

        part.append( sampleValue * 1.0 )

      if( 0 < len( part ) ):
        if( self.applyFilter ):
          part = python_filter_signal( self.widebandFilter, part )

        if( 0 == ( self.numProcessedObservations % int( self.graphPeriod ) ) ):
          self.graphFFT( part )
  
        self.calculateEnergy( part )     

      self.numProcessedObservations += 1

      done = ( self.numProcessedObservations >= self.numObservations )

    return( done )
Esempio n. 17
0
    def transmit(self, device, message):
        if  (                               \
            device.hasAppropriateStream (   \
                CAHAL_DEVICE_OUTPUT_STREAM, \
                self.numberOfChannels,      \
                self.bitDepth,              \
                self.sampleRate             \
                                        )   \
            ):
            print "Preparing signal for message: %s." % (message)

            symbolTracker = BitStream(message)
            bitPacker = BitPacker()

            numSymbols = symbolTracker.getSize() / self.bitsPerSymbol
            numSamples = numSymbols * self.samplesPerSymbol
            duration = math.ceil(numSamples / self.sampleRate)

            print "Buffering up to 5 seconds of audio."

            numSymbolsToRead =  \
              math.ceil( self.sampleRate / self.samplesPerSymbol * 5 )

            print "Symbols to read per iteration is 0x%x." % (numSymbolsToRead)

            hasRemaining = \
              self.bufferSymbols  (
                symbolTracker,
                bitPacker,
                numSymbolsToRead
                                  )

            self.sendSignal(device, symbolTracker, bitPacker, duration,
                            hasRemaining, numSymbolsToRead)
        else:
            print "ERROR: Could not find an appropriate stream."
Esempio n. 18
0
    def decode(self, data, errorPositions=None):
        if (self.codec and self.checkParamterIsString(data)):
            bitPacker = BitPacker()
            bitStream = BitStream(False, bitPacker)
            symbolTracker = BitStream(False, data)
            numberOfBlocks = \
                int(
                    math.ceil(
                        float(symbolTracker.getSize()) /
                        float(self.blockLength)
                    )
                )

            for i in range(numberOfBlocks):
                blockValues = [0 for j in range(self.numberOfBlockSymbols)]

                buffer = symbolTracker.readBytes(self.blockLength)

                for j in range(len(buffer)):
                    index = (i * self.numberOfBlockSymbols) + j
                    blockValues[j] = ord(buffer[j])

                    if (errorPositions is not None
                            and index < len(errorPositions)
                            and errorPositions[index]):
                        blockValues[j] = -1

                message =  \
                    self.codec.RSDecode(
                        blockValues,
                        (
                            self.numberOfBlockSymbols -
                            self.numberOfMessageSymbols
                        )
                    )

                if (message is not None):
                    map(
                        lambda x: bitPacker.writeByte(
                            x, ReedSolomonEncoder.SYMBOL_SIZE_IN_BITS),
                        message[0:self.numberOfMessageSymbols])
                else:
                    for i in range(self.numberOfMessageSymbols):
                        bitPacker.writeByte(
                            0, ReedSolomonEncoder.SYMBOL_SIZE_IN_BITS)

            return (bitStream.getRawBytes())
        else:
            print "ERROR: Codec was not initialized."

            return (None)
Esempio n. 19
0
    def sendSignal(self, device, symbolTracker, bitPacker, duration,
                   hasRemaining, numSymbolsToRead):
        flags =                                   \
          CAHAL_AUDIO_FORMAT_FLAGISSIGNEDINTEGER  \
          | CAHAL_AUDIO_FORMAT_FLAGISPACKED

        Transmitter.signal = BitStream(bitPacker)
        Transmitter.lock = _threading.Lock()

        print "Duration is %d seconds." % (duration)

        if  (
          start_playback  (               \
            device.struct,                \
            CAHAL_AUDIO_FORMAT_LINEARPCM, \
            self.numberOfChannels,        \
            self.sampleRate,              \
            self.bitDepth,                \
            playback,                     \
            flags                         \
                          )               \
            ):

            startTime = calendar.timegm(time.gmtime())

            while (hasRemaining):
                hasRemaining =  \
                  self.bufferSymbols( symbolTracker, bitPacker, numSymbolsToRead )

            endTime = calendar.timegm(time.gmtime())

            duration -= int(endTime - startTime)

            if (0 > duration):
                duation = 0

            duration = struct.unpack("I", struct.pack("i", duration))[0]

            cahal_sleep(duration * 1000)

            if (cahal_stop_playback()):
                print "Transmit stopped."
            else:
                print "ERROR: Could not stop playback."
        else:
            print "ERROR: Could not start playing."

        Transmitter.lock = None
Esempio n. 20
0
  def record( self, device ):
    if  (                               \
      device.hasAppropriateStream (     \
            CAHAL_DEVICE_INPUT_STREAM,  \
            self.numberOfChannels,      \
            self.bitDepth,              \
            self.sampleRate             \
                                  )     \
        ):
      flags =                                   \
        CAHAL_AUDIO_FORMAT_FLAGISSIGNEDINTEGER  \
        | CAHAL_AUDIO_FORMAT_FLAGISPACKED                                                                                

      BaseRecorder.bitPacker  = BitPacker()
      BaseRecorder.lock       = _threading.Lock()
      BaseRecorder.semaphore  = _threading.Semaphore( 0 )

      self.signal             = BitStream( BaseRecorder.bitPacker )

      if  (
        start_recording (               \
          device.struct,                \
          CAHAL_AUDIO_FORMAT_LINEARPCM, \
          self.numberOfChannels,        \
          self.sampleRate,              \
          self.bitDepth,                \
          bufferSamples,                \
          flags                         \
                        )               \
          ):
        print "Starting recording..."

        self.processObservations()

        print "Stopping recording..."

        cahal_stop_recording()

        print "Stopped recording."
      else:
        print "ERROR: Could not start recording."
    else:
      print "ERROR: Could not find an appropriate stream."

    BaseRecorder.bitPacker  = None
    BaseRecorder.lock       = None
    BaseRecorder.semaphore  = None
Esempio n. 21
0
    def encode(self, data):
        if (self.codec and self.checkParamterIsString(data)):
            bitPacker = BitPacker()
            bitStream = BitStream(False, bitPacker)
            symbolTracker = BitStream(False, data)
            numberOfBlocks = \
                int(
                    math.ceil(
                        float(symbolTracker.getSize()) /
                        float(self.messageLength)
                    )
                )

            for i in range(numberOfBlocks):
                blockValues = [
                    chr(0) for i in range(self.numberOfMessageSymbols)
                ]

                buffer = symbolTracker.readBytes(self.messageLength)

                for i in range(len(buffer)):
                    blockValues[i] = buffer[i]

                codeword =  \
                    self.codec.RSEncode(
                        blockValues,
                        (
                            self.numberOfBlockSymbols -
                            self.numberOfMessageSymbols
                        )
                    )

                map(
                    lambda x: bitPacker.writeByte(
                        x, ReedSolomonEncoder.SYMBOL_SIZE_IN_BITS), codeword)

            return (bitStream.getRawBytes())
        else:
            print "ERROR: Codec was not initialized."

            return (None)
Esempio n. 22
0
    def verify(self, original_collection, shuffled_collection):
        """
        Verifies that original_collection and shuffled_collection are
        equivalent as proven by this ShufflingProof object.

        If this method returns true, then we have proof that both collections
        contain encryptions of the same collection of plaintexts, save for the
        negligible probability (for a correct security parameter configured in
        params.py) that the zero-knowledge proof has been faked. Otherwise we
        gain no information about the two collections, other than they are not
        shown to be equivalent by this particular proof.

        ShufflingProof is a zero-knowledge proof: the result of this
        verification or the information within the ShufflingProof object for
        which two collections pass this verification, provide no information as
        to the association of particular ciphertexts in original_collection
        with particular ciphertexts of shuffled_collection.

        Arguments:
            original_collection::CiphertextCollection   --
                The original collection of ciphertexts.
            shuffled_collection::CiphertextCollection   --
                Another collection for which we wish to know if the current
                ShufflingProof object demonstrates equivalence with
                original_collection.

        Returns:
            result::bool    -- True if this proof shows both collections to be
                               equivalent.
                               False otherwise.
        """
        # Get the security parameter P with which the proof was originally
        # created. This is reflect in the length of self._collections and
        # self._mappings.
        assert len(self._collections) == len(self._mappings), \
            "The length of the private properties self._collections and " \
            "self._mappings of ShufflingProof must always be the same."
        security_parameter = len(self._collections)


        # Get the security parameter specified in params
        minimum_allowed_security_parameter = params.SHUFFLING_PROOF_SECURITY_PARAMETER

        # Check that the security parameter is <= 256, since that is the most
        # bits of challenge we can currently have. Also check that P is at least 1
        if(minimum_allowed_security_parameter < 1 or
           minimum_allowed_security_parameter > 256):
            raise ValueError("Security parameter for shuffling proof " \
                    "(params.SHUFFLING_PROOF_SECURITY_PARAMETER) is out of " \
                    "range. The security parameter must be between 1 and 256, "\
                    "its current value is %d. If you have set " \
                    "CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER in the file " \
                    "params.py, please correct this value or set it to None, " \
                    "in order for the security parameter to be decided based " \
                    "on the global SECURITY_LEVEL of plonevotecryptolib. It " \
                    "is recommended that " \
                    "CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER be always set " \
                    "to None for deployment operation of plonevotecryptolib." \
                    % security_parameter)

        # Check that the security parameter for which the proof was generated
        # is correct and meets the security standards declared in params.py
        if(security_parameter < minimum_allowed_security_parameter or
           security_parameter < 1 or
           security_parameter > 256):
            raise InvalidShuffilingProofError("The security parameter for " \
                    "(which the current proof was created is %d. This is " \
                    "(either an incorrect value (outside of the [1,256] " \
                    "(range) or not secure enough to meet the standards set " \
                    "(in the configuration of params.py (< %d). The proof " \
                    "(is thus invalid." \
                    % (security_parameter,
                      minimum_allowed_security_parameter))

        # Generate the challenge
        challenge = \
            self._generate_challenge(original_collection, shuffled_collection)

        # Verify that the challenge corresponds to the stored one
        if(challenge != self._challenge):
            return False

        # Get the challenge as a BitStream for easier manipulation
        challenge_bits = BitStream()
        challenge_bits.put_hex(challenge)
        challenge_bits.seek(0)  # back to the beginning of the stream

        # For each of the first P bits in the stream
        for i in range(0, security_parameter):
            bit = challenge_bits.get_num(1)
            if(bit == 0):
                # verify that self._mapping[i] maps original_collection into
                # self._collections[i]
                if(not self._mappings[i].verify(original_collection,
                                               self._collections[i])):
                    return False

            elif(bit == 1):
                # verify that self._mapping[i] self._collections[i] into
                # self._collections[i]
                if(not self._mappings[i].verify(self._collections[i],
                                               shuffled_collection)):
                    return False
            else:
                assert False, "We took a single bit, its value must be either "\
                        "0 or 1."

        # If we made it so far, the proof is correct
        # (each mapping is in accordance to the challenge and valid)
        return True
Esempio n. 23
0
    def new(cls, original_collection, shuffled_collection, mapping):
        """
        Constructs a new proof of equivalence between original_collection and
        shuffled_collection.

        This method should not be used outside of plonevotecryptolib.Mixnet.
        Consider using CiphertextCollection.shuffle_with_proof() instead.

        The given CiphertextCollectionMapping must be a valid mapping between
        original_collection and shuffled_collection.

        Arguments:
            original_collection::CiphertextCollection --
                The original collection to be shuffled.
            shuffled_collection::CiphertextCollection --
                The shuffled collection resulting from applying mapping to
                original_collection.
            mapping::CiphertextCollectionMapping --
                The mapping between original_collection and shuffled_collection.

        Returns:
            proof::ShufflingProof --
                The zero-knowledge proof of equivalence between
                original_collection and shuffled_collection.

        Throws:
            InvalidCiphertextCollectionMappingError --
                If mapping is not a valid mapping between original_collection
                and shuffled_collection.
            ValueError --
                If params.SHUFFLING_PROOF_SECURITY_PARAMETER is within an
                invalid range.
        """
        # Check that we have a valid mapping between the two collections:
        if(not mapping.verify(original_collection, shuffled_collection)):
            raise InvalidCiphertextCollectionMappingError( \
                    "mapping was expected to be a CiphertextCollectionMapping "\
                    "object representing a valid mapping between "\
                    "original_collection and shuffled_collection. However, "\
                    "mapping.verify(original_collection, shuffled_collection) "\
                    "returns False. A zero-knowledge proof of equivalence "\
                    "between two shuffled collections cannot be constructed "\
                    "without first having a valid mapping between them.")

        # Get the security parameter P
        security_parameter = params.SHUFFLING_PROOF_SECURITY_PARAMETER

        # Check that the security parameter is <= 256, since that is the most
        # bits of challenge we can currently have. Also check that P is at least 1
        if(security_parameter < 1 or security_parameter > 256):
            raise ValueError("Security parameter for shuffling proof " \
                    "(params.SHUFFLING_PROOF_SECURITY_PARAMETER) is out of " \
                    "range. The security parameter must be between 1 and 256, "\
                    "its current value is %d. If you have set " \
                    "CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER in the file " \
                    "params.py, please correct this value or set it to None, " \
                    "in order for the security parameter to be decided based " \
                    "on the global SECURITY_LEVEL of plonevotecryptolib. It " \
                    "is recommended that " \
                    "CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER be always set " \
                    "to None for deployment operation of plonevotecryptolib." \
                    % security_parameter)

        # Construct a new empty proof
        proof = ShufflingProof()

        # Populate proof._collections with P random shuffles of
        # original_collection. We save each mapping for now in proof._mappings.
        # (ie. every mapping in proof._mappings[i] will initially be from the
        # original collection into proof._collections[i])

        # generate new mappings in parallel
        pool = multiprocessing.Pool()
        async_params = [original_collection] * security_parameter
        generate_mappings_pool = pool.map_async(new_collection_mapping, async_params)
        for new_mapping in generate_mappings_pool.get(99999999):
            proof._mappings.append(new_mapping)
            proof._collections.append(new_mapping.apply(original_collection))
        pool.close()
        pool.join()

        # Generate the challenge
        proof._challenge = \
            proof._generate_challenge(original_collection, shuffled_collection)

        # Get the challenge as a BitStream for easier manipulation
        challenge_bits = BitStream()
        challenge_bits.put_hex(proof._challenge)
        challenge_bits.seek(0)  # back to the beginning of the stream

        # For each of the first P bits in the stream
        for i in range(0, security_parameter):
            ## print "Processing challenge bit %d" % i # replace with TaskMonitor API calls
            bit = challenge_bits.get_num(1)
            if(bit == 0):
                # Do nothing.
                # proof._mappings[i] is already a mapping from
                # original_collection unto proof._collections[i]
                pass
            elif(bit == 1):
                # Change proof._mappings[i] to be a mapping from
                # proof._collections[i] unto shuffled_collection, using
                # CiphertextCollectionMapping.rebase(...)

                # rebase(O->D, O->C_{i}) => C_{i}->D
                rebased_mapping = mapping.rebase(proof._mappings[i])

                # Replace O->C_{i} with C_{i}->D
                proof._mappings[i] = rebased_mapping
            else:
                assert False, "We took a single bit, its value must be either "\
                        "0 or 1."

        # return the proof object
        return proof
Esempio n. 24
0
class BaseRecorder:
  bitPacker           = None
  lock                = None
  semaphore           = None
  numObservationBits  = None

  def __init__  (
    self, bitDepth, numberOfChannels, sampleRate, widebandFirstStopband,
    widebandFirstPassband, widebandSecondPassband, widebandSecondStopband,
    passbandAttenuation, stopbandAttenuation, outputFileName, filter,
    writeOutput
                ):
    self.signal                 = None
    self.bitDepth               = bitDepth
    self.numberOfChannels       = numberOfChannels
    self.sampleRate             = int( sampleRate )
   
    self.widebandFirstStopband  = widebandFirstStopband
    self.widebandFirstPassband  = widebandFirstPassband
    self.widebandSecondPassband = widebandSecondPassband
    self.widebandSecondStopband = widebandSecondStopband

    self.passbandAttenuation    = passbandAttenuation
    self.stopbandAttenuation    = stopbandAttenuation

    self.writeOutput            = writeOutput
    self.applyFilter            = filter

    if( self.writeOutput ):
      self.outputFileName = outputFileName
    else:
      self.outputFileName = None

    if( self.applyFilter ):
      self.widebandFilter =  \
        python_initialize_kaiser_filter (
          self.widebandFirstStopband,
          self.widebandFirstPassband,
          self.widebandSecondPassband,
          self.widebandSecondStopband,
          self.passbandAttenuation,
          self.stopbandAttenuation,
          int( self.sampleRate )
                                        )
    else:
      self.widebandFilter = None

  def record( self, device ):
    if  (                               \
      device.hasAppropriateStream (     \
            CAHAL_DEVICE_INPUT_STREAM,  \
            self.numberOfChannels,      \
            self.bitDepth,              \
            self.sampleRate             \
                                  )     \
        ):
      flags =                                   \
        CAHAL_AUDIO_FORMAT_FLAGISSIGNEDINTEGER  \
        | CAHAL_AUDIO_FORMAT_FLAGISPACKED                                                                                

      BaseRecorder.bitPacker  = BitPacker()
      BaseRecorder.lock       = _threading.Lock()
      BaseRecorder.semaphore  = _threading.Semaphore( 0 )

      self.signal             = BitStream( BaseRecorder.bitPacker )

      if  (
        start_recording (               \
          device.struct,                \
          CAHAL_AUDIO_FORMAT_LINEARPCM, \
          self.numberOfChannels,        \
          self.sampleRate,              \
          self.bitDepth,                \
          bufferSamples,                \
          flags                         \
                        )               \
          ):
        print "Starting recording..."

        self.processObservations()

        print "Stopping recording..."

        cahal_stop_recording()

        print "Stopped recording."
      else:
        print "ERROR: Could not start recording."
    else:
      print "ERROR: Could not find an appropriate stream."

    BaseRecorder.bitPacker  = None
    BaseRecorder.lock       = None
    BaseRecorder.semaphore  = None

  def processObservations( self ):
    done = False

    while( not done ):
      buffer = None

      nBitsToRead = self.getNumberOfBitsToRead()

      BaseRecorder.semaphore.acquire( True )

      BaseRecorder.lock.acquire( True )

      availableData = self.signal.getSize()

      BaseRecorder.lock.release()

      #print "Available %d, waiting for %d." %( availableData, nBitsToRead )

      while( availableData >= nBitsToRead and not done ):
        BaseRecorder.lock.acquire( True )

        buffer = self.signal.read( nBitsToRead )

        BaseRecorder.lock.release()

        if( None != buffer ):
          done = self.processBuffer( buffer )

        nBitsToRead = self.getNumberOfBitsToRead()

        BaseRecorder.lock.acquire( True )

        availableData = self.signal.getSize()

        BaseRecorder.lock.release()

        #print "Available %d, waiting for %d." %( availableData, nBitsToRead )

  def getNumberOfBitsToRead( self ):
    return( 0 )

  def processbuffer( self, buffer ):
    return( True )

  def __del__( self ):
    if( self.writeOutput ):
      WAVRecorder.saveSignalToWAV ( 
        self.signal, self.outputFileName, self.numberOfChannels,
        self.bitDepth, self.sampleRate
                                  )

    if( self.signal ):
      self.signal = None

    if( self.widebandFilter ):
      csignal_destroy_passband_filter( self.widebandFilter )

    BaseRecorder.bitPacker           = None
    BaseRecorder.lock                = None
    BaseRecorder.semaphore           = None
    BaseRecorder.numObservationBits  = None
    def decompress_video(self, decompress_path):
        with open(decompress_path, "wb") as write_stream:
            #Get the bitstream to read the compression
            read_stream = BitStream(self.file_path)
            read_stream.set_offset(len(self.header) * 8)

            #Write the header for the video
            write_stream.write(self.header.encode())
            write_stream.write("FRAME\n".encode())

            #This marks the start of decompression
            number_of_numbers = 0
            array_of_nums = []

            counter = 0
            counter_bits = 0
            while read_stream.read_bits(5000):
                got_number = self.gomby.add_bits(read_stream.get_bit_array())

                read_stream.delete_bits(5000)
                counter_bits += 1

                if got_number:
                    nums = self.gomby.decode_nums()
                    number_of_numbers += len(nums)
                    array_of_nums += nums
                    print("Decompressed", number_of_numbers)
                    print("Need to get", self.frame.limit_to_convert)

                if number_of_numbers >= self.frame.limit_to_convert:
                    counter += 1
                    print("Decompressing frame: ", counter)

                    array_of_nums = self.frame.set_frame_by_array(
                        array_of_nums)
                    y, u, v = self.frame.decompress_frame(self.decompress_mode)

                    write_stream.write(y.astype(np.uint8))
                    write_stream.write(u.astype(np.uint8))
                    write_stream.write(v.astype(np.uint8))
                    write_stream.write("FRAME\n".encode())
                    number_of_numbers -= self.frame.limit_to_convert
                    print("Finished writing decompressed frame, now only have",
                          number_of_numbers)

            num_bits = read_stream.read_allbits()
            got_number = self.gomby.add_bits(read_stream.get_bit_array())
            if got_number:
                nums = self.gomby.decode_nums()
                array_of_nums += nums

                ## At this point we have all of the frame saved in memory, we will now start to divide it in frames to proceed to decompressing
                array_of_nums = self.frame.set_frame_by_array(array_of_nums)

                y, u, v = self.frame.decompress_frame(self.decompress_mode)

                write_stream.write(y.astype(np.uint8))
                write_stream.write(u.astype(np.uint8))
                write_stream.write(v.astype(np.uint8))
                print("Finished writing decompressed frame")
                #girar
            print("Finished writing decompressed frame")
Esempio n. 26
0
 def decrypt_to_bitstream(self, ciphertext, task_monitor=None, force=False):
     """
     Decrypts the given ciphertext into a bitstream.
     
     If the bitstream was originally encrypted with PublicKey.encrypt_X(), 
     then this method returns a bitstream following the format described 
     in Note 001 of the Ciphertext.py file:
         [size (64 bits) | message (size bits) | padding (X bits) ]
     
     Arguments:
         ciphertext::Ciphertext    -- An encrypted Ciphertext object.
         task_monitor::TaskMonitor    -- A task monitor for this task.
         force:bool    -- Set this to true if you wish to force a decryption 
                        attempt, even when the ciphertext's stored public key
                        fingerprint does not match that of the public key 
                        associated with this private key.
     
     Returns:
         bitstream::Bitstream    -- A bitstream containing the unencrypted 
                                    data.
     
     Throws:
         IncompatibleCiphertextError -- The given ciphertext does not appear 
                                        to be decryptable with the selected 
                                        private key.
     """
     # Check that the public key fingerprint stored in the ciphertext 
     # matches the public key associated with this private key.
     if(not force):
         if(ciphertext.nbits != self.cryptosystem.get_nbits()):
             raise IncompatibleCiphertextError("The given ciphertext is " \
                     "not decryptable with the selected private key: " \
                     "incompatible cryptosystem/key sizes.")
         
         if(ciphertext.pk_fingerprint != self.public_key.get_fingerprint()):
             raise IncompatibleCiphertextError("The given ciphertext is " \
                     "not decryptable with the selected private key: " \
                     "public key fingerprint mismatch.")
     
     # We read and decrypt the ciphertext block by block
     # See "Handbook of Applied Cryptography" Algorithm 8.18
     bitstream = BitStream()
     
     block_size = self.cryptosystem.get_nbits() - 1
     prime = self.cryptosystem.get_prime()
     key = self._key
     
     # Check if we have a task monitor and register with it
     if(task_monitor != None):
         # One tick per block
         ticks = ciphertext.get_length()
         decrypt_task_mon = \
             task_monitor.new_subtask("Decrypt data", expected_ticks = ticks)
     
     for gamma, delta in ciphertext:
         assert max(gamma, delta) < 2**(block_size + 1), \
             "The ciphertext object includes blocks larger than the " \
             "expected block size."
         m = (pow(gamma, prime - 1 - key, prime) * delta) % prime
         bitstream.put_num(m, block_size)
         
         if(task_monitor != None): decrypt_task_mon.tick()
         
     return bitstream
Esempio n. 27
0
 def encrypt_bitstream(self, bitstream, pad_to=None, task_monitor=None):
     """
     Encrypts the given bitstream into a ciphertext object.
     
     Arguments:
         bitstream::BitStream-- A stream of bits to encrypt 
                                (see BitStream utility class).
         pad_to::int            -- Minimum size (in bytes) of the resulting 
                                ciphertext. Data will be padded before 
                                encryption to match this size.
         task_monitor::TaskMonitor    -- A task monitor for this task.
     
     Returns:
         ciphertext:Ciphertext    -- A ciphertext object encapsulating the 
                                    encrypted data.        
     """
     random = StrongRandom()
     
     ## PART 1
     # First, format the bitstream as per Ciphertext.py Note 001,
     # previous to encryption.
     #     [size (64 bits) | message (size bits) | padding (X bits) ]
     ##
     formated_bitstream = BitStream()
     
     # The first 64 encode the size of the actual data in bits
     SIZE_BLOCK_LENGTH = 64
     size_in_bits = bitstream.get_length()
     
     if(size_in_bits >= 2**SIZE_BLOCK_LENGTH):
         raise ValueError("The size of the bitstream to encrypt is larger " \
                          "than 16 Exabits. The current format for  " \
                          "PloneVote ciphertext only allows encrypting a  " \
                          "maximum of 16 Exabits of information.")
     
     formated_bitstream.put_num(size_in_bits, SIZE_BLOCK_LENGTH)
     
     # We then copy the contents of the original bitstream
     bitstream.seek(0)
     formated_bitstream.put_bitstream_copy(bitstream)
     
     # Finally, we append random data until we reach the desired pad_to 
     # length
     unpadded_length = formated_bitstream.get_length()
     if(pad_to != None and (pad_to * 8) > unpadded_length):
         full_length = pad_to * 8
     else:
         full_length = unpadded_length
     
     padding_left = full_length - unpadded_length
     
     while(padding_left > 1024):
         padding_bits = random.randint(1, 2**1024)
         formated_bitstream.put_num(padding_bits,1024)
         padding_left -= 1024
     
     if(padding_left > 0):
         padding_bits = random.randint(1, 2**padding_left)
         formated_bitstream.put_num(padding_bits, padding_left)
         padding_left = 0
     
     ## PART 2
     # We encrypt the formated bitsteam using ElGamal into a Ciphertext 
     # object.
     # See "Handbook of Applied Cryptography" Algorithm 8.18
     ##
     
     # block_size is the size of each block of bits to encrypt
     # since we can only encrypt messages in [0, p - 1]
     # we should use (nbits - 1) as the block size, where 
     # 2**(nbits - 1) < p < 2**nbits
     
     block_size = self.cryptosystem.get_nbits() - 1
     prime = self.cryptosystem.get_prime()
     generator = self.cryptosystem.get_generator()
     
     # We pull data from the bitstream one block at a time and encrypt it
     formated_bitstream.seek(0)
     ciphertext = \
         Ciphertext(self.cryptosystem.get_nbits(), self.get_fingerprint()) 
     
     plaintext_bits_left = formated_bitstream.get_length()
     
     # Check if we have a task monitor and register with it
     if(task_monitor != None):
         # We will do two tick()s per block to encrypt: one for generating 
         # the gamma component of the ciphertext block and another for the 
         # delta component (those are the two time intensive steps, 
         # because of exponentiation). 
         ticks = math.ceil((1.0 * plaintext_bits_left) / block_size) * 2
         encrypt_task_mon = \
             task_monitor.new_subtask("Encrypt data", expected_ticks = ticks)
     
     while(plaintext_bits_left > 0):
     
         # get next block (message, m, etc) to encrypt
         if(plaintext_bits_left >= block_size):
             block = formated_bitstream.get_num(block_size)
             plaintext_bits_left -= block_size
         else:
             block = formated_bitstream.get_num(plaintext_bits_left)
             # Encrypt as if the stream was filled with random data past its 
             # end, this avoids introducing a 0's gap during decryption to 
             # bitstream
             displacement = block_size - plaintext_bits_left
             block = block << displacement
             padding = random.randint(0, 2**displacement - 1)
             assert (padding / 2**displacement == 0), \
                         "padding should be at most displacement bits long"
             block = block | padding
             plaintext_bits_left = 0
         
         # Select a random integer k, 1 <= k <= p − 2
         k = random.randint(1, prime - 2)
         
         # Compute gamma and delta
         gamma = pow(generator, k, prime)
         if(task_monitor != None): encrypt_task_mon.tick()
         
         delta = (block * pow(self._key, k, prime)) % prime
         if(task_monitor != None): encrypt_task_mon.tick()
         
         # Add this encrypted data portion to the ciphertext object
         ciphertext.append(gamma, delta)
     
     # return the ciphertext object
     return ciphertext
Esempio n. 28
0
class Ciphertext:
    """
    An object representing encrypted PloneVote data.

    Ciphertext objects are created by PublicKey encrypt operations and
    decrypted through PrivateKey decrypt methods (or through
    ThresholdDecryptionCombinator if the data was encrypted with a threshold
    public key and all partial decryptions are available).

    This class can also be store to and loaded from file using the PloneVote
    armored ciphertext XML format.

    Attributes:
        nbits::int    -- Size in bits of the cryptosystem/public key used to
                       encrypt this ciphertext.
        pk_fingerprint::string -- A fingerprint of the public key used to
                                  encrypt this ciphertext. This fingerprint can
                                  then be compared with the result from
                                  PublicKey.get_fingerprint() to check for
                                  compatibility with a given key pair or
                                  threshold public key.
        gamma::long[]
        delta::long[]    -- :
            This two attributes should only be accessed by key classes within
            PloneVoteCryptoLib.
            See "Handbook of Applied Cryptography" Algorithm 8.18 for the
            meaning of the variables. An array is used because the encrypted
            data might be longer than the cryptosystem's bit size.
    """
    def to_dict(self):
        return {'a': self.gamma, 'b': self.delta}

    def get_length(self):
        """
        Returns the length, in blocks, of the ciphertext.
        """
        assert len(self.gamma) == len(self.delta), "Each gamma component of " \
                                            "the ciphertext must correspond " \
                                            " to one delta component."
        return len(self.gamma)

    def __getitem__(self, i):
        """
        Makes this object indexable.

        Returns:
            (gamma, delta)::(long, long)    -- Returns the gamma, delta pair
                                               representing a particular block
                                               of the encrypted data.
                Use ciphertext[i] for block i.
        """
        return (self.gamma[i], self.delta[i])

    def __iter__(self):
        """
        Return an iterator (CiphertextIterator) for the current ciphertext.
        """
        return CiphertextIterator(self)

    def __eq__(self, other):
        """
        Implements Ciphertext equality.

        Two ciphertexts are equal if they have the same bit size, public key
        fingerprint and list of gamma and delta components. A ciphertext is not
        equal to any object of a different type.
        """
        if (isinstance(other, Ciphertext) and (other.nbits == self.nbits)
                and (other.pk_fingerprint == self.pk_fingerprint)
                and (other.gamma == self.gamma)
                and (other.delta == self.delta)):
            return True
        else:
            return False

    def __ne__(self, other):
        """
        Implements Ciphertext inequality.

        See __eq__(...) for the definition of Ciphertext equality,
        inequality its is negation.
        """
        return not self.__eq__(other)

    def get_fingerprint(self):
        """
        Gets a fingerprint of the current ciphertext.

        A ciphertext fingerprint is generated as a SHA-256 hash of the
        ciphertext, block by block.

        Returns:
            fingerprint::string -- A SHA-256 hexdigest providing a fingerprint
                                   of the current ciphertext.
        """
        fingerprint = sha256()
        for (gamma, delta) in self:
            fingerprint.update(hex(gamma))
            fingerprint.update(hex(delta))
        return fingerprint.hexdigest()

    def __init__(self, nbits, public_key_fingerprint):
        """
        Create an empty ciphertext object.

        Arguments:
            nbits::int    -- Size in bits of the cryptosystem/public key used
                             to encrypt this ciphertext.
            public_key_fingerprint::string    -- The fingerprint of the public
                                               key used to encrypt this data.
        """
        self.gamma = []
        self.delta = []
        self.nbits = nbits
        self.pk_fingerprint = public_key_fingerprint

    def append(self, gamma, delta):
        """
        Used internally by PublicKey.

        This method adds an encrypted block of data with its gamma and delta
        components from ElGamal (see HoAC Alg. 8.18).
        """
        self.gamma.append(gamma)
        self.delta.append(delta)

    def _encrypted_data_as_bitstream(self):
        """
        Returns the contents of this ciphertext as a BitStream object.

        This includes only the encrypted data (gamma and delta components), not
        the nbits and public key fingerprint metadata.

        The components are encoded alternating as follows:
            [gamma[0], delta[0], gamma[1], delta[1], ...]
        with each component represented as a nbits long number.

        Returns:
            bitstream::BitStream    -- The gamma and delta components of this
                                       ciphertext as a bitstream.
        """
        bitstream = BitStream()
        for i in range(0, self.get_length()):
            bitstream.put_num(self.gamma[i], self.nbits)
            bitstream.put_num(self.delta[i], self.nbits)
        return bitstream

    def _encrypted_data_as_base64(self):
        """
        Returns the contents of this ciphertext as a base64 string.

        This includes only the encrypted data (gamma and delta components), not
        the nbits and public key fingerprint metadata.
        """
        bitstream = self._encrypted_data_as_bitstream()
        bitstream.seek(0)
        length = bitstream.get_length()

        assert length % 8 == 0, \
                "The ciphertext data must be a multiple of eight bits in size."

        return bitstream.get_base64(length)

    def to_file(self, filename, SerializerClass=serialize.XMLSerializer):
        """
        Saves this ciphertext to a file.

        Arguments:
            filename::string    -- The path to the file in which to store the
                                   serialized Ciphertext object.
            SerializerClass::class --
                The class that provides the serialization. XMLSerializer by
                default. Must inherit from serialize.BaseSerializer and provide
                an adequate serialize_to_file method.
                Note that often the same class used to serialize the data must
                be used to deserialize it.
                (see utilities/serialize.py documentation for more information)
        """
        # Create a new serializer object for the Ciphertext structure definition
        serializer = SerializerClass(Ciphertext_serialize_structure_definition)

        # Generate a serializable data dictionary matching the definition:
        data = {
            "PloneVoteCiphertext": {
                "nbits": str(self.nbits),
                "PKFingerprint": self.pk_fingerprint,
                "EncryptedData": self._encrypted_data_as_base64()
            }
        }

        # Use the serializer to store the data to file
        serializer.serialize_to_file(filename, data)

    @classmethod
    def from_file(cls, filename, SerializerClass=serialize.XMLSerializer):
        """
        Loads an instance of Ciphertext from the given file.

        Arguments:
            filename::string    -- The name of a file containing the ciphertext
                                   in serialized form.
            SerializerClass::class --
                The class that provides the deserialization. XMLSerializer by
                default. Must inherit from serialize.BaseSerializer and provide
                an adequate deserialize_from_file method.
                Note that often the same class used to serialize the data must
                be used to deserialize it.
                (see utilities/serialize.py documentation for more information)

        Throws:
            InvalidPloneVoteCryptoFileError -- If the file is not a valid
                                               PloneVoteCryptoLib stored
                                               ciphertext file.
        """
        # Create a new serializer object for the Ciphertext structure definition
        serializer = SerializerClass(Ciphertext_serialize_structure_definition)

        # Deserialize the Ciphertext instance from file
        try:
            data = serializer.deserialize_from_file(filename)
        except serialize.InvalidSerializeDataError, e:
            # Convert the exception to an InvalidPloneVoteCryptoFileError
            raise InvalidPloneVoteCryptoFileError(filename,
                "File \"%s\" does not contain a valid ciphertext. The " \
                "following error occurred while trying to deserialize the " \
                "file contents: %s" % (filename, str(e)))

        # Get the values from the deserialized data
        try:
            nbits = int(data["PloneVoteCiphertext"]["nbits"])
        except ValueError:
            raise InvalidPloneVoteCryptoFileError(filename,
                    "File \"%s\" does not contain a valid ciphertext. The " \
                    "stored value for nbits is not a valid (decimal) integer." \
                    % filename)

        fingerprint_str = data["PloneVoteCiphertext"]["PKFingerprint"]
        enc_data_str = data["PloneVoteCiphertext"]["EncryptedData"]

        # Construct a new Ciphertext object with the given nbits and fingerprint
        ciphertext = cls(nbits, fingerprint_str)

        # Load the encrypted data
        bitstream = BitStream()
        bitstream.put_base64(enc_data_str)
        bitstream.seek(0)
        length = bitstream.get_length()

        #     number of gamma and delta blocks in the bitstream:
        blocks = length / (nbits * 2)

        for i in range(0, blocks):
            gamma_val = bitstream.get_num(nbits)
            delta_val = bitstream.get_num(nbits)
            ciphertext.append(gamma_val, delta_val)

        # Return the ciphertext
        return ciphertext
Esempio n. 29
0
    def new(cls, original_collection, shuffled_collection, mapping):
        """
        Constructs a new proof of equivalence between original_collection and
        shuffled_collection.

        This method should not be used outside of plonevotecryptolib.Mixnet.
        Consider using CiphertextCollection.shuffle_with_proof() instead.

        The given CiphertextCollectionMapping must be a valid mapping between
        original_collection and shuffled_collection.

        Arguments:
            original_collection::CiphertextCollection --
                The original collection to be shuffled.
            shuffled_collection::CiphertextCollection --
                The shuffled collection resulting from applying mapping to
                original_collection.
            mapping::CiphertextCollectionMapping --
                The mapping between original_collection and shuffled_collection.

        Returns:
            proof::ShufflingProof --
                The zero-knowledge proof of equivalence between
                original_collection and shuffled_collection.

        Throws:
            InvalidCiphertextCollectionMappingError --
                If mapping is not a valid mapping between original_collection
                and shuffled_collection.
            ValueError --
                If params.SHUFFLING_PROOF_SECURITY_PARAMETER is within an
                invalid range.
        """
        # Check that we have a valid mapping between the two collections:
        if (not mapping.verify(original_collection, shuffled_collection)):
            raise InvalidCiphertextCollectionMappingError( \
                    "mapping was expected to be a CiphertextCollectionMapping "\
                    "object representing a valid mapping between "\
                    "original_collection and shuffled_collection. However, "\
                    "mapping.verify(original_collection, shuffled_collection) "\
                    "returns False. A zero-knowledge proof of equivalence "\
                    "between two shuffled collections cannot be constructed "\
                    "without first having a valid mapping between them.")

        # Get the security parameter P
        security_parameter = params.SHUFFLING_PROOF_SECURITY_PARAMETER

        # Check that the security parameter is <= 256, since that is the most
        # bits of challenge we can currently have. Also check that P is at least 1
        if (security_parameter < 1 or security_parameter > 256):
            raise ValueError("Security parameter for shuffling proof " \
                    "(params.SHUFFLING_PROOF_SECURITY_PARAMETER) is out of " \
                    "range. The security parameter must be between 1 and 256, "\
                    "its current value is %d. If you have set " \
                    "CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER in the file " \
                    "params.py, please correct this value or set it to None, " \
                    "in order for the security parameter to be decided based " \
                    "on the global SECURITY_LEVEL of plonevotecryptolib. It " \
                    "is recommended that " \
                    "CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER be always set " \
                    "to None for deployment operation of plonevotecryptolib." \
                    % security_parameter)

        # Construct a new empty proof
        proof = ShufflingProof()

        # Populate proof._collections with P random shuffles of
        # original_collection. We save each mapping for now in proof._mappings.
        # (ie. every mapping in proof._mappings[i] will initially be from the
        # original collection into proof._collections[i])

        # generate new mappings in parallel
        pool = multiprocessing.Pool()
        async_params = [original_collection] * security_parameter
        generate_mappings_pool = pool.map_async(new_collection_mapping,
                                                async_params)
        for new_mapping in generate_mappings_pool.get(99999999):
            proof._mappings.append(new_mapping)
            proof._collections.append(new_mapping.apply(original_collection))
        pool.close()
        pool.join()

        # Generate the challenge
        proof._challenge = \
            proof._generate_challenge(original_collection, shuffled_collection)

        # Get the challenge as a BitStream for easier manipulation
        challenge_bits = BitStream()
        challenge_bits.put_hex(proof._challenge)
        challenge_bits.seek(0)  # back to the beginning of the stream

        # For each of the first P bits in the stream
        for i in range(0, security_parameter):
            ## print "Processing challenge bit %d" % i # replace with TaskMonitor API calls
            bit = challenge_bits.get_num(1)
            if (bit == 0):
                # Do nothing.
                # proof._mappings[i] is already a mapping from
                # original_collection unto proof._collections[i]
                pass
            elif (bit == 1):
                # Change proof._mappings[i] to be a mapping from
                # proof._collections[i] unto shuffled_collection, using
                # CiphertextCollectionMapping.rebase(...)

                # rebase(O->D, O->C_{i}) => C_{i}->D
                rebased_mapping = mapping.rebase(proof._mappings[i])

                # Replace O->C_{i} with C_{i}->D
                proof._mappings[i] = rebased_mapping
            else:
                assert False, "We took a single bit, its value must be either "\
                        "0 or 1."

        # return the proof object
        return proof
    def compress_video(self, compress_path, mode="JPEG-1"):
        if mode not in ["JPEG-" + str(i)
                        for i in range(1, 8)] and mode != "JPEG-LS":
            print("Invalid mode")
            return None
        with open(self.file_path, "rb") as stream:
            line = stream.readline()

            gomby = Golomb(4)
            bit_stream = BitStream()

            header = self.header[:-1] + " G" + str(
                gomby.encoding_parameter) + " M" + mode + "\n"

            with open(compress_path, "wb") as file_path:
                file_path.write(header.encode())

            counter = 0

            while True:
                start_time = time()
                if counter > 2:
                    break
                counter += 1
                print("Compressing frame: ", counter)
                try:
                    line = stream.readline()
                except ValueError:
                    print("Finished compressing")
                    break
                line = stream.readline()
                self.frame.set_frame(stream)
                start = time()
                compressed_frame = self.frame.compress_frame(mode)
                print("Compressed in ", time() - start)
                y = compressed_frame[0]
                u = compressed_frame[1]
                v = compressed_frame[2]

                for x in np.nditer(y):
                    bit_stream.add_to_bit_array(gomby.encode(int(x)))

                #bit_stream.write_allbits(compress_path)

                print("Finished compressing Y")

                for x in np.nditer(u):
                    bit_stream.add_to_bit_array(gomby.encode(int(x)))

                #bit_stream.write_allbits(compress_path)

                print("Finished compressing U")

                for x in np.nditer(v):
                    bit_stream.add_to_bit_array(gomby.encode(int(x)))

                bit_stream.write_allbits(compress_path)

                print("Finished compressing in", time() - start_time)

            bit_stream.close(compress_path)
Esempio n. 31
0
class BaseRecorder:
    bitPacker = None
    lock = None
    semaphore = None
    numObservationBits = None

    def __init__(self, bitDepth, numberOfChannels, sampleRate,
                 widebandFirstStopband, widebandFirstPassband,
                 widebandSecondPassband, widebandSecondStopband,
                 passbandAttenuation, stopbandAttenuation, outputFileName,
                 filter, writeOutput):
        self.signal = None
        self.bitDepth = bitDepth
        self.numberOfChannels = numberOfChannels
        self.sampleRate = int(sampleRate)

        self.widebandFirstStopband = widebandFirstStopband
        self.widebandFirstPassband = widebandFirstPassband
        self.widebandSecondPassband = widebandSecondPassband
        self.widebandSecondStopband = widebandSecondStopband

        self.passbandAttenuation = passbandAttenuation
        self.stopbandAttenuation = stopbandAttenuation

        self.writeOutput = writeOutput
        self.applyFilter = filter

        if (self.writeOutput):
            self.outputFileName = outputFileName
        else:
            self.outputFileName = None

        if (self.applyFilter):
            self.widebandFilter =  \
              python_initialize_kaiser_filter (
                self.widebandFirstStopband,
                self.widebandFirstPassband,
                self.widebandSecondPassband,
                self.widebandSecondStopband,
                self.passbandAttenuation,
                self.stopbandAttenuation,
                int( self.sampleRate )
                                              )
        else:
            self.widebandFilter = None

    def record(self, device):
        if  (                               \
          device.hasAppropriateStream (     \
                CAHAL_DEVICE_INPUT_STREAM,  \
                self.numberOfChannels,      \
                self.bitDepth,              \
                self.sampleRate             \
                                      )     \
            ):
            flags =                                   \
              CAHAL_AUDIO_FORMAT_FLAGISSIGNEDINTEGER  \
              | CAHAL_AUDIO_FORMAT_FLAGISPACKED

            BaseRecorder.bitPacker = BitPacker()
            BaseRecorder.lock = _threading.Lock()
            BaseRecorder.semaphore = _threading.Semaphore(0)

            self.signal = BitStream(BaseRecorder.bitPacker)

            if  (
              start_recording (               \
                device.struct,                \
                CAHAL_AUDIO_FORMAT_LINEARPCM, \
                self.numberOfChannels,        \
                self.sampleRate,              \
                self.bitDepth,                \
                bufferSamples,                \
                flags                         \
                              )               \
                ):
                print "Starting recording..."

                self.processObservations()

                print "Stopping recording..."

                cahal_stop_recording()

                print "Stopped recording."
            else:
                print "ERROR: Could not start recording."
        else:
            print "ERROR: Could not find an appropriate stream."

        BaseRecorder.bitPacker = None
        BaseRecorder.lock = None
        BaseRecorder.semaphore = None

    def processObservations(self):
        done = False

        while (not done):
            buffer = None

            nBitsToRead = self.getNumberOfBitsToRead()

            BaseRecorder.semaphore.acquire(True)

            BaseRecorder.lock.acquire(True)

            availableData = self.signal.getSize()

            BaseRecorder.lock.release()

            #print "Available %d, waiting for %d." %( availableData, nBitsToRead )

            while (availableData >= nBitsToRead and not done):
                BaseRecorder.lock.acquire(True)

                buffer = self.signal.read(nBitsToRead)

                BaseRecorder.lock.release()

                if (None != buffer):
                    done = self.processBuffer(buffer)

                nBitsToRead = self.getNumberOfBitsToRead()

                BaseRecorder.lock.acquire(True)

                availableData = self.signal.getSize()

                BaseRecorder.lock.release()

                #print "Available %d, waiting for %d." %( availableData, nBitsToRead )

    def getNumberOfBitsToRead(self):
        return (0)

    def processbuffer(self, buffer):
        return (True)

    def __del__(self):
        if (self.writeOutput):
            WAVRecorder.saveSignalToWAV(self.signal, self.outputFileName,
                                        self.numberOfChannels, self.bitDepth,
                                        self.sampleRate)

        if (self.signal):
            self.signal = None

        if (self.widebandFilter):
            csignal_destroy_passband_filter(self.widebandFilter)

        BaseRecorder.bitPacker = None
        BaseRecorder.lock = None
        BaseRecorder.semaphore = None
        BaseRecorder.numObservationBits = None
Esempio n. 32
0
    def verify(self, original_collection, shuffled_collection):
        """
        Verifies that original_collection and shuffled_collection are
        equivalent as proven by this ShufflingProof object.

        If this method returns true, then we have proof that both collections
        contain encryptions of the same collection of plaintexts, save for the
        negligible probability (for a correct security parameter configured in
        params.py) that the zero-knowledge proof has been faked. Otherwise we
        gain no information about the two collections, other than they are not
        shown to be equivalent by this particular proof.

        ShufflingProof is a zero-knowledge proof: the result of this
        verification or the information within the ShufflingProof object for
        which two collections pass this verification, provide no information as
        to the association of particular ciphertexts in original_collection
        with particular ciphertexts of shuffled_collection.

        Arguments:
            original_collection::CiphertextCollection   --
                The original collection of ciphertexts.
            shuffled_collection::CiphertextCollection   --
                Another collection for which we wish to know if the current
                ShufflingProof object demonstrates equivalence with
                original_collection.

        Returns:
            result::bool    -- True if this proof shows both collections to be
                               equivalent.
                               False otherwise.
        """
        # Get the security parameter P with which the proof was originally
        # created. This is reflect in the length of self._collections and
        # self._mappings.
        assert len(self._collections) == len(self._mappings), \
            "The length of the private properties self._collections and " \
            "self._mappings of ShufflingProof must always be the same."
        security_parameter = len(self._collections)

        # Get the security parameter specified in params
        minimum_allowed_security_parameter = params.SHUFFLING_PROOF_SECURITY_PARAMETER

        # Check that the security parameter is <= 256, since that is the most
        # bits of challenge we can currently have. Also check that P is at least 1
        if (minimum_allowed_security_parameter < 1
                or minimum_allowed_security_parameter > 256):
            raise ValueError("Security parameter for shuffling proof " \
                    "(params.SHUFFLING_PROOF_SECURITY_PARAMETER) is out of " \
                    "range. The security parameter must be between 1 and 256, "\
                    "its current value is %d. If you have set " \
                    "CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER in the file " \
                    "params.py, please correct this value or set it to None, " \
                    "in order for the security parameter to be decided based " \
                    "on the global SECURITY_LEVEL of plonevotecryptolib. It " \
                    "is recommended that " \
                    "CUSTOM_SHUFFLING_PROOF_SECURITY_PARAMETER be always set " \
                    "to None for deployment operation of plonevotecryptolib." \
                    % security_parameter)

        # Check that the security parameter for which the proof was generated
        # is correct and meets the security standards declared in params.py
        if (security_parameter < minimum_allowed_security_parameter
                or security_parameter < 1 or security_parameter > 256):
            raise InvalidShuffilingProofError("The security parameter for " \
                    "(which the current proof was created is %d. This is " \
                    "(either an incorrect value (outside of the [1,256] " \
                    "(range) or not secure enough to meet the standards set " \
                    "(in the configuration of params.py (< %d). The proof " \
                    "(is thus invalid." \
                    % (security_parameter,
                      minimum_allowed_security_parameter))

        # Generate the challenge
        challenge = \
            self._generate_challenge(original_collection, shuffled_collection)

        # Verify that the challenge corresponds to the stored one
        if (challenge != self._challenge):
            return False

        # Get the challenge as a BitStream for easier manipulation
        challenge_bits = BitStream()
        challenge_bits.put_hex(challenge)
        challenge_bits.seek(0)  # back to the beginning of the stream

        # For each of the first P bits in the stream
        for i in range(0, security_parameter):
            bit = challenge_bits.get_num(1)
            if (bit == 0):
                # verify that self._mapping[i] maps original_collection into
                # self._collections[i]
                if (not self._mappings[i].verify(original_collection,
                                                 self._collections[i])):
                    return False

            elif (bit == 1):
                # verify that self._mapping[i] self._collections[i] into
                # self._collections[i]
                if (not self._mappings[i].verify(self._collections[i],
                                                 shuffled_collection)):
                    return False
            else:
                assert False, "We took a single bit, its value must be either "\
                        "0 or 1."

        # If we made it so far, the proof is correct
        # (each mapping is in accordance to the challenge and valid)
        return True
Esempio n. 33
0
    def decrypt_to_bitstream(self, ciphertext, task_monitor=None, force=False):
        """
        Decrypts the given ciphertext into a bitstream.
        
        If the bitstream was originally encrypted with PublicKey.encrypt_X(), 
        then this method returns a bitstream following the format described 
        in Note 001 of the Ciphertext.py file:
            [size (64 bits) | message (size bits) | padding (X bits) ]
        
        Arguments:
            ciphertext::Ciphertext    -- An encrypted Ciphertext object.
            task_monitor::TaskMonitor    -- A task monitor for this task.
            force:bool    -- Set this to true if you wish to force a decryption 
                           attempt, even when the ciphertext's stored public key
                           fingerprint does not match that of the public key 
                           associated with this private key.
        
        Returns:
            bitstream::Bitstream    -- A bitstream containing the unencrypted 
                                       data.
        
        Throws:
            IncompatibleCiphertextError -- The given ciphertext does not appear 
                                           to be decryptable with the selected 
                                           private key.
        """
        # Check that the public key fingerprint stored in the ciphertext
        # matches the public key associated with this private key.
        if (not force):
            if (ciphertext.nbits != self.cryptosystem.get_nbits()):
                raise IncompatibleCiphertextError("The given ciphertext is " \
                        "not decryptable with the selected private key: " \
                        "incompatible cryptosystem/key sizes.")

            if (ciphertext.pk_fingerprint !=
                    self.public_key.get_fingerprint()):
                raise IncompatibleCiphertextError("The given ciphertext is " \
                        "not decryptable with the selected private key: " \
                        "public key fingerprint mismatch.")

        # We read and decrypt the ciphertext block by block
        # See "Handbook of Applied Cryptography" Algorithm 8.18
        bitstream = BitStream()

        block_size = self.cryptosystem.get_nbits() - 1
        prime = self.cryptosystem.get_prime()
        key = self._key

        # Check if we have a task monitor and register with it
        if (task_monitor != None):
            # One tick per block
            ticks = ciphertext.get_length()
            decrypt_task_mon = \
                task_monitor.new_subtask("Decrypt data", expected_ticks = ticks)

        for gamma, delta in ciphertext:
            assert max(gamma, delta) < 2**(block_size + 1), \
                "The ciphertext object includes blocks larger than the " \
                "expected block size."
            m = (pow(gamma, prime - 1 - key, prime) * delta) % prime
            bitstream.put_num(m, block_size)

            if (task_monitor != None): decrypt_task_mon.tick()

        return bitstream
Esempio n. 34
0
    def encrypt_bitstream(self, bitstream, pad_to=None, task_monitor=None):
        """
        Encrypts the given bitstream into a ciphertext object.
        
        Arguments:
            bitstream::BitStream-- A stream of bits to encrypt 
                                   (see BitStream utility class).
            pad_to::int            -- Minimum size (in bytes) of the resulting 
                                   ciphertext. Data will be padded before 
                                   encryption to match this size.
            task_monitor::TaskMonitor    -- A task monitor for this task.
        
        Returns:
            ciphertext:Ciphertext    -- A ciphertext object encapsulating the 
                                       encrypted data.        
        """
        random = StrongRandom()

        ## PART 1
        # First, format the bitstream as per Ciphertext.py Note 001,
        # previous to encryption.
        #     [size (64 bits) | message (size bits) | padding (X bits) ]
        ##
        formated_bitstream = BitStream()

        # The first 64 encode the size of the actual data in bits
        SIZE_BLOCK_LENGTH = 64
        size_in_bits = bitstream.get_length()

        if (size_in_bits >= 2**SIZE_BLOCK_LENGTH):
            raise ValueError("The size of the bitstream to encrypt is larger " \
                             "than 16 Exabits. The current format for  " \
                             "PloneVote ciphertext only allows encrypting a  " \
                             "maximum of 16 Exabits of information.")

        formated_bitstream.put_num(size_in_bits, SIZE_BLOCK_LENGTH)

        # We then copy the contents of the original bitstream
        bitstream.seek(0)
        formated_bitstream.put_bitstream_copy(bitstream)

        # Finally, we append random data until we reach the desired pad_to
        # length
        unpadded_length = formated_bitstream.get_length()
        if (pad_to != None and (pad_to * 8) > unpadded_length):
            full_length = pad_to * 8
        else:
            full_length = unpadded_length

        padding_left = full_length - unpadded_length

        while (padding_left > 1024):
            padding_bits = random.randint(1, 2**1024)
            formated_bitstream.put_num(padding_bits, 1024)
            padding_left -= 1024

        if (padding_left > 0):
            padding_bits = random.randint(1, 2**padding_left)
            formated_bitstream.put_num(padding_bits, padding_left)
            padding_left = 0

        ## PART 2
        # We encrypt the formated bitsteam using ElGamal into a Ciphertext
        # object.
        # See "Handbook of Applied Cryptography" Algorithm 8.18
        ##

        # block_size is the size of each block of bits to encrypt
        # since we can only encrypt messages in [0, p - 1]
        # we should use (nbits - 1) as the block size, where
        # 2**(nbits - 1) < p < 2**nbits

        block_size = self.cryptosystem.get_nbits() - 1
        prime = self.cryptosystem.get_prime()
        generator = self.cryptosystem.get_generator()

        # We pull data from the bitstream one block at a time and encrypt it
        formated_bitstream.seek(0)
        ciphertext = \
            Ciphertext(self.cryptosystem.get_nbits(), self.get_fingerprint())

        plaintext_bits_left = formated_bitstream.get_length()

        # Check if we have a task monitor and register with it
        if (task_monitor != None):
            # We will do two tick()s per block to encrypt: one for generating
            # the gamma component of the ciphertext block and another for the
            # delta component (those are the two time intensive steps,
            # because of exponentiation).
            ticks = math.ceil((1.0 * plaintext_bits_left) / block_size) * 2
            encrypt_task_mon = \
                task_monitor.new_subtask("Encrypt data", expected_ticks = ticks)

        while (plaintext_bits_left > 0):

            # get next block (message, m, etc) to encrypt
            if (plaintext_bits_left >= block_size):
                block = formated_bitstream.get_num(block_size)
                plaintext_bits_left -= block_size
            else:
                block = formated_bitstream.get_num(plaintext_bits_left)
                # Encrypt as if the stream was filled with random data past its
                # end, this avoids introducing a 0's gap during decryption to
                # bitstream
                displacement = block_size - plaintext_bits_left
                block = block << displacement
                padding = random.randint(0, 2**displacement - 1)
                assert (padding / 2**displacement == 0), \
                            "padding should be at most displacement bits long"
                block = block | padding
                plaintext_bits_left = 0

            # Select a random integer k, 1 <= k <= p − 2
            k = random.randint(1, prime - 2)

            # Compute gamma and delta
            gamma = pow(generator, k, prime)
            if (task_monitor != None): encrypt_task_mon.tick()

            delta = (block * pow(self._key, k, prime)) % prime
            if (task_monitor != None): encrypt_task_mon.tick()

            # Add this encrypted data portion to the ciphertext object
            ciphertext.append(gamma, delta)

        # return the ciphertext object
        return ciphertext