def _ed25519_verify(cls, key, message, signature): # type: (Type[_Utility], AnyStr, AnyStr, AnyStr) -> None if not cls._utility: cls._allocate() byte_key = to_bytes(key) byte_message = to_bytearray(message) byte_signature = to_bytes(signature) try: cls._check_error( lib.olm_ed25519_verify(cls._utility, byte_key, len(byte_key), ffi.from_buffer(byte_message), len(byte_message), byte_signature, len(byte_signature))) finally: # clear out copies of the message, which may be a plaintext if byte_message is not message: for i in range(0, len(byte_message)): byte_message[i] = 0
def __init__(self): # type: () -> None """Create a new Olm account. Creates a new account and its matching identity key pair. Raises OlmAccountError on failure. If there weren't enough random bytes for the account creation the error message for the exception will be NOT_ENOUGH_RANDOM. """ # This is needed to silence mypy not knowing the type of _account. # There has to be a better way for this. if False: # pragma: no cover self._account = self._account # type: ffi.cdata random_length = lib.olm_create_account_random_length(self._account) random = URANDOM(random_length) self._check_error( lib.olm_create_account(self._account, ffi.from_buffer(random), random_length))
def sign(self, message): # type: (AnyStr) -> str """Sign a message Returns the signature. Raises PkSigningError on failure. Args: message(str): the message to sign. """ bytes_message = to_bytearray(message) signature_length = lib.olm_pk_signature_length() signature_buffer = ffi.new("char[]", signature_length) ret = lib.olm_pk_sign(self._pk_signing, ffi.from_buffer(bytes_message), len(bytes_message), signature_buffer, signature_length) self._check_error(ret) return bytes_to_native_str( ffi.unpack(signature_buffer, signature_length))
def from_pickle(cls, pickle, passphrase=""): # type: (bytes, Optional[str]) -> Session """Load a previously stored Olm session. Loads a session from a pickled base64 string and returns a Session 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 session. """ if not pickle: raise ValueError("Pickle can't be empty") byte_key = bytearray(passphrase, "utf-8") if passphrase else b"" # copy because unpickle will destroy the buffer pickle_buffer = ffi.new("char[]", pickle) session = cls.__new__(cls) try: ret = lib.olm_unpickle_session(session._session, ffi.from_buffer(byte_key), len(byte_key), pickle_buffer, len(pickle)) session._check_error(ret) finally: # clear out copies of the passphrase for i in range(0, len(byte_key)): byte_key[i] = 0 return session
def __init__(self, recipient_key): # type: (AnyStr) -> None """Create a new PK encryption object. Args: recipient_key(str): a public key that will be used for encryption """ if not recipient_key: raise ValueError("Recipient key can't be empty") self._buf = ffi.new("char[]", lib.olm_pk_encryption_size()) self._pk_encryption = lib.olm_pk_encryption(self._buf) track_for_finalization(self, self._pk_encryption, _clear_pk_encryption) byte_key = to_bytearray(recipient_key) lib.olm_pk_encryption_set_recipient_key(self._pk_encryption, ffi.from_buffer(byte_key), len(byte_key)) # clear out copies of the key if byte_key is not recipient_key: # pragma: no cover for i in range(0, len(byte_key)): byte_key[i] = 0
def __init__(self, session_key): # type: (AnyStr) -> None """Create a new inbound group session. Start a new inbound group session, from a key exported from an outbound group session. Raises OlmGroupSessionError on failure. The error message of the exception will be "OLM_INVALID_BASE64" if the session key is not valid base64 and "OLM_BAD_SESSION_KEY" if the session key is invalid. """ if False: # pragma: no cover self._session = self._session # type: ffi.cdata byte_session_key = to_bytearray(session_key) try: ret = lib.olm_init_inbound_group_session( self._session, ffi.from_buffer(byte_session_key), len(byte_session_key)) finally: if byte_session_key is not session_key: for i in range(0, len(byte_session_key)): byte_session_key[i] = 0 self._check_error(ret)
def set_their_pubkey(self, key): # type: (str) -> None """Set the public key of the other user. This sets the public key of the other user, it needs to be set before bytes can be generated for the authentication string and a MAC can be calculated. Args: key (str): The other users public key. Raises OlmSasError on failure. """ byte_key = to_bytearray(key) self._check_error( lib.olm_sas_set_their_key( self._sas, ffi.from_buffer(byte_key), len(byte_key) ) ) self.other_key_set = True
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 _create_sas(self, buffer, buffer_length): self._check_error( lib.olm_create_sas(self._sas, ffi.from_buffer(buffer), buffer_length))