Ejemplo n.º 1
0
    def Decrypt(self, input_bytes):
        """
    Decrypts the given ciphertext.

    @param input_bytes: raw byte string formatted as Header|IV|Ciph|Sig where
      Sig is the signature over the entire payload (Header|IV|Ciph).
    @type input_bytes: string

    @return: plaintext message
    @rtype: string

    @raise ShortCiphertextError: if the ciphertext is too short to have IV & Sig
    @raise InvalidSignatureError: if the signature doesn't correspond to payload
    """
        data_bytes = input_bytes[keyczar.HEADER_SIZE:]  # remove header
        if len(data_bytes) < self.block_size + util.HLEN:  # IV + sig
            raise errors.ShortCiphertextError(len(data_bytes))

        iv_bytes = data_bytes[:self.
                              block_size]  # first block of bytes is the IV
        ciph_bytes = data_bytes[self.block_size:-util.HLEN]
        sig_bytes = data_bytes[-util.HLEN:]  # last 20 bytes are sig
        if not self.hmac_key.Verify(input_bytes[:-util.HLEN], sig_bytes):
            raise errors.InvalidSignatureError()

        plain = AES.new(self.key_bytes, AES.MODE_CBC,
                        iv_bytes).decrypt(ciph_bytes)
        return self._UnPad(plain)
Ejemplo n.º 2
0
    def Decrypt(self, ciphertext, decoder=util.Base64WSDecode):
        """
    Decrypts the given ciphertext and returns the plaintext.

    @param ciphertext: ciphertext to be decrypted - by default is Base64 encoded
    @type ciphertext: string

    @param decoder: function to perform decoding. Defaults to Base64, use None
    for no decoding.
    @type encoder: function

    @return: plaintext message
    @rtype: string

    @raise ShortCiphertextError: if length is too short to have Header, IV, Sig
    @raise BadVersionError: if header specifies an illegal version
    @raise BadFormatError: if header specifies an illegal format
    @raise KeyNotFoundError: if key specified in header doesn't exist
    @raise InvalidSignatureError: if the signature can't be verified
    """
        data_bytes = decoder(ciphertext) if decoder else ciphertext
        if len(data_bytes) < HEADER_SIZE:
            raise errors.ShortCiphertextError(len(data_bytes))
        key = self._ParseHeader(data_bytes[:HEADER_SIZE])
        return key.Decrypt(data_bytes)
Ejemplo n.º 3
0
    def DecryptIO(self, reader, writer):
        """
    Decrypts from an IO reader and writes the plaintext to an IO writer.

    @param reader: binary ciphertext to be decrypted
    @type reader: io.BufferedReader

    @param writer: writer to recieve binary plaintext
    @type encoder: io.BufferedWriter

    @raise ShortCiphertextError: if length is too short to have Header, IV, Sig
    @raise BadVersionError: if header specifies an illegal version
    @raise BadFormatError: if header specifies an illegal format
    @raise KeyNotFoundError: if key specified in header doesn't exist
    @raise InvalidSignatureError: if the signature can't be verified
    """
        header = util.ReadLength(reader, constants.HEADER_SIZE)
        if len(header) < constants.HEADER_SIZE:
            raise errors.ShortCiphertextError(len(header))
        matchedkeys = self._ParseHeader(header)
        tempwriter = writer
        multiplekeys = len(matchedkeys) > 1
        for key in matchedkeys:
            if multiplekeys:
                # if we have more than one key possiblity we need
                # to take precations
                if not reader.seekable():
                    # read the entire stream if it's not seekable
                    reader = util.BytesReader(header + util.ReadAll(reader))
                reader.seek(constants.HEADER_SIZE)
                # use a temp writer
                tempwriter, getvalue = util.BytesWriter()
            try:
                key.DecryptIO(header, reader, tempwriter)
                if multiplekeys:
                    #write to final output on success
                    writer.write(getvalue())
                    writer.flush()
                return
            except errors.InvalidSignatureError:
                pass
            except errors.OaepDecodingError:
                pass
            except:
                pass  # we should pass on all exceptions
                # as to not leak anything more than
                # invalid cipher text

        raise errors.InvalidSignatureError()
Ejemplo n.º 4
0
  def read(self, chars=-1):
    """ 
    Decrypts data from the source stream and returns the resulting plaintext.
    NOTE: the signature validation is performed on the final read if sufficient
    data is available. Streaming => it isn't possible to validate up front as
    done by Decrypt().

    @param chars: indicates the number of characters to read from the stream.
    read() will never return more than chars characters, but it might return
    less, if there are not enough characters available.
    @type chars: integer

    @raise ShortCiphertextError: if the ciphertext is too short to have IV & Sig
    @raise InvalidSignatureError: if the signature doesn't correspond to payload
    @raise KeyNotFoundError: if key specified in header doesn't exist
    @raise ValueError: if stream closed
    """
    self.__CheckOpen('read')
    is_data_avail = True
    if not self.__key:
      is_data_avail = self.__CreateKey()

    if is_data_avail and self.__key and not self.__cipher:
      is_data_avail = self.__CreateCipher()

    if is_data_avail and self.__key and self.__cipher:
      data_to_decrypt = b''
      need_more_data = True
      while need_more_data:
        read_bytes, is_data_avail = self.__ReadBytes(self.__key.block_size,
                                                     block=False)
        if read_bytes:
          self.__encrypted_buffer += read_bytes

        reserved_data_len = util.HLEN
        if is_data_avail:
          reserved_data_len += self.__key.block_size

        available_data = self.__encrypted_buffer[:-reserved_data_len]

        if is_data_avail:
          no_decrypt_len = len(available_data) % self.__key.block_size
        else:
          no_decrypt_len = 0
        # slicing with [:-0] does not work!
        if no_decrypt_len:
          data_to_decrypt = available_data[:-no_decrypt_len]
        else:
          data_to_decrypt = available_data

        need_more_data = (is_data_avail and not data_to_decrypt)

      if data_to_decrypt:
        self.__hmac_stream.Update(data_to_decrypt)
        self.__encrypted_buffer = self.__encrypted_buffer[len(data_to_decrypt):]
        decrypted_data = self.__cipher.decrypt(data_to_decrypt)

        if not is_data_avail:
          if len(self.__encrypted_buffer) != util.HLEN:
            raise errors.ShortCiphertextError(len(self.__encrypted_buffer))
          current_sig_bytes = self.__hmac_stream.Sign()
          msg_sig_bytes = self.__encrypted_buffer
          self.__encrypted_buffer = b''
          # it is important to verify mac before unpadding plaintext
          if not self.__key.hmac_key.VerifySignedData(current_sig_bytes, 
                                                      msg_sig_bytes):
            raise errors.InvalidSignatureError()
          decrypted_data = self.__key._UnPad(decrypted_data)

        self.__decrypted_buffer += decrypted_data

    if chars < 0:
      result = self.__decrypted_buffer
      self.__decrypted_buffer = b''
    else:
      result = self.__decrypted_buffer[:chars]
      self.__decrypted_buffer = self.__decrypted_buffer[chars:]

    if not result and is_data_avail:
      result = None

    return result