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)
def handle_request(ip, request): if request.get('version') != '1': raise errors.UnsupportedVersionError() if request.get('api_key') not in settings.API_KEYS: raise errors.InvalidAPIKeyError() if not is_nonce_ok(request): raise errors.InvalidNonceError() if not is_signature_ok(request): raise errors.InvalidSignatureError() if not is_timestamp_ok(request): raise errors.InvalidTimestampError() if request.get('request') not in REQUEST_TABLE: raise errors.InvalidRequestError() if not is_request_authorized(request): raise errors.UnauthorizedRequestError() if not is_ip_authorized(ip, request): raise errors.UnauthorizedIPAddressError(ip) return dispatch_request(ip, request)
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 = '' 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: decrypted_data = self.__key._UnPad(decrypted_data) self.__decrypted_buffer += decrypted_data 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 = '' if not self.__key.hmac_key.VerifySignedData( current_sig_bytes, msg_sig_bytes): raise errors.InvalidSignatureError() if chars < 0: result = self.__decrypted_buffer self.__decrypted_buffer = '' else: result = self.__decrypted_buffer[:chars] self.__decrypted_buffer = self.__decrypted_buffer[chars:] if not result and is_data_avail: result = None return result