def from_pickle(cls, pickle, passphrase=""): # types: (bytes, str) -> PkDecryption if not pickle: raise ValueError("Pickle can't be empty") byte_key = to_bytes(passphrase) key_buffer = ffi.new("char[]", byte_key) pickle_buffer = ffi.new("char[]", pickle) pubkey_length = lib.olm_pk_key_length() pubkey_buffer = ffi.new("char[]", pubkey_length) obj = cls.__new__(cls) ret = lib.olm_unpickle_pk_decryption( obj._pk_decryption, key_buffer, len(byte_key), pickle_buffer, len(pickle), pubkey_buffer, pubkey_length) obj._check_error(ret) obj.public_key = bytes_to_native_str(ffi.unpack( pubkey_buffer, pubkey_length )) return obj
def pickle(self, passphrase=""): # type: (Optional[str]) -> bytes """Store an inbound group session. Stores a group session as a base64 string. Encrypts the session using the supplied passphrase. Returns a byte object containing the base64 encoded string of the pickled session. Args: passphrase(str, optional): The passphrase to be used to encrypt the session. """ byte_passphrase = bytes(passphrase, "utf-8") if passphrase else b"" passphrase_buffer = ffi.new("char[]", byte_passphrase) pickle_length = lib.olm_pickle_inbound_group_session_length( self._session) pickle_buffer = ffi.new("char[]", pickle_length) ret = lib.olm_pickle_inbound_group_session(self._session, passphrase_buffer, len(byte_passphrase), pickle_buffer, pickle_length) self._check_error(ret) return ffi.unpack(pickle_buffer, pickle_length)
def decrypt(self, message): # type: (_OlmMessage) -> str """Decrypts a message using the session. Returns the plaintext string on success. Raises OlmSessionError on failure. If the base64 couldn't be decoded then the error message will be "INVALID_BASE64". If the message is for an unsupported version of the protocol the error message will be "BAD_MESSAGE_VERSION". If the message couldn't be decoded then the error message will be "BAD_MESSAGE_FORMAT". If the MAC on the message was invalid then the error message will be "BAD_MESSAGE_MAC". Args: message(OlmMessage): The Olm message that will be decrypted. It can be either an OlmPreKeyMessage or an OlmMessage. """ if not message.ciphertext: raise ValueError("Ciphertext can't be empty") byte_ciphertext = to_bytes(message.ciphertext) ciphertext_buffer = ffi.new("char[]", byte_ciphertext) max_plaintext_length = lib.olm_decrypt_max_plaintext_length( self._session, message.message_type, ciphertext_buffer, len(byte_ciphertext)) plaintext_buffer = ffi.new("char[]", max_plaintext_length) ciphertext_buffer = ffi.new("char[]", byte_ciphertext) plaintext_length = lib.olm_decrypt(self._session, message.message_type, ciphertext_buffer, len(byte_ciphertext), plaintext_buffer, max_plaintext_length) self._check_error(plaintext_length) return bytes_to_native_str( ffi.unpack(plaintext_buffer, plaintext_length))
def from_pickle(cls, pickle, passphrase=""): # type: (bytes, Optional[str]) -> OutboundGroupSession """Load a previously stored outbound group session. Loads an outbound group session from a pickled base64 string and returns an OutboundGroupSession object. Decrypts the session using the supplied passphrase. Raises OlmSessionError on failure. If the passphrase doesn't match the one used to encrypt the session then the error message for the exception will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then the error message will be "INVALID_BASE64". Args: pickle(bytes): Base64 encoded byte string containing the pickled session passphrase(str, optional): The passphrase used to encrypt the """ if not pickle: raise ValueError("Pickle can't be empty") byte_passphrase = bytes(passphrase, "utf-8") if passphrase else b"" passphrase_buffer = ffi.new("char[]", byte_passphrase) pickle_buffer = ffi.new("char[]", pickle) obj = cls.__new__(cls) ret = lib.olm_unpickle_outbound_group_session(obj._session, passphrase_buffer, len(byte_passphrase), pickle_buffer, len(pickle)) obj._check_error(ret) return obj
def encrypt(self, plaintext): # type: (AnyStr) -> str """Encrypt a message. Returns the encrypted ciphertext. Args: plaintext(str): A string that will be encrypted using the group session. """ byte_plaintext = to_bytes(plaintext) message_length = lib.olm_group_encrypt_message_length( self._session, len(byte_plaintext)) message_buffer = ffi.new("char[]", message_length) plaintext_buffer = ffi.new("char[]", byte_plaintext) ret = lib.olm_group_encrypt( self._session, plaintext_buffer, len(byte_plaintext), message_buffer, message_length, ) self._check_error(ret) return bytes_to_native_str(ffi.unpack(message_buffer, message_length))
def from_pickle(cls, pickle, passphrase=""): # type: (bytes, Optional[str]) -> Account """Load a previously stored olm account. Loads an account from a pickled base64-encoded string and returns an Account object. Decrypts the account using the supplied passphrase. Raises OlmAccountError on failure. If the passphrase doesn't match the one used to encrypt the account then the error message for the exception will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then the error message will be "INVALID_BASE64". Args: pickle(bytes): Base64 encoded byte string containing the pickled account passphrase(str, optional): The passphrase used to encrypt the account. """ if not pickle: raise ValueError("Pickle can't be empty") byte_key = bytes(passphrase, "utf-8") if passphrase else b"" key_buffer = ffi.new("char[]", byte_key) pickle_buffer = ffi.new("char[]", pickle) obj = cls.__new__(cls) ret = lib.olm_unpickle_account(obj._account, key_buffer, len(byte_key), pickle_buffer, len(pickle)) obj._check_error(ret) return obj
def __init__(self, seed): # type: (bytes) -> None """Create a new signing object. Args: seed(bytes): the seed to use as the private key for signing. The seed must have the same length as the seeds generated by PkSigning.generate_seed(). """ if not seed: raise ValueError("seed can't be empty") self._buf = ffi.new("char[]", lib.olm_pk_signing_size()) self._pk_signing = lib.olm_pk_signing(self._buf) track_for_finalization(self, self._pk_signing, _clear_pk_signing) seed_buffer = ffi.new("char[]", seed) pubkey_length = lib.olm_pk_signing_public_key_length() pubkey_buffer = ffi.new("char[]", pubkey_length) ret = lib.olm_pk_signing_key_from_seed(self._pk_signing, pubkey_buffer, pubkey_length, seed_buffer, len(seed)) # zero out copies of the seed lib.memset(seed_buffer, 0, len(seed)) self._check_error(ret) self.public_key = bytes_to_native_str( ffi.unpack(pubkey_buffer, pubkey_length))
def decrypt(self, ciphertext): # type: (AnyStr) -> Tuple[str, int] """Decrypt a message Returns a tuple of the decrypted plain-text and the message index of the decrypted message or raises OlmGroupSessionError on failure. On failure the error message of the exception will be: * OLM_INVALID_BASE64 if the message is not valid base64 * OLM_BAD_MESSAGE_VERSION if the message was encrypted with an unsupported version of the protocol * OLM_BAD_MESSAGE_FORMAT if the message headers could not be decoded * OLM_BAD_MESSAGE_MAC if the message could not be verified * OLM_UNKNOWN_MESSAGE_INDEX if we do not have a session key corresponding to the message's index (i.e., it was sent before the session key was shared with us) Args: ciphertext(str): Base64 encoded ciphertext containing the encrypted message """ if not ciphertext: raise ValueError("Ciphertext can't be empty.") byte_ciphertext = to_bytes(ciphertext) # copy because max_plaintext_length will destroy the buffer ciphertext_buffer = ffi.new("char[]", byte_ciphertext) max_plaintext_length = lib.olm_group_decrypt_max_plaintext_length( self._session, ciphertext_buffer, len(byte_ciphertext)) self._check_error(max_plaintext_length) plaintext_buffer = ffi.new("char[]", max_plaintext_length) # copy because max_plaintext_length will destroy the buffer ciphertext_buffer = ffi.new("char[]", byte_ciphertext) message_index = ffi.new("uint32_t*") plaintext_length = lib.olm_group_decrypt(self._session, ciphertext_buffer, len(byte_ciphertext), plaintext_buffer, max_plaintext_length, message_index) self._check_error(plaintext_length) plaintext = bytes_to_native_str( ffi.unpack(plaintext_buffer, plaintext_length)) # clear out copies of the plaintext lib.memset(plaintext_buffer, 0, max_plaintext_length) return plaintext, message_index[0]
def decrypt(self, message, unicode_errors="replace"): # type: (_OlmMessage, str) -> str """Decrypts a message using the session. Returns the plaintext string on success. Raises OlmSessionError on failure. If the base64 couldn't be decoded then the error message will be "INVALID_BASE64". If the message is for an unsupported version of the protocol the error message will be "BAD_MESSAGE_VERSION". If the message couldn't be decoded then the error message will be "BAD_MESSAGE_FORMAT". If the MAC on the message was invalid then the error message will be "BAD_MESSAGE_MAC". Args: message(OlmMessage): The Olm message that will be decrypted. It can be either an OlmPreKeyMessage or an OlmMessage. unicode_errors(str, optional): The error handling scheme to use for unicode decoding errors. The default is "replace" meaning that the character that was unable to decode will be replaced with the unicode replacement character (U+FFFD). Other possible values are "strict", "ignore" and "xmlcharrefreplace" as well as any other name registered with codecs.register_error that can handle UnicodeEncodeErrors. """ if not message.ciphertext: raise ValueError("Ciphertext can't be empty") byte_ciphertext = to_bytes(message.ciphertext) # make a copy the ciphertext buffer, because # olm_decrypt_max_plaintext_length wants to destroy something ciphertext_buffer = ffi.new("char[]", byte_ciphertext) max_plaintext_length = lib.olm_decrypt_max_plaintext_length( self._session, message.message_type, ciphertext_buffer, len(byte_ciphertext)) self._check_error(max_plaintext_length) plaintext_buffer = ffi.new("char[]", max_plaintext_length) # make a copy the ciphertext buffer, because # olm_decrypt_max_plaintext_length wants to destroy something ciphertext_buffer = ffi.new("char[]", byte_ciphertext) plaintext_length = lib.olm_decrypt(self._session, message.message_type, ciphertext_buffer, len(byte_ciphertext), plaintext_buffer, max_plaintext_length) self._check_error(plaintext_length) plaintext = to_unicode_str(ffi.unpack(plaintext_buffer, plaintext_length), errors=unicode_errors) # clear out copies of the plaintext lib.memset(plaintext_buffer, 0, max_plaintext_length) return plaintext
def matches(self, message, identity_key=None): # type: (OlmPreKeyMessage, Optional[AnyStr]) -> bool """Checks if the PRE_KEY message is for this in-bound session. This can happen if multiple messages are sent to this session before this session sends a message in reply. Returns True if the session matches. Returns False if the session does not match. Raises OlmSessionError on failure. If the base64 couldn't be decoded then the error message will be "INVALID_BASE64". If the message was for an unsupported protocol version then the error message will be "BAD_MESSAGE_VERSION". If the message couldn't be decoded then then the error message will be * "BAD_MESSAGE_FORMAT". Args: message(OlmPreKeyMessage): The Olm prekey message that will checked if it is intended for this session. identity_key(str, optional): The identity key of the sender. To check if the message was also sent using this identity key. """ if not isinstance(message, OlmPreKeyMessage): raise TypeError("Matches can only be called with prekey messages.") if not message.ciphertext: raise ValueError("Ciphertext can't be empty") ret = None byte_ciphertext = to_bytes(message.ciphertext) message_buffer = ffi.new("char[]", byte_ciphertext) if identity_key: byte_id_key = to_bytes(identity_key) identity_key_buffer = ffi.new("char[]", byte_id_key) ret = lib.olm_matches_inbound_session_from(self._session, identity_key_buffer, len(byte_id_key), message_buffer, len(byte_ciphertext)) else: ret = lib.olm_matches_inbound_session(self._session, message_buffer, len(byte_ciphertext)) self._check_error(ret) return bool(ret)
def encrypt(self, plaintext): # type: (AnyStr) -> _OlmMessage """Encrypts a message using the session. Returns the ciphertext as an base64 encoded strin on success. Raises OlmSessionError on failure. If there weren't enough random bytes to encrypt the message the error message for the exception will be NOT_ENOUGH_RANDOM. Args: plaintext(str): The plaintext message that will be encrypted. """ byte_plaintext = to_bytes(plaintext) r_length = lib.olm_encrypt_random_length(self._session) random = URANDOM(r_length) random_buffer = ffi.new("char[]", random) message_type = lib.olm_encrypt_message_type(self._session) self._check_error(message_type) ciphertext_length = lib.olm_encrypt_message_length( self._session, len(plaintext) ) ciphertext_buffer = ffi.new("char[]", ciphertext_length) plaintext_buffer = ffi.new("char[]", byte_plaintext) self._check_error(lib.olm_encrypt( self._session, plaintext_buffer, len(byte_plaintext), random_buffer, r_length, ciphertext_buffer, ciphertext_length, )) if message_type == lib.OLM_MESSAGE_TYPE_PRE_KEY: return OlmPreKeyMessage( bytes_to_native_str(ffi.unpack( ciphertext_buffer, ciphertext_length ))) elif message_type == lib.OLM_MESSAGE_TYPE_MESSAGE: return OlmMessage( bytes_to_native_str(ffi.unpack( ciphertext_buffer, ciphertext_length ))) else: # pragma: no cover raise ValueError("Unknown message type")
def generate_bytes(self, extra_info, length): # type: (str, int) -> bytes """Generate bytes to use for the short authentication string. Args: extra_info (str): Extra information to mix in when generating the bytes. length (int): The number of bytes to generate. Raises OlmSasError if the other users persons public key isn't set or an internal Olm error happens. """ if length < 1: raise ValueError("The length needs to be a positive integer value") byte_info = to_bytearray(extra_info) out_buffer = ffi.new("char[]", length) self._check_error( lib.olm_sas_generate_bytes( self._sas, ffi.from_buffer(byte_info), len(byte_info), out_buffer, length ) ) return ffi.unpack(out_buffer, length)
def pickle(self, passphrase=""): # type: (str) -> bytes """Store a PkDecryption object. Stores a PkDecryption object as a base64 string. Encrypts the object using the supplied passphrase. Returns a byte object containing the base64 encoded string of the pickled session. Args: passphrase(str, optional): The passphrase to be used to encrypt the object. """ byte_key = to_bytearray(passphrase) pickle_length = lib.olm_pickle_pk_decryption_length( self._pk_decryption) pickle_buffer = ffi.new("char[]", pickle_length) ret = lib.olm_pickle_pk_decryption(self._pk_decryption, ffi.from_buffer(byte_key), len(byte_key), pickle_buffer, pickle_length) try: self._check_error(ret) finally: # zero out copies of the passphrase for i in range(0, len(byte_key)): byte_key[i] = 0 return ffi.unpack(pickle_buffer, pickle_length)
def __new__(cls, session_key=None): # type: (Type[InboundGroupSession], Optional[str]) -> InboundGroupSession obj = super().__new__(cls) obj._buf = ffi.new("char[]", lib.olm_inbound_group_session_size()) obj._session = lib.olm_inbound_group_session(obj._buf) track_for_finalization(obj, obj._session, _clear_inbound_group_session) return obj
def __init__(self, other_users_pubkey=None): # type: (Optional[str]) -> None """Create a new SAS object. Args: other_users_pubkey(str, optional): The other users public key, this key is necesary to generate bytes for the authentication string as well as to calculate the MAC. Attributes: other_key_set (bool): A boolean flag that tracks if we set the other users public key for this SAS object. Raises OlmSasError on failure. """ self._buf = ffi.new("char[]", lib.olm_sas_size()) self._sas = lib.olm_sas(self._buf) self.other_key_set = False track_for_finalization(self, self._sas, _clear_sas) random_length = lib.olm_create_sas_random_length(self._sas) random = URANDOM(random_length) self._create_sas(random, random_length) if other_users_pubkey: self.set_their_pubkey(other_users_pubkey)
def sign(self, message): # type: (AnyStr) -> str """Signs a message with this account. Signs a message with the private ed25519 identity key of this account. Returns the signature. Raises OlmAccountError on failure. Args: message(str): The message to sign. """ bytes_message = to_bytearray(message) out_length = lib.olm_account_signature_length(self._account) out_buffer = ffi.new("char[]", out_length) try: self._check_error( lib.olm_account_sign(self._account, ffi.from_buffer(bytes_message), len(bytes_message), out_buffer, out_length)) finally: # clear out copies of the message, which may be plaintext if bytes_message is not message: for i in range(0, len(bytes_message)): bytes_message[i] = 0 return bytes_to_native_str(ffi.unpack(out_buffer, out_length))
def pickle(self, passphrase=""): # type: (Optional[str]) -> bytes """Store an Olm account. Stores an account as a base64 string. Encrypts the account using the supplied passphrase. Returns a byte object containing the base64 encoded string of the pickled account. Raises OlmAccountError on failure. Args: passphrase(str, optional): The passphrase to be used to encrypt the account. """ byte_key = bytearray(passphrase, "utf-8") if passphrase else b"" pickle_length = lib.olm_pickle_account_length(self._account) pickle_buffer = ffi.new("char[]", pickle_length) try: self._check_error( lib.olm_pickle_account(self._account, ffi.from_buffer(byte_key), len(byte_key), pickle_buffer, pickle_length)) finally: # zero out copies of the passphrase for i in range(0, len(byte_key)): byte_key[i] = 0 return ffi.unpack(pickle_buffer, pickle_length)
def calculate_mac(self, message, extra_info): # type: (str, str) -> str """Generate a message authentication code based on the shared secret. Args: message (str): The message to produce the authentication code for. extra_info (str): Extra information to mix in when generating the MAC Raises OlmSasError on failure. """ byte_message = to_bytes(message) byte_info = to_bytes(extra_info) mac_length = lib.olm_sas_mac_length(self._sas) mac_buffer = ffi.new("char[]", mac_length) self._check_error( lib.olm_sas_calculate_mac( self._sas, ffi.from_buffer(byte_message), len(byte_message), ffi.from_buffer(byte_info), len(byte_info), mac_buffer, mac_length ) ) return bytes_to_native_str(ffi.unpack(mac_buffer, mac_length))
def calculate_mac_long_kdf(self, message, extra_info): # type: (str, str) -> str """Generate a message authentication code based on the shared secret. This function should not be used unless compatibility with an older non-tagged Olm version is required. Args: message (str): The message to produce the authentication code for. extra_info (str): Extra information to mix in when generating the MAC Raises OlmSasError on failure. """ byte_message = to_bytes(message) byte_info = to_bytes(extra_info) mac_length = lib.olm_sas_mac_length(self._sas) mac_buffer = ffi.new("char[]", mac_length) self._check_error( lib.olm_sas_calculate_mac_long_kdf( self._sas, ffi.from_buffer(byte_message), len(byte_message), ffi.from_buffer(byte_info), len(byte_info), mac_buffer, mac_length ) ) return bytes_to_native_str(ffi.unpack(mac_buffer, mac_length))
def __new__(cls): # type: (Type[Account]) -> Account obj = super().__new__(cls) obj._buf = ffi.new("char[]", lib.olm_account_size()) obj._account = lib.olm_account(obj._buf) track_for_finalization(obj, obj._account, _clear_account) return obj
def decrypt(self, message): # type (PkMessage) -> str ephermal_key = to_bytes(message.ephermal_key) ephermal_key_size = len(ephermal_key) mac = to_bytes(message.mac) mac_length = len(mac) ciphertext = to_bytes(message.ciphertext) ciphertext_length = len(ciphertext) max_plaintext_length = lib.olm_pk_max_plaintext_length( self._pk_decryption, ciphertext_length ) plaintext = ffi.new("char[]", max_plaintext_length) ret = lib.olm_pk_decrypt( self._pk_decryption, ephermal_key, ephermal_key_size, mac, mac_length, ciphertext, ciphertext_length, plaintext, max_plaintext_length) self._check_error(ret) unpacked_plaintext = (ffi.unpack( plaintext, ret )) return bytes_to_native_str(unpacked_plaintext)
def import_session(cls, session_key): # type: (AnyStr) -> InboundGroupSession """Create an InboundGroupSession from an exported session key. Creates an InboundGroupSession with an previously exported session key, raises OlmGroupSessionError on failure. The error message for the exception will be: * OLM_INVALID_BASE64 if the session_key is not valid base64 * OLM_BAD_SESSION_KEY if the session_key is invalid Args: session_key(str): The exported session key with which the inbound group session will be created """ obj = cls.__new__(cls) byte_session_key = to_bytes(session_key) key_buffer = ffi.new("char[]", byte_session_key) ret = lib.olm_import_inbound_group_session(obj._session, key_buffer, len(byte_session_key)) obj._check_error(ret) return obj
def export_session(self, message_index): # type: (int) -> str """Export an inbound group session Export the base64-encoded ratchet key for this session, at the given index, in a format which can be used by import_session(). Raises OlmGroupSessionError on failure. The error message for the exception will be: * OLM_UNKNOWN_MESSAGE_INDEX if we do not have a session key corresponding to the given index (ie, it was sent before the session key was shared with us) Args: message_index(int): The message index at which the session should be exported. """ export_length = lib.olm_export_inbound_group_session_length( self._session) export_buffer = ffi.new("char[]", export_length) ret = lib.olm_export_inbound_group_session(self._session, export_buffer, export_length, message_index) self._check_error(ret) return bytes_to_native_str(ffi.unpack(export_buffer, export_length))
def encrypt(self, plaintext): # type: (AnyStr) -> str """Encrypt a message. Returns the encrypted ciphertext. Args: plaintext(str): A string that will be encrypted using the group session. """ byte_plaintext = to_bytearray(plaintext) message_length = lib.olm_group_encrypt_message_length( self._session, len(byte_plaintext)) message_buffer = ffi.new("char[]", message_length) try: ret = lib.olm_group_encrypt( self._session, ffi.from_buffer(byte_plaintext), len(byte_plaintext), message_buffer, message_length, ) self._check_error(ret) finally: # clear out copies of plaintext if byte_plaintext is not plaintext: for i in range(0, len(byte_plaintext)): byte_plaintext[i] = 0 return bytes_to_native_str(ffi.unpack(message_buffer, message_length))
def pickle(self, passphrase=""): # type: (Optional[str]) -> bytes """Store an outbound group session. Stores a group session as a base64 string. Encrypts the session using the supplied passphrase. Returns a byte object containing the base64 encoded string of the pickled session. Args: passphrase(str, optional): The passphrase to be used to encrypt the session. """ byte_passphrase = bytearray(passphrase, "utf-8") if passphrase else b"" pickle_length = lib.olm_pickle_outbound_group_session_length( self._session) pickle_buffer = ffi.new("char[]", pickle_length) try: ret = lib.olm_pickle_outbound_group_session( self._session, ffi.from_buffer(byte_passphrase), len(byte_passphrase), pickle_buffer, pickle_length) self._check_error(ret) finally: # clear out copies of the passphrase for i in range(0, len(byte_passphrase)): byte_passphrase[i] = 0 return ffi.unpack(pickle_buffer, pickle_length)
def __init__(self): if False: # pragma: no cover self._pk_decryption = self._pk_decryption # type: ffi.cdata random_length = lib.olm_pk_private_key_length() random = URANDOM(random_length) random_buffer = ffi.new("char[]", random) key_length = lib.olm_pk_key_length() key_buffer = ffi.new("char[]", key_length) ret = lib.olm_pk_key_from_private(self._pk_decryption, key_buffer, key_length, random_buffer, random_length) self._check_error(ret) self.public_key = bytes_to_native_str( ffi.unpack(key_buffer, key_length))
def __init__(self, account, identity_key, one_time_key): # type: (Account, AnyStr, AnyStr) -> None """Create a new outbound Olm session. Creates a new outbound session for sending messages to a given identity key and one-time key. Raises OlmSessionError on failure. If the keys couldn't be decoded as base64 then the error message will be "INVALID_BASE64". If there weren't enough random bytes for the session creation the error message for the exception will be NOT_ENOUGH_RANDOM. Args: account(Account): The Olm Account that will be used to create this session. identity_key(str): The identity key of the person with whom we want to start the session. one_time_key(str): A one-time key from the person with whom we want to start the session. """ if not identity_key: raise ValueError("Identity key can't be empty") if not one_time_key: raise ValueError("One-time key can't be empty") super().__init__() byte_id_key = to_bytes(identity_key) byte_one_time = to_bytes(one_time_key) session_random_length = lib.olm_create_outbound_session_random_length( self._session) random = URANDOM(session_random_length) random_buffer = ffi.new("char[]", random) identity_key_buffer = ffi.new("char[]", byte_id_key) one_time_key_buffer = ffi.new("char[]", byte_one_time) self._check_error( lib.olm_create_outbound_session(self._session, account._account, identity_key_buffer, len(byte_id_key), one_time_key_buffer, len(byte_one_time), random_buffer, session_random_length))
def __new__(cls): # type: (Type[PkDecryption]) -> PkDecryption obj = super().__new__(cls) obj._buf = ffi.new("char[]", lib.olm_pk_decryption_size()) obj._pk_decryption = lib.olm_pk_decryption(obj._buf) obj.public_key = None track_for_finalization(obj, obj._pk_decryption, _clear_pk_decryption) return obj
def __new__(cls): # type: (Type[OutboundGroupSession]) -> OutboundGroupSession obj = super().__new__(cls) obj._buf = ffi.new("char[]", lib.olm_outbound_group_session_size()) obj._session = lib.olm_outbound_group_session(obj._buf) track_for_finalization(obj, obj._session, _clear_outbound_group_session) return obj
def encrypt(self, plaintext): # type: (AnyStr) -> PkMessage """Encrypt a message. Returns the encrypted PkMessage. Args: plaintext(str): A string that will be encrypted using the PkEncryption object. """ byte_plaintext = to_bytearray(plaintext) r_length = lib.olm_pk_encrypt_random_length(self._pk_encryption) random = URANDOM(r_length) random_buffer = ffi.new("char[]", random) ciphertext_length = lib.olm_pk_ciphertext_length( self._pk_encryption, len(byte_plaintext)) ciphertext = ffi.new("char[]", ciphertext_length) mac_length = lib.olm_pk_mac_length(self._pk_encryption) mac = ffi.new("char[]", mac_length) ephemeral_key_size = lib.olm_pk_key_length() ephemeral_key = ffi.new("char[]", ephemeral_key_size) ret = lib.olm_pk_encrypt(self._pk_encryption, ffi.from_buffer(byte_plaintext), len(byte_plaintext), ciphertext, ciphertext_length, mac, mac_length, ephemeral_key, ephemeral_key_size, random_buffer, r_length) try: self._check_error(ret) finally: # pragma: no cover # clear out copies of plaintext if byte_plaintext is not plaintext: for i in range(0, len(byte_plaintext)): byte_plaintext[i] = 0 message = PkMessage( bytes_to_native_str(ffi.unpack(ephemeral_key, ephemeral_key_size)), bytes_to_native_str(ffi.unpack(mac, mac_length)), bytes_to_native_str(ffi.unpack(ciphertext, ciphertext_length))) return message