Exemple #1
0
    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
Exemple #2
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))
Exemple #3
0
    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))
Exemple #4
0
    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
Exemple #5
0
    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
Exemple #6
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)
Exemple #7
0
    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
Exemple #8
0
    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)
Exemple #9
0
 def _create_sas(self, buffer, buffer_length):
     self._check_error(
         lib.olm_create_sas(self._sas, ffi.from_buffer(buffer),
                            buffer_length))