def get_package_keycode(self, package_id, public_key_id=None, private_key=None): """ Gets the decrypted package keycode using trusted device keys. Trusted device must have been assigned prior to the package being uploaded. :param package_id: The package Id :param public_key_id: The public key id for the trusted device :param private_key: The private trusted device key :return: """ #if path_to_keys: # data = read_key_pair(path_to_keys) # public_key_id = data["publicKeyId"] # private_key = data["privateKey"] if public_key_id is None or private_key is None: public_key_id = self.KEY_ID private_key = self.KEY_PAIR endpoint = '/package/' + package_id + '/link/' + public_key_id url = self.BASE_URL + endpoint headers = make_headers(self.API_SECRET, self.API_KEY, endpoint) try: keycode = requests.get(url, headers=headers).json()["message"] key_pair = pgpy.PGPKey.from_blob(str(private_key))[0] keycode_message = PGPMessage.from_blob(keycode) decrypted_keycode = key_pair.decrypt(keycode_message).message return {"keyCode": decrypted_keycode} except Exception as e: raise GetKeycodeFailedException(details=str(e))
def __init__(self, sendsafely_instance, package_variables=None): """ :param sendsafely_instance: The authenticated SendSafely object. :param package_variables: """ super().__init__() self.initialized_via_keycode = True if package_variables is None: self.client_secret = _generate_keycode() self.sendsafely = sendsafely_instance data = {"vdr": "false"} endpoint = "/package" url = self.sendsafely.BASE_URL + endpoint headers = make_headers(self.sendsafely.API_SECRET, self.sendsafely.API_KEY, endpoint, request_body=json.dumps(data)) response = requests.put(url, headers=headers, json=data).json() try: self.server_secret = response["serverSecret"] self.package_id = response["packageId"] self.package_code = response["packageCode"] except KeyError: raise CreatePackageFailedException(details=response["message"]) else: self.sendsafely = sendsafely_instance self.package_id = package_variables["packageId"] self.package_code = package_variables["packageCode"] self.client_secret = package_variables["clientSecret"] if not self.client_secret: self.initialized_via_keycode = False self.server_secret = package_variables["serverSecret"]
def get_sent_packages(self, row_index=0, page_size=100): """ Get all packages sent by this user :param row_index: The row to start at :param page_size: The number of pages to fetch at a time :return: The JSON response as a list of packages """ endpoint = "/package" url = self.BASE_URL + endpoint all_packages = [] pagination_data = [] try: while True: params = {"rowIndex": row_index, "pageSize": page_size} headers = make_headers(self.API_SECRET, self.API_KEY, endpoint) response = requests.get(url, headers=headers, params=params).json() pagination = response["pagination"] pagination_data.append(pagination) packages = response["packages"] all_packages.extend(packages) if len(packages) < page_size: return { "packages": all_packages, "pagination": pagination_data } row_index += page_size except Exception as e: GetPackagesException(details=str(e))
def generate_trusted_device_key_pair(self, description): """ Adds a public key to this user :param description: A description of this public key to submit to SendSafely :return: The response, including key pair """ key = pgpy.PGPKey.new(pgpy.constants.PubKeyAlgorithm.RSAEncryptOrSign, 2048) email = self.get_user_information()["email"] uid = pgpy.PGPUID.new('Trusted Browser', email=email) key.add_uid( uid=uid, usage={KeyFlags.EncryptCommunications, KeyFlags.EncryptStorage}, hashes=[HashAlgorithm.SHA256], ciphers=[SymmetricKeyAlgorithm.AES256], compression=[CompressionAlgorithm.Uncompressed]) public_key = str(key.pubkey) endpoint = "/public-key" url = self.BASE_URL + endpoint body = {"publicKey": public_key, "description": description} headers = make_headers(self.API_SECRET, self.API_KEY, endpoint, request_body=json.dumps(body)) response = requests.put(url, headers=headers, json=body).json() if response["response"] != "SUCCESS": raise TrustedDeviceException(details=response["message"]) self.KEY_ID = response["id"] self.KEY_PAIR = key result = { "response": response, "privateKey": str(key), "publicKey": public_key } return result
def _add_file(self, filename, filesize, parts=1, directory_id=None): """ Adds the passed file to the package with the specified ID If bigger than 2.5 MBs, split the file by 2.5 MBs and set parts according to the amount of splits """ part_size = 2621440 if filesize > part_size: parts = 1 + math.ceil((filesize - (part_size / 4)) / part_size) body = { 'filename': filename, 'parts': parts, 'filesize': filesize } if directory_id: body["directoryId"] = directory_id endpoint = "/package/" + self.package_id + "/file" url = self.sendsafely.BASE_URL + endpoint headers = make_headers(self.sendsafely.API_SECRET, self.sendsafely.API_KEY, endpoint, request_body=json.dumps(body)) try: response = requests.put(url=url, json=body, headers=headers).json() except Exception as e: raise AddFileFailedException(details=str(e)) if response["response"] != "SUCCESS": raise AddFileFailedException(details=response["message"]) return response
def get_public_keys(self): endpoint = '/package/' + self.package_id + '/public-keys/' url = self.sendsafely.BASE_URL + endpoint headers = make_headers(self.sendsafely.API_SECRET, self.sendsafely.API_KEY, endpoint) response = requests.get(url=url, headers=headers).json() if response["response"] != "SUCCESS": raise GetPublicKeysFailedException(details=response["message"]) return response["publicKeys"]
def get_file_information(self, file_id): """ Return the file information for a specified fileId """ endpoint = "/package/" + self.package_id + "/file/" + file_id url = self.sendsafely.BASE_URL + endpoint headers = make_headers(self.sendsafely.API_SECRET, self.sendsafely.API_KEY, endpoint) response = requests.get(url=url, headers=headers).json() if response["response"] != "SUCCESS": raise GetFileInformationException(details=response["message"]) return response["file"]
def get_user_information(self): endpoint = "/user" url = self.BASE_URL + endpoint headers = make_headers(self.API_SECRET, self.API_KEY, endpoint) try: response = requests.get(url, headers=headers).json() except Exception as e: raise GetUserInformationException(details=str(e)) if response["response"] != "SUCCESS": raise GetUserInformationException(details=response["message"]) return response
def delete_file_from_package(self, file_id): """ Deletes the file with the specified id from the package with the specified ID """ endpoint = "/package/" + self.package_id + "/file/" + file_id url = self.sendsafely.BASE_URL + endpoint headers = make_headers(self.sendsafely.API_SECRET, self.sendsafely.API_KEY, endpoint) try: response = requests.delete(url=url, headers=headers).json() except Exception as e: raise DeleteFileException(details=e) if response["response"] != "SUCCESS": raise DeleteFileException(details=response["message"]) return response
def get_package_message(self): """ :returns: The decrypted message """ self._block_operation_without_keycode() try: checksum = _calculate_package_checksum(package_code=self.package_code, keycode=self.client_secret) endpoint = '/package/' + self.package_id + '/message/' + checksum["checksum"] url = self.sendsafely.BASE_URL + endpoint headers = make_headers(self.sendsafely.API_SECRET, self.sendsafely.API_KEY, endpoint) response = requests.get(url, headers=headers).json() message = _decrypt_message(response["message"], server_secret=self.server_secret, client_secret=self.client_secret) return message except Exception as e: raise GetPackageMessageException(details=str(e))
def delete_package(self, package_id): """ Deletes a given package. :param package_id: the package you desire to delete. :return: the JSON response. """ endpoint = "/package/" + package_id url = self.BASE_URL + endpoint headers = make_headers(self.API_SECRET, self.API_KEY, endpoint) try: response = requests.delete(url, headers=headers).json() except Exception as e: raise DeletePackageException(details=str(e)) if response["response"] != "SUCCESS": raise DeletePackageException(details=response["message"]) return response
def revoke_trusted_device_key(self, public_key_id): """ Removes the public key with public_key_id from this account. :param public_key_id: The public key ID :return: the JSON response """ endpoint = "/public-key/" + public_key_id url = self.BASE_URL + endpoint headers = make_headers(self.API_SECRET, self.API_KEY, endpoint) try: response = requests.delete(url, headers=headers).json() except Exception as e: raise TrustedDeviceException(details=str(e)) if response["response"] != "SUCCESS": raise TrustedDeviceException(details=response["message"]) return response
def get_package_information(self, package_id): """ Get a detailed status of a given package :param package_id: The package you desire to inquire about. :return: The detailed status as a JSON response. """ endpoint = "/package/" + package_id url = self.BASE_URL + endpoint headers = make_headers(self.API_SECRET, self.API_KEY, endpoint) try: response = requests.get(url, headers=headers).json() except Exception as e: raise GetPackageInformationFailedException(details=str(e)) if response["response"] != "SUCCESS": raise GetPackageInformationFailedException( details=response["message"]) return response
def _upload_keycodes(self): # Get public keys available for the users public_keys = self.get_public_keys() uploaded = [] # Upload keycodes for key in public_keys: public_key_id = key["id"] encrypted_keycode = _encrypt_keycode(self.client_secret, key["key"]) endpoint = '/package/' + self.package_id + '/link/' + public_key_id url = self.sendsafely.BASE_URL + endpoint body = {"keycode": encrypted_keycode} headers = make_headers(self.sendsafely.API_SECRET, self.sendsafely.API_KEY, endpoint, request_body=json.dumps(body)) response = requests.put(url=url, headers=headers, json=body).json() if response["response"] != "SUCCESS": raise UploadKeycodeException(details=response["message"]) uploaded.append(public_key_id) return {"uploadedPublicKeyIds": uploaded}
def add_recipient(self, email): """ Adds a recipient to this package :param email: The email to add to this package :return: """ sendsafely = self.sendsafely endpoint = "/package/" + self.package_id + "/recipient" url = sendsafely.BASE_URL + endpoint body = {'email': email} headers = make_headers(sendsafely.API_SECRET, sendsafely.API_KEY, endpoint, request_body=json.dumps(body)) try: response = requests.put(url, headers=headers, json=body).json() except Exception as e: raise AddRecipientFailedException(details=str(e)) if response["response"] != "SUCCESS": raise AddRecipientFailedException(details=response["message"]) return response
def finalize(self): """ Finalizes the package, returns a link, including the keycode :returns: A link the recipient can access it with if successful """ self._upload_keycodes() checksum = _calculate_package_checksum(package_code=self.package_code, keycode=self.client_secret) endpoint = '/package/' + self.package_id + '/finalize' url = self.sendsafely.BASE_URL + endpoint headers = make_headers(self.sendsafely.API_SECRET, self.sendsafely.API_KEY, endpoint, request_body=json.dumps(checksum)) response = requests.post(url=url, json=checksum, headers=headers).json() if "errors" not in response: if self.initialized_via_keycode: keycode = "#keyCode=" + self.client_secret response["message"] = response["message"] + keycode else: raise FinalizePackageFailedException(details=str(response)) return response
def update_recipient_phone_number(self, recipient_id, phone, country_code="US"): """ Update a recipient phone number :param recipient_id: The id of the recipient :param phone: The desired phone number, string in the form "(123) 456-7890" :param country_code: The country code :return: """ sendsafely = self.sendsafely endpoint = "/package/" + self.package_id + "/recipient/" + recipient_id url = sendsafely.BASE_URL + endpoint body = {'phoneNumber': phone, 'countrycode': country_code} headers = make_headers(sendsafely.API_SECRET, sendsafely.API_KEY, endpoint, request_body=json.dumps(body)) try: response = requests.post(url, headers=headers, json=body).json() except Exception as e: raise UpdateRecipientFailedException(details=str(e)) if response["response"] != "SUCCESS": raise UpdateRecipientFailedException(details=response["message"]) return response
def encrypt_and_upload_message(self, message): """ Adds a message to this package :param message: the message to add :return: the JSON response """ self._block_operation_without_keycode() try: encrypted_message = _encrypt_message(message_to_encrypt=message, server_secret=self.server_secret, client_secret=self.client_secret) body = {'message': encrypted_message} endpoint = "/package/" + self.package_id + "/message/" url = self.sendsafely.BASE_URL + endpoint headers = make_headers(self.sendsafely.API_SECRET, self.sendsafely.API_KEY, endpoint, request_body=json.dumps(body)) response = requests.put(url, headers=headers, json=body).json() except Exception as e: raise UploadMessageException(details=str(e)) if response["response"] != "SUCCESS": raise UploadMessageException(details=response["message"]) return response