コード例 #1
0
ファイル: core.py プロジェクト: xmikos/pyxolotl
 def __init__(self, db, cryptostorage):
     self.store = LiteAxolotlStore(db, cryptostorage)
     if not self.store.getLocalRegistrationId():
         self.init_store()
コード例 #2
0
ファイル: core.py プロジェクト: xmikos/pyxolotl
 def __init__(self, db, cryptostorage):
     self.store = LiteAxolotlStore(db, cryptostorage)
     if not self.store.getLocalRegistrationId():
         self.init_store()
コード例 #3
0
ファイル: core.py プロジェクト: xmikos/pyxolotl
class Pyxolotl:
    """Universal Axolotl (Double Ratchet) encryption"""

    # PreKeys are not used with serverless P2P communication
    COUNT_PREKEYS = 10
    DEFAULT_DEVICE_ID = 1

    def __init__(self, db, cryptostorage):
        self.store = LiteAxolotlStore(db, cryptostorage)
        if not self.store.getLocalRegistrationId():
            self.init_store()

    def init_store(self):
        """Create new identity key pair and initialize database"""
        logger.info('Creating new identity...')
        identityKeyPair = KeyHelper.generateIdentityKeyPair()
        registrationId = KeyHelper.generateRegistrationId()
        preKeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(),
                                            self.COUNT_PREKEYS)
        signedPreKey = KeyHelper.generateSignedPreKey(
            identityKeyPair, KeyHelper.getRandomSequence(65536))

        self.store.storeLocalData(registrationId, identityKeyPair)
        self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey)

        for preKey in preKeys:
            self.store.storePreKey(preKey.getId(), preKey)

    def init_key_exchange(self, recipient):
        """Send initial key exchange message to recipient"""
        logger.info(
            'Sending initial key exchange message to {}...'.format(recipient))
        sessionBuilder = self.getSessionBuilder(recipient)
        keyExchangeMessage = sessionBuilder.processInitKeyExchangeMessage()
        return Message(recipient, keyExchangeMessage.serialize(),
                       MessageType.KEY)

    def send(self, recipient, plaintext):
        """Send encrypted message to recipient"""
        if self.store.containsSession(recipient, self.DEFAULT_DEVICE_ID):
            if not self.store.sessionStore.hasPendingKeyExchange(
                    recipient, self.DEFAULT_DEVICE_ID):
                logger.info(
                    'Sending encrypted message to {}...'.format(recipient))
                sessionCipher = self.getSessionCipher(recipient)
                whisperMessage = sessionCipher.encrypt(plaintext)
                return Message(recipient, whisperMessage.serialize(),
                               MessageType.SECURE)
            else:
                raise PendingKeyExchangeException(
                    'Session is in pending key exchange state, '
                    'wait for KeyExchangeMessage reply!')
        else:
            raise NoSessionException('Session doesn\'t exists, '
                                     'send initial KeyExchangeMessage first!')

    def end_session(self, recipient):
        """Send end session message to recipient and delete session"""
        if self.store.containsSession(recipient, self.DEFAULT_DEVICE_ID):
            endSessionMessage = None
            if not self.store.sessionStore.hasPendingKeyExchange(
                    recipient, self.DEFAULT_DEVICE_ID):
                logger.info(
                    'Sending end session message to {}...'.format(recipient))
                sessionCipher = self.getSessionCipher(recipient)
                endSessionMessage = sessionCipher.encrypt('TERMINATE')

            logger.info(
                'Deleting session for recipient {}...'.format(recipient))
            self.store.deleteSession(recipient, self.DEFAULT_DEVICE_ID)

            if endSessionMessage:
                return Message(recipient, endSessionMessage.serialize(),
                               MessageType.END_SESSION)
        else:
            raise NoSessionException('Session doesn\'t exists!')

    def receive(self, message):
        """Receive encrypted message"""
        if message.message_type == MessageType.KEY:
            decrypted = self.handle_KeyExchangeMessage(message)
        elif message.message_type == MessageType.SECURE:
            decrypted = self.handle_WhisperMessage(message)
        elif message.message_type == MessageType.PREKEY:
            decrypted = self.handle_PreKeyWhisperMessage(message)
        elif message.message_type == MessageType.END_SESSION:
            decrypted = self.handle_EndSessionMessage(message)
        else:
            raise ValueError('Received unknown type of Axolotl message'
                             'from {}!'.format(message.identity))
        return decrypted

    def handle_KeyExchangeMessage(self, message):
        """Handle received key exchange message"""
        #if self.store.containsSession(message.identity, self.DEFAULT_DEVICE_ID):
        #    raise RuntimeError('KeyExchangeMessage received, but session already exists!')

        sessionBuilder = self.getSessionBuilder(message.identity)
        keyExchangeMessage = sessionBuilder.processKeyExchangeMessage(
            KeyExchangeMessage(serialized=message.message))

        if keyExchangeMessage:
            logger.info('Received initial KeyExchangeMessage from {}, '
                        'sending response...'.format(message.identity))
            return Message(message.identity, keyExchangeMessage.serialize(),
                           MessageType.KEY)
        else:
            logger.info(
                'Received response from {} to initial KeyExchangeMessage, '
                'key exchange completed.'.format(message.identity))

    def handle_PreKeyWhisperMessage(self, message):
        """Handle received PreKey message"""
        logger.info('Received PreKeyWhisperMessage from {}, '
                    'decrypting...'.format(message.identity))
        preKeyWhisperMessage = PreKeyWhisperMessage(serialized=message.message)
        sessionCipher = self.getSessionCipher(message.identity)
        plaintext = sessionCipher.decryptPkmsg(preKeyWhisperMessage)
        return plaintext

    def handle_WhisperMessage(self, message):
        """Handle received encrypted message"""
        logger.info('Received WhisperMessage from {}, decrypting...'.format(
            message.identity))
        whisperMessage = WhisperMessage(serialized=message.message)
        sessionCipher = self.getSessionCipher(message.identity)
        plaintext = sessionCipher.decryptMsg(whisperMessage)
        return plaintext

    def handle_EndSessionMessage(self, message):
        """Handle end session message"""
        plaintext = self.handle_WhisperMessage(message)
        if plaintext == 'TERMINATE':
            logger.info('Received EndSessionMessage from {}, '
                        'deleting session!'.format(message.identity))
            self.store.deleteSession(message.identity, self.DEFAULT_DEVICE_ID)
        else:
            logger.info('Received EndSessionMessage from {}, but plaintext '
                        'isn\'t "TERMINATE"!'.format(message.identity))
        return plaintext

    def getSessionBuilder(self, identity):
        """Construct SessionBuilder for given identity"""
        return SessionBuilder(self.store, self.store, self.store, self.store,
                              identity, self.DEFAULT_DEVICE_ID)

    def getSessionCipher(self, identity):
        """Construct SessionCipher for given identity"""
        return SessionCipher(self.store, self.store, self.store, self.store,
                             identity, self.DEFAULT_DEVICE_ID)
コード例 #4
0
ファイル: core.py プロジェクト: xmikos/pyxolotl
class Pyxolotl:
    """Universal Axolotl (Double Ratchet) encryption"""

    # PreKeys are not used with serverless P2P communication
    COUNT_PREKEYS = 10
    DEFAULT_DEVICE_ID = 1

    def __init__(self, db, cryptostorage):
        self.store = LiteAxolotlStore(db, cryptostorage)
        if not self.store.getLocalRegistrationId():
            self.init_store()

    def init_store(self):
        """Create new identity key pair and initialize database"""
        logger.info('Creating new identity...')
        identityKeyPair = KeyHelper.generateIdentityKeyPair()
        registrationId = KeyHelper.generateRegistrationId()
        preKeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(), self.COUNT_PREKEYS)
        signedPreKey = KeyHelper.generateSignedPreKey(identityKeyPair,
                                                      KeyHelper.getRandomSequence(65536))

        self.store.storeLocalData(registrationId, identityKeyPair)
        self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey)

        for preKey in preKeys:
            self.store.storePreKey(preKey.getId(), preKey)

    def init_key_exchange(self, recipient):
        """Send initial key exchange message to recipient"""
        logger.info('Sending initial key exchange message to {}...'.format(recipient))
        sessionBuilder = self.getSessionBuilder(recipient)
        keyExchangeMessage = sessionBuilder.processInitKeyExchangeMessage()
        return Message(recipient, keyExchangeMessage.serialize(), MessageType.KEY)

    def send(self, recipient, plaintext):
        """Send encrypted message to recipient"""
        if self.store.containsSession(recipient, self.DEFAULT_DEVICE_ID):
            if not self.store.sessionStore.hasPendingKeyExchange(recipient, self.DEFAULT_DEVICE_ID):
                logger.info('Sending encrypted message to {}...'.format(recipient))
                sessionCipher = self.getSessionCipher(recipient)
                whisperMessage = sessionCipher.encrypt(plaintext)
                return Message(recipient, whisperMessage.serialize(), MessageType.SECURE)
            else:
                raise PendingKeyExchangeException('Session is in pending key exchange state, '
                                                  'wait for KeyExchangeMessage reply!')
        else:
            raise NoSessionException('Session doesn\'t exists, '
                                     'send initial KeyExchangeMessage first!')

    def end_session(self, recipient):
        """Send end session message to recipient and delete session"""
        if self.store.containsSession(recipient, self.DEFAULT_DEVICE_ID):
            endSessionMessage = None
            if not self.store.sessionStore.hasPendingKeyExchange(recipient, self.DEFAULT_DEVICE_ID):
                logger.info('Sending end session message to {}...'.format(recipient))
                sessionCipher = self.getSessionCipher(recipient)
                endSessionMessage = sessionCipher.encrypt('TERMINATE')

            logger.info('Deleting session for recipient {}...'.format(recipient))
            self.store.deleteSession(recipient, self.DEFAULT_DEVICE_ID)

            if endSessionMessage:
                return Message(recipient, endSessionMessage.serialize(), MessageType.END_SESSION)
        else:
            raise NoSessionException('Session doesn\'t exists!')

    def receive(self, message):
        """Receive encrypted message"""
        if message.message_type == MessageType.KEY:
            decrypted = self.handle_KeyExchangeMessage(message)
        elif message.message_type == MessageType.SECURE:
            decrypted = self.handle_WhisperMessage(message)
        elif message.message_type == MessageType.PREKEY:
            decrypted = self.handle_PreKeyWhisperMessage(message)
        elif message.message_type == MessageType.END_SESSION:
            decrypted = self.handle_EndSessionMessage(message)
        else:
            raise ValueError('Received unknown type of Axolotl message'
                             'from {}!'.format(message.identity))
        return decrypted

    def handle_KeyExchangeMessage(self, message):
        """Handle received key exchange message"""
        #if self.store.containsSession(message.identity, self.DEFAULT_DEVICE_ID):
        #    raise RuntimeError('KeyExchangeMessage received, but session already exists!')

        sessionBuilder = self.getSessionBuilder(message.identity)
        keyExchangeMessage = sessionBuilder.processKeyExchangeMessage(
            KeyExchangeMessage(serialized=message.message)
        )

        if keyExchangeMessage:
            logger.info('Received initial KeyExchangeMessage from {}, '
                        'sending response...'.format(message.identity))
            return Message(message.identity, keyExchangeMessage.serialize(), MessageType.KEY)
        else:
            logger.info('Received response from {} to initial KeyExchangeMessage, '
                        'key exchange completed.'.format(message.identity))

    def handle_PreKeyWhisperMessage(self, message):
        """Handle received PreKey message"""
        logger.info('Received PreKeyWhisperMessage from {}, '
                    'decrypting...'.format(message.identity))
        preKeyWhisperMessage = PreKeyWhisperMessage(serialized=message.message)
        sessionCipher = self.getSessionCipher(message.identity)
        plaintext = sessionCipher.decryptPkmsg(preKeyWhisperMessage)
        return plaintext

    def handle_WhisperMessage(self, message):
        """Handle received encrypted message"""
        logger.info('Received WhisperMessage from {}, decrypting...'.format(message.identity))
        whisperMessage = WhisperMessage(serialized=message.message)
        sessionCipher = self.getSessionCipher(message.identity)
        plaintext = sessionCipher.decryptMsg(whisperMessage)
        return plaintext

    def handle_EndSessionMessage(self, message):
        """Handle end session message"""
        plaintext = self.handle_WhisperMessage(message)
        if plaintext == 'TERMINATE':
            logger.info('Received EndSessionMessage from {}, '
                        'deleting session!'.format(message.identity))
            self.store.deleteSession(message.identity, self.DEFAULT_DEVICE_ID)
        else:
            logger.info('Received EndSessionMessage from {}, but plaintext '
                        'isn\'t "TERMINATE"!'.format(message.identity))
        return plaintext

    def getSessionBuilder(self, identity):
        """Construct SessionBuilder for given identity"""
        return SessionBuilder(self.store, self.store, self.store, self.store,
                              identity, self.DEFAULT_DEVICE_ID)

    def getSessionCipher(self, identity):
        """Construct SessionCipher for given identity"""
        return SessionCipher(self.store, self.store, self.store, self.store,
                             identity, self.DEFAULT_DEVICE_ID)