python-axolotl-0.1.39/0000755000175000017500000000000013064436273015053 5ustar tarektarek00000000000000python-axolotl-0.1.39/PKG-INFO0000644000175000017500000000175413064436273016157 0ustar tarektarek00000000000000Metadata-Version: 1.1 Name: python-axolotl Version: 0.1.39 Summary: Python port of libaxolotl-android, originally written by Moxie Marlinspik Home-page: https://github.com/tgalal/python-axolotl Author: Tarek Galal Author-email: tare2.galal@gmail.com License: GPLv3 License Download-URL: https://github.com/tgalal/python-axolotl/releases Description: UNKNOWN Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) Classifier: Natural Language :: English Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Topic :: Security :: Cryptography Classifier: Topic :: Software Development :: Libraries :: Python Modules python-axolotl-0.1.39/setup.py0000644000175000017500000000252013064436211016554 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import sys import axolotl from setuptools import find_packages, setup deps = ['pycrypto', 'python-axolotl-curve25519', 'protobuf>=3.0.0.b2'] setup( name='python-axolotl', version=axolotl.__version__ , packages= find_packages(), install_requires = deps, license='GPLv3 License', author='Tarek Galal', author_email='tare2.galal@gmail.com', description="Python port of libaxolotl-android, originally written by Moxie Marlinspik", url='https://github.com/tgalal/python-axolotl', download_url='https://github.com/tgalal/python-axolotl/releases', platforms='any', classifiers=['Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 'Natural Language :: English', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Topic :: Security :: Cryptography', 'Topic :: Software Development :: Libraries :: Python Modules'] ) python-axolotl-0.1.39/python_axolotl.egg-info/0000755000175000017500000000000013064436273021630 5ustar tarektarek00000000000000python-axolotl-0.1.39/python_axolotl.egg-info/top_level.txt0000644000175000017500000000001013064436273024351 0ustar tarektarek00000000000000axolotl python-axolotl-0.1.39/python_axolotl.egg-info/PKG-INFO0000644000175000017500000000175413064436273022734 0ustar tarektarek00000000000000Metadata-Version: 1.1 Name: python-axolotl Version: 0.1.39 Summary: Python port of libaxolotl-android, originally written by Moxie Marlinspik Home-page: https://github.com/tgalal/python-axolotl Author: Tarek Galal Author-email: tare2.galal@gmail.com License: GPLv3 License Download-URL: https://github.com/tgalal/python-axolotl/releases Description: UNKNOWN Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) Classifier: Natural Language :: English Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Topic :: Security :: Cryptography Classifier: Topic :: Software Development :: Libraries :: Python Modules python-axolotl-0.1.39/python_axolotl.egg-info/dependency_links.txt0000644000175000017500000000000113064436273025676 0ustar tarektarek00000000000000 python-axolotl-0.1.39/python_axolotl.egg-info/requires.txt0000644000175000017500000000006613064436273024232 0ustar tarektarek00000000000000pycrypto python-axolotl-curve25519 protobuf>=3.0.0.b2 python-axolotl-0.1.39/python_axolotl.egg-info/SOURCES.txt0000644000175000017500000000607213064436273023521 0ustar tarektarek00000000000000setup.py axolotl/__init__.py axolotl/axolotladdress.py axolotl/duplicatemessagexception.py axolotl/identitykey.py axolotl/identitykeypair.py axolotl/invalidkeyexception.py axolotl/invalidkeyidexception.py axolotl/invalidmessageexception.py axolotl/invalidversionexception.py axolotl/legacymessageexception.py axolotl/nosessionexception.py axolotl/sessionbuilder.py axolotl/sessioncipher.py axolotl/statekeyexchangeexception.py axolotl/untrustedidentityexception.py axolotl/ecc/__init__.py axolotl/ecc/curve.py axolotl/ecc/djbec.py axolotl/ecc/ec.py axolotl/ecc/eckeypair.py axolotl/groups/__init__.py axolotl/groups/groupcipher.py axolotl/groups/groupsessionbuilder.py axolotl/groups/senderkeyname.py axolotl/groups/ratchet/__init__.py axolotl/groups/ratchet/senderchainkey.py axolotl/groups/ratchet/sendermessagekey.py axolotl/groups/state/__init__.py axolotl/groups/state/senderkeyrecord.py axolotl/groups/state/senderkeystate.py axolotl/groups/state/senderkeystore.py axolotl/kdf/__init__.py axolotl/kdf/derivedmessagesecrets.py axolotl/kdf/derivedrootsecrets.py axolotl/kdf/hkdf.py axolotl/kdf/hkdfv2.py axolotl/kdf/hkdfv3.py axolotl/kdf/messagekeys.py axolotl/protocol/__init__.py axolotl/protocol/ciphertextmessage.py axolotl/protocol/keyexchangemessage.py axolotl/protocol/prekeywhispermessage.py axolotl/protocol/senderkeydistributionmessage.py axolotl/protocol/senderkeymessage.py axolotl/protocol/whispermessage.py axolotl/protocol/whisperprotos_pb2.py axolotl/ratchet/__init__.py axolotl/ratchet/aliceaxolotlparameters.py axolotl/ratchet/bobaxolotlparamaters.py axolotl/ratchet/chainkey.py axolotl/ratchet/ratchetingsession.py axolotl/ratchet/rootkey.py axolotl/ratchet/symmetricaxolotlparameters.py axolotl/state/__init__.py axolotl/state/axolotlstore.py axolotl/state/identitykeystore.py axolotl/state/prekeybundle.py axolotl/state/prekeyrecord.py axolotl/state/prekeystore.py axolotl/state/sessionrecord.py axolotl/state/sessionstate.py axolotl/state/sessionstore.py axolotl/state/signedprekeyrecord.py axolotl/state/signedprekeystore.py axolotl/state/storageprotos_pb2.py axolotl/tests/__init__.py axolotl/tests/inmemoryaxolotlstore.py axolotl/tests/inmemoryidentitykeystore.py axolotl/tests/inmemoryprekeystore.py axolotl/tests/inmemorysessionstore.py axolotl/tests/inmemorysignedprekeystore.py axolotl/tests/test_sessionbuilder.py axolotl/tests/test_sessioncipher.py axolotl/tests/test_sigs.py axolotl/tests/groups/__init__.py axolotl/tests/groups/inmemorysenderkeystore.py axolotl/tests/groups/test_groupcipher.py axolotl/tests/kdf/__init__.py axolotl/tests/kdf/test_hkdf.py axolotl/tests/ratchet/__init__.py axolotl/tests/ratchet/test_chainkey.py axolotl/tests/ratchet/test_ratchetingsession.py axolotl/tests/ratchet/test_rootkey.py axolotl/tests/util/__init__.py axolotl/tests/util/test_byteutil.py axolotl/util/__init__.py axolotl/util/byteutil.py axolotl/util/hexutil.py axolotl/util/keyhelper.py axolotl/util/medium.py python_axolotl.egg-info/PKG-INFO python_axolotl.egg-info/SOURCES.txt python_axolotl.egg-info/dependency_links.txt python_axolotl.egg-info/requires.txt python_axolotl.egg-info/top_level.txtpython-axolotl-0.1.39/axolotl/0000755000175000017500000000000013064436273016535 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/util/0000755000175000017500000000000013064436273017512 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/util/medium.py0000644000175000017500000000010113064436211021324 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class Medium: MAX_VALUE = 0xFFFFFF python-axolotl-0.1.39/axolotl/util/__init__.py0000644000175000017500000000003013064436211021604 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- python-axolotl-0.1.39/axolotl/util/byteutil.py0000644000175000017500000000343313064436211021720 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class ByteUtil: @staticmethod def combine(*args): baos = bytearray() for a in args: if type(a) in (list, bytearray, str, bytes): baos.extend(a) else: baos.append(a) return baos # @staticmethod # def xsplit(inp, firstLength, secondLength, thirdLength = None): # parts = [] # parts.append(inp[:firstLength]) # parts.append(inp[len(parts[0]): secondLength + 1]) # if thirdLength: # parts.append(inp[len(parts[1]): thirdLength + 1]) # return parts @staticmethod def split(inp, firstLength, secondLength, thirdLength=None): parts = [] parts.append(inp[:firstLength]) parts.append(inp[firstLength:firstLength + secondLength]) if thirdLength is not None: parts.append(inp[firstLength + secondLength: firstLength + secondLength + thirdLength]) return parts @staticmethod def trim(inp, length): return inp[:length] @staticmethod def intsToByteHighAndLow(highValue, lowValue): highValue = ord(highValue) if type(highValue) is str else highValue lowValue = ord(lowValue) if type(lowValue) is str else lowValue return ((highValue << 4 | lowValue) & 0xFF) % 256 @staticmethod def highBitsToInt(value): bit = ord(value) if type(value) is str else value return (bit & 0xFF) >> 4 @staticmethod def lowBitsToInt(value): return value & 0xF @staticmethod def intToByteArray(_bytes, offset, value): _bytes[offset + 3] = value % 256 _bytes[offset + 2] = (value >> 8) % 256 _bytes[offset + 1] = (value >> 16) % 256 _bytes[offset] = (value >> 24) % 256 return 4 python-axolotl-0.1.39/axolotl/util/hexutil.py0000644000175000017500000000060513064436211021537 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import codecs import sys decode_hex = codecs.getdecoder("hex_codec") class HexUtil: @staticmethod def decodeHex(hexString): hexString = hexString.encode() if type(hexString) is str else hexString result = decode_hex(hexString)[0] if sys.version_info >= (3, 0): result = result.decode('latin-1') return result python-axolotl-0.1.39/axolotl/util/keyhelper.py0000644000175000017500000000600613064436211022046 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import os import time import binascii import math from ..ecc.curve import Curve from ..identitykey import IdentityKey from ..identitykeypair import IdentityKeyPair from ..state.prekeyrecord import PreKeyRecord from ..state.signedprekeyrecord import SignedPreKeyRecord from .medium import Medium class KeyHelper: def __init__(self): pass @staticmethod def generateIdentityKeyPair(): """ Generate an identity key pair. Clients should only do this once, at install time. @return the generated IdentityKeyPair. """ keyPair = Curve.generateKeyPair() publicKey = IdentityKey(keyPair.getPublicKey()) serialized = '0a21056e8936e8367f768a7bba008ade7cf58407bdc7a6aae293e2c' \ 'b7c06668dcd7d5e12205011524f0c15467100dd603e0d6020f4d293' \ 'edfbcd82129b14a88791ac81365c' serialized = binascii.unhexlify(serialized.encode()) identityKeyPair = IdentityKeyPair(publicKey, keyPair.getPrivateKey()) return identityKeyPair # return IdentityKeyPair(serialized=serialized) @staticmethod def generateRegistrationId(): """ Generate a registration ID. Clients should only do this once, at install time. """ regId = KeyHelper.getRandomSequence() return regId @staticmethod def getRandomSequence(max=4294967296): size = int(math.log(max) / math.log(2)) / 8 rand = os.urandom(int(size)) randh = binascii.hexlify(rand) return int(randh, 16) @staticmethod def generatePreKeys(start, count): """ Generate a list of PreKeys. Clients should do this at install time, and subsequently any time the list of PreKeys stored on the server runs low. PreKey IDs are shorts, so they will eventually be repeated. Clients should store PreKeys in a circular buffer, so that they are repeated as infrequently as possible. @param start The starting PreKey ID, inclusive. @param count The number of PreKeys to generate. @return the list of generated PreKeyRecords. """ results = [] start -= 1 for i in range(0, count): preKeyId = ((start + i) % (Medium.MAX_VALUE - 1)) + 1 results.append(PreKeyRecord(preKeyId, Curve.generateKeyPair())) return results @staticmethod def generateSignedPreKey(identityKeyPair, signedPreKeyId): keyPair = Curve.generateKeyPair() signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize()) spk = SignedPreKeyRecord(signedPreKeyId, int(round(time.time() * 1000)), keyPair, signature) return spk @staticmethod def generateSenderSigningKey(): return Curve.generateKeyPair() @staticmethod def generateSenderKey(): return os.urandom(32) @staticmethod def generateSenderKeyId(): return KeyHelper.getRandomSequence(2147483647) python-axolotl-0.1.39/axolotl/duplicatemessagexception.py0000644000175000017500000000011713064436211024167 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class DuplicateMessageException(Exception): pass python-axolotl-0.1.39/axolotl/untrustedidentityexception.py0000644000175000017500000000044113064436211024624 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class UntrustedIdentityException(Exception): def __init__(self, name, identityKey): self.name = name self.identityKey = identityKey def getName(self): return self.name def getIdentityKey(self): return self.identityKey python-axolotl-0.1.39/axolotl/identitykeypair.py0000644000175000017500000000177513064436211022327 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from .state.storageprotos_pb2 import IdentityKeyPairStructure from .identitykey import IdentityKey from .ecc.curve import Curve class IdentityKeyPair: def __init__(self, identityKeyPublicKey=None, ecPrivateKey=None, serialized=None): if serialized: structure = IdentityKeyPairStructure() structure.ParseFromString(serialized) self.publicKey = IdentityKey(bytearray(structure.publicKey), offset=0) self.privateKey = Curve.decodePrivatePoint(bytearray(structure.privateKey)) else: self.publicKey = identityKeyPublicKey self.privateKey = ecPrivateKey def getPublicKey(self): return self.publicKey def getPrivateKey(self): return self.privateKey def serialize(self): structure = IdentityKeyPairStructure() structure.publicKey = self.publicKey.serialize() structure.privateKey = self.privateKey.serialize() return structure.SerializeToString() python-axolotl-0.1.39/axolotl/identitykey.py0000644000175000017500000000117413064436211021444 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from .ecc.curve import Curve class IdentityKey: def __init__(self, ecPubKeyOrBytes, offset=None): if offset is None: self.publicKey = ecPubKeyOrBytes else: self.publicKey = Curve.decodePoint(bytearray(ecPubKeyOrBytes), offset) def getPublicKey(self): return self.publicKey def serialize(self): return self.publicKey.serialize() def get_fingerprint(self): raise Exception("IMPL ME") def __eq__(self, other): return self.publicKey == other.getPublicKey() def hashCode(self): raise Exception("IMPL ME") python-axolotl-0.1.39/axolotl/__init__.py0000644000175000017500000000023713064436211020640 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- __version__ = '0.1.39' __author__ = 'Tarek Galal' __email__ = 'tare2.galal@gmail.com' __license__ = 'GPLv3' __status__ = 'Production' python-axolotl-0.1.39/axolotl/invalidkeyidexception.py0000644000175000017500000000011313064436211023465 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class InvalidKeyIdException(Exception): pass python-axolotl-0.1.39/axolotl/ecc/0000755000175000017500000000000013064436273017267 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/ecc/__init__.py0000644000175000017500000000000013064436211021356 0ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/ecc/ec.py0000644000175000017500000000065213064436211020223 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import abc class ECPublicKey(object): __metaclass__ = abc.ABCMeta KEY_SIZE = 33 @abc.abstractmethod def serialize(self): pass @abc.abstractmethod def getType(self): pass class ECPrivateKey(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def serialize(self): pass @abc.abstractmethod def getType(self): pass python-axolotl-0.1.39/axolotl/ecc/curve.py0000644000175000017500000000572013064436211020761 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import os from .eckeypair import ECKeyPair from ..invalidkeyexception import InvalidKeyException import axolotl_curve25519 as _curve class Curve: DJB_TYPE = 5 # always DJB curve25519 keys @staticmethod def generatePrivateKey(): rand = os.urandom(32) return _curve.generatePrivateKey(rand) @staticmethod def generatePublicKey(privateKey): return _curve.generatePublicKey(privateKey) @staticmethod def generateKeyPair(): from .djbec import DjbECPublicKey, DjbECPrivateKey privateKey = Curve.generatePrivateKey() publicKey = Curve.generatePublicKey(privateKey) return ECKeyPair(DjbECPublicKey(publicKey), DjbECPrivateKey(privateKey)) @staticmethod def decodePoint(_bytes, offset=0): type = _bytes[0] # byte appears to be automatically converted to an integer?? if type == Curve.DJB_TYPE: from .djbec import DjbECPublicKey type = _bytes[offset] & 0xFF if type != Curve.DJB_TYPE: raise InvalidKeyException("Unknown key type: %s " % type) keyBytes = _bytes[offset+1:][:32] return DjbECPublicKey(bytes(keyBytes)) else: raise InvalidKeyException("Unknown key type: %s" % type) @staticmethod def decodePrivatePoint(_bytes): from .djbec import DjbECPrivateKey return DjbECPrivateKey(bytes(_bytes)) @staticmethod def calculateAgreement(publicKey, privateKey): """ :type publicKey: ECPublicKey :type privateKey: ECPrivateKey """ if publicKey.getType() != privateKey.getType(): raise InvalidKeyException("Public and private keys must be of the same type!") if publicKey.getType() == Curve.DJB_TYPE: return _curve.calculateAgreement(privateKey.getPrivateKey(), publicKey.getPublicKey()) else: raise InvalidKeyException("Unknown type: %s" % publicKey.getType()) @staticmethod def verifySignature(ecPublicSigningKey, message, signature): """ :type ecPublicSigningKey: ECPublicKey :type message: bytearray :type signature: bytearray """ if ecPublicSigningKey.getType() == Curve.DJB_TYPE: result = _curve.verifySignature(ecPublicSigningKey.getPublicKey(), message, signature) return result == 0 else: raise InvalidKeyException("Unknown type: %s" % ecPublicSigningKey.getType()) @staticmethod def calculateSignature(privateSigningKey, message): """ :type privateSigningKey: ECPrivateKey :type message: bytearray """ if privateSigningKey.getType() == Curve.DJB_TYPE: rand = os.urandom(64) res = _curve.calculateSignature(rand, privateSigningKey.getPrivateKey(), message) return res else: raise InvalidKeyException("Unknown type: %s" % privateSigningKey.getType()) python-axolotl-0.1.39/axolotl/ecc/djbec.py0000644000175000017500000000274513064436211020710 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import binascii from .ec import ECPublicKey, ECPrivateKey from ..util.byteutil import ByteUtil class DjbECPublicKey(ECPublicKey): def __init__(self, publicKey): self.publicKey = publicKey def serialize(self): from .curve import Curve combined = ByteUtil.combine([Curve.DJB_TYPE], self.publicKey) return bytes(combined) def getType(self): from .curve import Curve return Curve.DJB_TYPE def getPublicKey(self): return self.publicKey def __eq__(self, other): return self.publicKey == other.getPublicKey() def __lt__(self, other): myVal = int(binascii.hexlify(self.publicKey), 16) otherVal = int(binascii.hexlify(other.getPublicKey()), 16) return myVal < otherVal def __cmp__(self, other): myVal = int(binascii.hexlify(self.publicKey), 16) otherVal = int(binascii.hexlify(other.getPublicKey()), 16) if myVal < otherVal: return -1 elif myVal == otherVal: return 0 else: return 1 class DjbECPrivateKey(ECPrivateKey): def __init__(self, privateKey): self.privateKey = privateKey def getType(self): from .curve import Curve return Curve.DJB_TYPE def getPrivateKey(self): return self.privateKey def serialize(self): return self.privateKey def __eq__(self, other): return self.privateKey == other.getPrivateKey() python-axolotl-0.1.39/axolotl/ecc/eckeypair.py0000644000175000017500000000060013064436211021601 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class ECKeyPair(): def __init__(self, publicKey, privateKey): """ :type publicKey: ECPublicKey :type privateKey: ECPrivateKey """ self.publicKey = publicKey self.privateKey = privateKey def getPrivateKey(self): return self.privateKey def getPublicKey(self): return self.publicKey python-axolotl-0.1.39/axolotl/nosessionexception.py0000644000175000017500000000011013064436211023026 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class NoSessionException(Exception): pass python-axolotl-0.1.39/axolotl/ratchet/0000755000175000017500000000000013064436273020167 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/ratchet/__init__.py0000644000175000017500000000003013064436211022261 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- python-axolotl-0.1.39/axolotl/ratchet/aliceaxolotlparameters.py0000644000175000017500000000541213064436211025277 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class AliceAxolotlParameters: def __init__(self, ourIdentityKey, ourBaseKey, theirIdentityKey, theirSignedPreKey, theirRatchetKey, theirOneTimePreKey): """ :type ourBaseKey: ECKeyPair :type theirSignedPreKey: ECKeyPair :type ourIdentityKey: IdentityKeyPair :type theirOneTimePreKey: ECPublicKey :type theirRatchetKey: ECKeyPair :type theirIdentityKey: IdentityKey """ self.ourBaseKey = ourBaseKey self.ourIdentityKey = ourIdentityKey self.theirSignedPreKey = theirSignedPreKey self.theirRatchetKey = theirRatchetKey self.theirIdentityKey = theirIdentityKey self.theirOneTimePreKey = theirOneTimePreKey if ourBaseKey is None or ourIdentityKey is None or theirSignedPreKey is None \ or theirRatchetKey is None or theirIdentityKey is None or theirSignedPreKey is None: raise ValueError("Null value!") def getOurIdentityKey(self): return self.ourIdentityKey def getOurBaseKey(self): return self.ourBaseKey def getTheirIdentityKey(self): return self.theirIdentityKey def getTheirSignedPreKey(self): return self.theirSignedPreKey def getTheirOneTimePreKey(self): return self.theirOneTimePreKey def getTheirRatchetKey(self): return self.theirRatchetKey @staticmethod def newBuilder(): return AliceAxolotlParameters.Builder() class Builder: def __init__(self): self.ourIdentityKey = None self.ourBaseKey = None self.theirIdentityKey = None self.theirSignedPreKey = None self.theirRatchetKey = None self.theirOneTimePreKey = None def setOurIdentityKey(self, ourIdentityKey): self.ourIdentityKey = ourIdentityKey return self def setOurBaseKey(self, ourBaseKey): self.ourBaseKey = ourBaseKey return self def setTheirRatchetKey(self, theirRatchetKey): self.theirRatchetKey = theirRatchetKey return self def setTheirIdentityKey(self, theirIdentityKey): self.theirIdentityKey = theirIdentityKey return self def setTheirSignedPreKey(self, theirSignedPreKey): self.theirSignedPreKey = theirSignedPreKey return self def setTheirOneTimePreKey(self, theirOneTimePreKey): self.theirOneTimePreKey = theirOneTimePreKey return self def create(self): return AliceAxolotlParameters(self.ourIdentityKey, self.ourBaseKey, self.theirIdentityKey, self.theirSignedPreKey, self.theirRatchetKey, self.theirOneTimePreKey) python-axolotl-0.1.39/axolotl/ratchet/ratchetingsession.py0000644000175000017500000001446413064436211024276 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ..ecc.curve import Curve from .bobaxolotlparamaters import BobAxolotlParameters from .aliceaxolotlparameters import AliceAxolotlParameters from ..kdf.hkdf import HKDF from ..util.byteutil import ByteUtil from .rootkey import RootKey from .chainkey import ChainKey class RatchetingSession: @staticmethod def initializeSession(sessionState, sessionVersion, parameters): """ :type sessionState: SessionState :type sessionVersion: int :type parameters: SymmetricAxolotlParameters """ if RatchetingSession.isAlice(parameters.getOurBaseKey().getPublicKey(), parameters.getTheirBaseKey()): aliceParameters = AliceAxolotlParameters.newBuilder() aliceParameters.setOurBaseKey(parameters.getOurBaseKey()) \ .setOurIdentityKey(parameters.getOurIdentityKey()) \ .setTheirRatchetKey(parameters.getTheirRatchetKey()) \ .setTheirIdentityKey(parameters.getTheirIdentityKey()) \ .setTheirSignedPreKey(parameters.getTheirBaseKey()) \ .setTheirOneTimePreKey(None) RatchetingSession.initializeSessionAsAlice(sessionState, sessionVersion, aliceParameters.create()) else: bobParameters = BobAxolotlParameters.newBuilder() bobParameters.setOurIdentityKey(parameters.getOurIdentityKey()) \ .setOurRatchetKey(parameters.getOurRatchetKey()) \ .setOurSignedPreKey(parameters.getOurBaseKey()) \ .setOurOneTimePreKey(None) \ .setTheirBaseKey(parameters.getTheirBaseKey()) \ .setTheirIdentityKey(parameters.getTheirIdentityKey()) RatchetingSession.initializeSessionAsBob(sessionState, sessionVersion, bobParameters.create()) @staticmethod def initializeSessionAsAlice(sessionState, sessionVersion, parameters): """ :type sessionState: SessionState :type sessionVersion: int :type parameters: AliceAxolotlParameters """ sessionState.setSessionVersion(sessionVersion) sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey()) sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey()) sendingRatchetKey = Curve.generateKeyPair() secrets = bytearray() if sessionVersion >= 3: secrets.extend(RatchetingSession.getDiscontinuityBytes()) secrets.extend(Curve.calculateAgreement(parameters.getTheirSignedPreKey(), parameters.getOurIdentityKey().getPrivateKey())) secrets.extend(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(), parameters.getOurBaseKey().getPrivateKey())) secrets.extend(Curve.calculateAgreement(parameters.getTheirSignedPreKey(), parameters.getOurBaseKey().getPrivateKey())) if sessionVersion >= 3 and parameters.getTheirOneTimePreKey() is not None: secrets.extend(Curve.calculateAgreement(parameters.getTheirOneTimePreKey(), parameters.getOurBaseKey().getPrivateKey())) derivedKeys = RatchetingSession.calculateDerivedKeys(sessionVersion, secrets) sendingChain = derivedKeys.getRootKey().createChain(parameters.getTheirRatchetKey(), sendingRatchetKey) sessionState.addReceiverChain(parameters.getTheirRatchetKey(), derivedKeys.getChainKey()) sessionState.setSenderChain(sendingRatchetKey, sendingChain[1]) sessionState.setRootKey(sendingChain[0]) @staticmethod def initializeSessionAsBob(sessionState, sessionVersion, parameters): """ :type sessionState: SessionState :type sessionVersion: int :type parameters: BobAxolotlParameters """ sessionState.setSessionVersion(sessionVersion) sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey()) sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey()) secrets = bytearray() if sessionVersion >= 3: secrets.extend(RatchetingSession.getDiscontinuityBytes()) secrets.extend(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(), parameters.getOurSignedPreKey().getPrivateKey())) secrets.extend(Curve.calculateAgreement(parameters.getTheirBaseKey(), parameters.getOurIdentityKey().getPrivateKey())) secrets.extend(Curve.calculateAgreement(parameters.getTheirBaseKey(), parameters.getOurSignedPreKey().getPrivateKey())) if sessionVersion >= 3 and parameters.getOurOneTimePreKey() is not None: secrets.extend(Curve.calculateAgreement(parameters.getTheirBaseKey(), parameters.getOurOneTimePreKey().getPrivateKey())) derivedKeys = RatchetingSession.calculateDerivedKeys(sessionVersion, secrets) sessionState.setSenderChain(parameters.getOurRatchetKey(), derivedKeys.getChainKey()) sessionState.setRootKey(derivedKeys.getRootKey()) @staticmethod def getDiscontinuityBytes(): return bytearray([0xFF] * 32) @staticmethod def calculateDerivedKeys(sessionVersion, masterSecret): kdf = HKDF.createFor(sessionVersion) derivedSecretBytes = kdf.deriveSecrets(masterSecret, bytearray("WhisperText".encode()), 64) derivedSecrets = ByteUtil.split(derivedSecretBytes, 32, 32) return RatchetingSession.DerivedKeys(RootKey(kdf, derivedSecrets[0]), ChainKey(kdf, derivedSecrets[1], 0)) @staticmethod def isAlice(ourKey, theirKey): """ :type ourKey: ECPublicKey :type theirKey: ECPublicKey """ return ourKey < theirKey class DerivedKeys: def __init__(self, rootKey, chainKey): """ :type rootKey: RootKey :type chainKey: ChainKey """ self.rootKey = rootKey self.chainKey = chainKey def getRootKey(self): return self.rootKey def getChainKey(self): return self.chainKey python-axolotl-0.1.39/axolotl/ratchet/chainkey.py0000644000175000017500000000246013064436211022326 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import hmac import hashlib from ..kdf.derivedmessagesecrets import DerivedMessageSecrets from ..kdf.messagekeys import MessageKeys class ChainKey: MESSAGE_KEY_SEED = bytearray([0x01]) CHAIN_KEY_SEED = bytearray([0x02]) def __init__(self, kdf, key, index): self.kdf = kdf self.key = key self.index = index def getKey(self): return self.key def getIndex(self): return self.index def getNextChainKey(self): nextKey = self.getBaseMaterial(self.__class__.CHAIN_KEY_SEED) return ChainKey(self.kdf, nextKey, self.index + 1) def getMessageKeys(self): inputKeyMaterial = self.getBaseMaterial(self.__class__.MESSAGE_KEY_SEED) keyMaterialBytes = self.kdf.deriveSecrets(inputKeyMaterial, bytearray("WhisperMessageKeys".encode()), DerivedMessageSecrets.SIZE) keyMaterial = DerivedMessageSecrets(keyMaterialBytes) return MessageKeys(keyMaterial.getCipherKey(), keyMaterial.getMacKey(), keyMaterial.getIv(), self.index) def getBaseMaterial(self, seedBytes): mac = hmac.new(bytes(self.key), digestmod=hashlib.sha256) mac.update(bytes(seedBytes)) return mac.digest() python-axolotl-0.1.39/axolotl/ratchet/symmetricaxolotlparameters.py0000644000175000017500000000523113064436211026235 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class SymmetricAxolotlParameters: def __init__(self, ourBaseKey, ourRatchetKey, ourIdentityKey, theirBaseKey, theirRatchetKey, theirIdentityKey): """ :type ourBaseKey: ECKeyPair :type ourRatchetKey: ECKeyPair :type ourIdentityKey: IdentityKeyPair :type theirBaseKey: ECPublicKey :type theirRatchetKey: ECKeyPair :type theirIdentityKey: IdentityKey """ self.ourBaseKey = ourBaseKey self.ourIdentityKey = ourIdentityKey self.ourRatchetKey = ourRatchetKey self.theirRatchetKey = theirRatchetKey self.theirIdentityKey = theirIdentityKey self.theirBaseKey = theirBaseKey if ourBaseKey is None or ourIdentityKey is None or ourRatchetKey is None \ or theirRatchetKey is None or theirIdentityKey is None or theirBaseKey is None: raise ValueError("Null value!") def getOurBaseKey(self): return self.ourBaseKey def getOurIdentityKey(self): return self.ourIdentityKey def getTheirRatchetKey(self): return self.theirRatchetKey def getTheirIdentityKey(self): return self.theirIdentityKey def getTheirBaseKey(self): return self.theirBaseKey def getOurRatchetKey(self): return self.ourRatchetKey @staticmethod def newBuilder(): return SymmetricAxolotlParameters.Builder() class Builder: def __init__(self): self.ourIdentityKey = None self.ourBaseKey = None self.ourRatchetKey = None self.theirRatchetKey = None self.theirIdentityKey = None self.theirBaseKey = None def setOurIdentityKey(self, ourIdentityKey): self.ourIdentityKey = ourIdentityKey return self def setOurBaseKey(self, ourBaseKey): self.ourBaseKey = ourBaseKey return self def setOurRatchetKey(self, ourRatchetKey): self.ourRatchetKey = ourRatchetKey return self def setTheirRatchetKey(self, theirRatchetKey): self.theirRatchetKey = theirRatchetKey return self def setTheirIdentityKey(self, theirIdentityKey): self.theirIdentityKey = theirIdentityKey return self def setTheirBaseKey(self, theirBaseKey): self.theirBaseKey = theirBaseKey return self def create(self): return SymmetricAxolotlParameters(self.ourBaseKey, self.ourRatchetKey, self.ourIdentityKey, self.theirBaseKey, self.theirRatchetKey, self.theirIdentityKey) python-axolotl-0.1.39/axolotl/ratchet/bobaxolotlparamaters.py0000644000175000017500000000526313064436211024764 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class BobAxolotlParameters: def __init__(self, ourIdentityKey, ourSignedPreKey, ourRatchetKey, ourOneTimePreKey, theirIdentityKey, theirBaseKey): """ :type ourIdentityKey: IdentityKeyPair :type ourSignedPreKey: ECKeyPair :type ourRatchetKey: ECKeyPair :type ourOneTimePreKey: ECKeyPair :type theirIdentityKey: IdentityKey :type theirBaseKey: ECPublicKey """ self.ourIdentityKey = ourIdentityKey self.ourSignedPreKey = ourSignedPreKey self.ourRatchetKey = ourRatchetKey self.ourOneTimePreKey = ourOneTimePreKey self.theirIdentityKey = theirIdentityKey self.theirBaseKey = theirBaseKey if ourIdentityKey is None or ourSignedPreKey is None or ourRatchetKey is None \ or theirIdentityKey is None or theirBaseKey is None: raise ValueError("Null value!") def getOurIdentityKey(self): return self.ourIdentityKey def getOurSignedPreKey(self): return self.ourSignedPreKey def getOurOneTimePreKey(self): return self.ourOneTimePreKey def getTheirIdentityKey(self): return self.theirIdentityKey def getTheirBaseKey(self): return self.theirBaseKey def getOurRatchetKey(self): return self.ourRatchetKey @staticmethod def newBuilder(): return BobAxolotlParameters.Builder() class Builder: def __init__(self): self.ourIdentityKey = None self.ourSignedPreKey = None self.ourOneTimePreKey = None self.ourRatchetKey = None self.theirIdentityKey = None self.theirBaseKey = None def setOurIdentityKey(self, ourIdentityKey): self.ourIdentityKey = ourIdentityKey return self def setOurSignedPreKey(self, ourSignedPreKey): self.ourSignedPreKey = ourSignedPreKey return self def setOurOneTimePreKey(self, ourOneTimePreKey): self.ourOneTimePreKey = ourOneTimePreKey return self def setOurRatchetKey(self, ourRatchetKey): self.ourRatchetKey = ourRatchetKey return self def setTheirIdentityKey(self, theirIdentityKey): self.theirIdentityKey = theirIdentityKey return self def setTheirBaseKey(self, theirBaseKey): self.theirBaseKey = theirBaseKey return self def create(self): return BobAxolotlParameters(self.ourIdentityKey, self.ourSignedPreKey, self.ourRatchetKey, self.ourOneTimePreKey, self.theirIdentityKey, self.theirBaseKey) python-axolotl-0.1.39/axolotl/ratchet/rootkey.py0000644000175000017500000000201613064436211022224 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ..ecc.curve import Curve from ..kdf.derivedrootsecrets import DerivedRootSecrets from .chainkey import ChainKey class RootKey: def __init__(self, kdf, key): self.kdf = kdf self.key = key def getKeyBytes(self): return self.key def createChain(self, ECPublicKey_theirRatchetKey, ECKeyPair_ourRatchetKey): sharedSecret = Curve.calculateAgreement(ECPublicKey_theirRatchetKey, ECKeyPair_ourRatchetKey.getPrivateKey()) derivedSecretBytes = self.kdf.deriveSecrets(sharedSecret, bytearray("WhisperRatchet".encode()), DerivedRootSecrets.SIZE, salt=self.key) derivedSecrets = DerivedRootSecrets(derivedSecretBytes) newRootKey = RootKey(self.kdf, derivedSecrets.getRootKey()) newChainKey = ChainKey(self.kdf, derivedSecrets.getChainKey(), 0) return (newRootKey, newChainKey) python-axolotl-0.1.39/axolotl/invalidkeyexception.py0000644000175000017500000000011113064436211023146 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class InvalidKeyException(Exception): pass python-axolotl-0.1.39/axolotl/sessioncipher.py0000644000175000017500000002717513064436211021771 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import sys import Crypto.Cipher.AES as AES from Crypto.Util import Counter from .ecc.curve import Curve from .sessionbuilder import SessionBuilder from .util.byteutil import ByteUtil from .state.sessionstate import SessionState from .protocol.whispermessage import WhisperMessage from .protocol.prekeywhispermessage import PreKeyWhisperMessage from .nosessionexception import NoSessionException from .invalidmessageexception import InvalidMessageException from .duplicatemessagexception import DuplicateMessageException if sys.version_info >= (3, 0): unicode = str import logging logger = logging.getLogger(__name__) class SessionCipher: def __init__(self, sessionStore, preKeyStore, signedPreKeyStore, identityKeyStore, recepientId, deviceId): self.sessionStore = sessionStore self.preKeyStore = preKeyStore self.recipientId = recepientId self.deviceId = deviceId self.sessionBuilder = SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore, identityKeyStore, recepientId, deviceId) def encrypt(self, paddedMessage): """ :type paddedMessage: str """ # TODO: make this less ugly and python 2 and 3 compatible # paddedMessage = bytearray(paddedMessage.encode() if (sys.version_info >= (3, 0) and not type(paddedMessage) in (bytes, bytearray)) or type(paddedMessage) is unicode else paddedMessage) if (sys.version_info >= (3, 0) and not type(paddedMessage) in (bytes, bytearray)) or type(paddedMessage) is unicode: paddedMessage = bytearray(paddedMessage.encode()) else: paddedMessage = bytearray(paddedMessage) sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId) sessionState = sessionRecord.getSessionState() chainKey = sessionState.getSenderChainKey() messageKeys = chainKey.getMessageKeys() senderEphemeral = sessionState.getSenderRatchetKey() previousCounter = sessionState.getPreviousCounter() sessionVersion = sessionState.getSessionVersion() ciphertextBody = self.getCiphertext(sessionVersion, messageKeys, paddedMessage) ciphertextMessage = WhisperMessage(sessionVersion, messageKeys.getMacKey(), senderEphemeral, chainKey.getIndex(), previousCounter, ciphertextBody, sessionState.getLocalIdentityKey(), sessionState.getRemoteIdentityKey()) if sessionState.hasUnacknowledgedPreKeyMessage(): items = sessionState.getUnacknowledgedPreKeyMessageItems() localRegistrationid = sessionState.getLocalRegistrationId() ciphertextMessage = PreKeyWhisperMessage(sessionVersion, localRegistrationid, items.getPreKeyId(), items.getSignedPreKeyId(), items.getBaseKey(), sessionState.getLocalIdentityKey(), ciphertextMessage) sessionState.setSenderChainKey(chainKey.getNextChainKey()) self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord) return ciphertextMessage def decryptMsg(self, ciphertext, textMsg=True): """ :type ciphertext: WhisperMessage :type textMsg: Bool set this to False if you are decrypting bytes instead of string """ if not self.sessionStore.containsSession(self.recipientId, self.deviceId): raise NoSessionException("No session for: %s, %s" % (self.recipientId, self.deviceId)) sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId) plaintext = self.decryptWithSessionRecord(sessionRecord, ciphertext) self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord) return plaintext def decryptPkmsg(self, ciphertext, textMsg=True): """ :type ciphertext: PreKeyWhisperMessage """ sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId) unsignedPreKeyId = self.sessionBuilder.process(sessionRecord, ciphertext) plaintext = self.decryptWithSessionRecord(sessionRecord, ciphertext.getWhisperMessage()) # callback.handlePlaintext(plaintext) self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord) if unsignedPreKeyId is not None: self.preKeyStore.removePreKey(unsignedPreKeyId) return plaintext def decryptWithSessionRecord(self, sessionRecord, cipherText): """ :type sessionRecord: SessionRecord :type cipherText: WhisperMessage """ previousStates = sessionRecord.getPreviousSessionStates() exceptions = [] try: sessionState = SessionState(sessionRecord.getSessionState()) plaintext = self.decryptWithSessionState(sessionState, cipherText) sessionRecord.setState(sessionState) return plaintext except InvalidMessageException as e: exceptions.append(e) for i in range(0, len(previousStates)): previousState = previousStates[i] try: promotedState = SessionState(previousState) plaintext = self.decryptWithSessionState(promotedState, cipherText) previousStates.pop(i) sessionRecord.promoteState(promotedState) return plaintext except InvalidMessageException as e: exceptions.append(e) raise InvalidMessageException("No valid sessions", exceptions) def decryptWithSessionState(self, sessionState, ciphertextMessage): if not sessionState.hasSenderChain(): raise InvalidMessageException("Uninitialized session!") if ciphertextMessage.getMessageVersion() != sessionState.getSessionVersion(): raise InvalidMessageException("Message version %s, but session version %s" % (ciphertextMessage.getMessageVersion, sessionState.getSessionVersion())) messageVersion = ciphertextMessage.getMessageVersion() theirEphemeral = ciphertextMessage.getSenderRatchetKey() counter = ciphertextMessage.getCounter() chainKey = self.getOrCreateChainKey(sessionState, theirEphemeral) messageKeys = self.getOrCreateMessageKeys(sessionState, theirEphemeral, chainKey, counter) ciphertextMessage.verifyMac(messageVersion, sessionState.getRemoteIdentityKey(), sessionState.getLocalIdentityKey(), messageKeys.getMacKey()) plaintext = self.getPlaintext(messageVersion, messageKeys, ciphertextMessage.getBody()) sessionState.clearUnacknowledgedPreKeyMessage() return plaintext def getOrCreateChainKey(self, sessionState, ECPublickKey_theirEphemeral): theirEphemeral = ECPublickKey_theirEphemeral if sessionState.hasReceiverChain(theirEphemeral): return sessionState.getReceiverChainKey(theirEphemeral) else: rootKey = sessionState.getRootKey() ourEphemeral = sessionState.getSenderRatchetKeyPair() receiverChain = rootKey.createChain(theirEphemeral, ourEphemeral) ourNewEphemeral = Curve.generateKeyPair() senderChain = receiverChain[0].createChain(theirEphemeral, ourNewEphemeral) sessionState.setRootKey(senderChain[0]) sessionState.addReceiverChain(theirEphemeral, receiverChain[1]) sessionState.setPreviousCounter(max(sessionState.getSenderChainKey().getIndex() - 1, 0)) sessionState.setSenderChain(ourNewEphemeral, senderChain[1]) return receiverChain[1] def getOrCreateMessageKeys(self, sessionState, ECPublicKey_theirEphemeral, chainKey, counter): theirEphemeral = ECPublicKey_theirEphemeral if chainKey.getIndex() > counter: if sessionState.hasMessageKeys(theirEphemeral, counter): return sessionState.removeMessageKeys(theirEphemeral, counter) else: raise DuplicateMessageException("Received message with old counter: %s, %s" % (chainKey.getIndex(), counter)) if counter - chainKey.getIndex() > 2000: raise InvalidMessageException("Over 2000 messages into the future!") while chainKey.getIndex() < counter: messageKeys = chainKey.getMessageKeys() sessionState.setMessageKeys(theirEphemeral, messageKeys) chainKey = chainKey.getNextChainKey() sessionState.setReceiverChainKey(theirEphemeral, chainKey.getNextChainKey()) return chainKey.getMessageKeys() def getCiphertext(self, version, messageKeys, plainText): """ :type version: int :type messageKeys: MessageKeys :type plainText: bytearray """ cipher = None if version >= 3: cipher = self.getCipher(messageKeys.getCipherKey(), messageKeys.getIv()) else: cipher = self.getCipher_v2(messageKeys.getCipherKey(), messageKeys.getCounter()) return cipher.encrypt(bytes(plainText)) def getPlaintext(self, version, messageKeys, cipherText): cipher = None if version >= 3: cipher = self.getCipher(messageKeys.getCipherKey(), messageKeys.getIv()) else: cipher = self.getCipher_v2(messageKeys.getCipherKey(), messageKeys.getCounter()) return cipher.decrypt(cipherText) def getCipher(self, key, iv): # Cipher.getInstance("AES/CBC/PKCS5Padding"); # cipher = AES.new(key, AES.MODE_CBC, IV = iv) # return cipher return AESCipher(key, iv) def getCipher_v2(self, key, counter): # AES/CTR/NoPadding # counterbytes = struct.pack('>L', counter) + (b'\x00' * 12) # counterint = struct.unpack(">L", counterbytes)[0] # counterint = int.from_bytes(counterbytes, byteorder='big') ctr = Counter.new(128, initial_value=counter) # cipher = AES.new(key, AES.MODE_CTR, counter=ctr) ivBytes = bytearray(16) ByteUtil.intToByteArray(ivBytes, 0, counter) cipher = AES.new(key, AES.MODE_CTR, IV=bytes(ivBytes), counter=ctr) return cipher BS = 16 if sys.version_info >= (3, 0): pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode() unpad = lambda s : s[0:-s[-1]] else: pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) unpad = lambda s : s[0:-ord(s[-1])] class AESCipher: def __init__(self, key, iv): self.key = key self.iv = iv self.cipher = AES.new(key, AES.MODE_CBC, IV = iv) def unpad(self, data): unpadLength = data[-1] if type(unpadLength) is int: cmp = bytes([data[-unpadLength]] * unpadLength) else: unpadLength = ord(unpadLength) cmp = data[-unpadLength] * unpadLength if data[-unpadLength:] != cmp: raise ValueError("Data not properly padded \n %s" % data) return data[0:-unpadLength] def encrypt(self, raw): # if sys.version_info >= (3,0): # rawPadded = pad(raw.decode()).encode() # else: rawPadded = pad(raw) try: return self.cipher.encrypt(rawPadded) except ValueError: raise def decrypt(self, enc): return self.unpad(self.cipher.decrypt(enc)) python-axolotl-0.1.39/axolotl/sessionbuilder.py0000644000175000017500000003521513064436211022137 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import logging from .ecc.curve import Curve from .ratchet.aliceaxolotlparameters import AliceAxolotlParameters from .ratchet.bobaxolotlparamaters import BobAxolotlParameters from .ratchet.symmetricaxolotlparameters import SymmetricAxolotlParameters from .ratchet.ratchetingsession import RatchetingSession from .invalidkeyexception import InvalidKeyException from .invalidkeyidexception import InvalidKeyIdException from .untrustedidentityexception import UntrustedIdentityException from .protocol.keyexchangemessage import KeyExchangeMessage from .protocol.ciphertextmessage import CiphertextMessage from .statekeyexchangeexception import StaleKeyExchangeException from .util.medium import Medium from .util.keyhelper import KeyHelper logger = logging.getLogger(__name__) class SessionBuilder: def __init__(self, sessionStore, preKeyStore, signedPreKeyStore, identityKeyStore, recepientId, deviceId): self.sessionStore = sessionStore self.preKeyStore = preKeyStore self.signedPreKeyStore = signedPreKeyStore self.identityKeyStore = identityKeyStore self.recipientId = recepientId self.deviceId = deviceId def process(self, sessionRecord, message): """ :param sessionRecord: :param message: :type message: PreKeyWhisperMessage """ messageVersion = message.getMessageVersion() theirIdentityKey = message.getIdentityKey() unsignedPreKeyId = None if not self.identityKeyStore.isTrustedIdentity(self.recipientId, theirIdentityKey): raise UntrustedIdentityException(self.recipientId, theirIdentityKey) if messageVersion == 2: unsignedPreKeyId = self.processV2(sessionRecord, message) elif messageVersion == 3: unsignedPreKeyId = self.processV3(sessionRecord, message) else: raise AssertionError("Unkown version %s" % messageVersion) self.identityKeyStore.saveIdentity(self.recipientId, theirIdentityKey) return unsignedPreKeyId def processV2(self, sessionRecord, message): """ :type sessionRecord: SessionRecord :type message: PreKeyWhisperMessage """ if message.getPreKeyId() is None: raise InvalidKeyIdException("V2 message requires one time prekey id!") if not self.preKeyStore.containsPreKey(message.getPreKeyId()) and \ self.sessionStore.containsSession(self.recipientId, self.deviceId): logging.warn("We've already processed the prekey part of this V2 session, " "letting bundled message fall through...") return None ourPreKey = self.preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair() parameters = BobAxolotlParameters.newBuilder() parameters.setOurIdentityKey(self.identityKeyStore.getIdentityKeyPair())\ .setOurSignedPreKey(ourPreKey)\ .setOurRatchetKey(ourPreKey)\ .setOurOneTimePreKey(None)\ .setTheirIdentityKey(message.getIdentityKey())\ .setTheirBaseKey(message.getBaseKey()) if not sessionRecord.isFresh(): sessionRecord.archiveCurrentState() RatchetingSession.initializeSessionAsBob(sessionRecord.getSessionState(), message.getMessageVersion(), parameters.create()) sessionRecord.getSessionState().setLocalRegistrationId(self.identityKeyStore.getLocalRegistrationId()) sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId()) sessionRecord.getSessionState().setAliceBaseKey(message.getBaseKey().serialize()) if message.getPreKeyId() != Medium.MAX_VALUE: return message.getPreKeyId() else: return None def processV3(self, sessionRecord, message): """ :param sessionRecord: :param message: :type message: PreKeyWhisperMessage :return: """ if sessionRecord.hasSessionState(message.getMessageVersion(), message.getBaseKey().serialize()): logger.warn("We've already setup a session for this V3 message, letting bundled message fall through...") return None ourSignedPreKey = self.signedPreKeyStore.loadSignedPreKey(message.getSignedPreKeyId()).getKeyPair() parameters = BobAxolotlParameters.newBuilder() parameters.setTheirBaseKey(message.getBaseKey())\ .setTheirIdentityKey(message.getIdentityKey())\ .setOurIdentityKey(self.identityKeyStore.getIdentityKeyPair())\ .setOurSignedPreKey(ourSignedPreKey)\ .setOurRatchetKey(ourSignedPreKey) if message.getPreKeyId() is not None: parameters.setOurOneTimePreKey(self.preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair()) else: parameters.setOurOneTimePreKey(None) if not sessionRecord.isFresh(): sessionRecord.archiveCurrentState() RatchetingSession.initializeSessionAsBob(sessionRecord.getSessionState(), message.getMessageVersion(), parameters.create()) sessionRecord.getSessionState().setLocalRegistrationId(self.identityKeyStore.getLocalRegistrationId()) sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId()) sessionRecord.getSessionState().setAliceBaseKey(message.getBaseKey().serialize()) if message.getPreKeyId() is not None and message.getPreKeyId() != Medium.MAX_VALUE: return message.getPreKeyId() else: return None def processPreKeyBundle(self, preKey): """ :type preKey: PreKeyBundle """ if not self.identityKeyStore.isTrustedIdentity(self.recipientId, preKey.getIdentityKey()): raise UntrustedIdentityException(self.recipientId, preKey.getIdentityKey()) if preKey.getSignedPreKey() is not None and\ not Curve.verifySignature(preKey.getIdentityKey().getPublicKey(), preKey.getSignedPreKey().serialize(), preKey.getSignedPreKeySignature()): raise InvalidKeyException("Invalid signature on device key!") if preKey.getSignedPreKey() is None and preKey.getPreKey() is None: raise InvalidKeyException("Both signed and unsigned prekeys are absent!") supportsV3 = preKey.getSignedPreKey() is not None sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId) ourBaseKey = Curve.generateKeyPair() theirSignedPreKey = preKey.getSignedPreKey() if supportsV3 else preKey.getPreKey() theirOneTimePreKey = preKey.getPreKey() theirOneTimePreKeyId = preKey.getPreKeyId() if theirOneTimePreKey is not None else None parameters = AliceAxolotlParameters.newBuilder() parameters.setOurBaseKey(ourBaseKey)\ .setOurIdentityKey(self.identityKeyStore.getIdentityKeyPair())\ .setTheirIdentityKey(preKey.getIdentityKey())\ .setTheirSignedPreKey(theirSignedPreKey)\ .setTheirRatchetKey(theirSignedPreKey)\ .setTheirOneTimePreKey(theirOneTimePreKey if supportsV3 else None) if not sessionRecord.isFresh(): sessionRecord.archiveCurrentState() RatchetingSession.initializeSessionAsAlice(sessionRecord.getSessionState(), 3 if supportsV3 else 2, parameters.create()) sessionRecord.getSessionState().setUnacknowledgedPreKeyMessage(theirOneTimePreKeyId, preKey.getSignedPreKeyId(), ourBaseKey.getPublicKey()) sessionRecord.getSessionState().setLocalRegistrationId(self.identityKeyStore.getLocalRegistrationId()) sessionRecord.getSessionState().setRemoteRegistrationId(preKey.getRegistrationId()) sessionRecord.getSessionState().setAliceBaseKey(ourBaseKey.getPublicKey().serialize()) self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord) self.identityKeyStore.saveIdentity(self.recipientId, preKey.getIdentityKey()) def processKeyExchangeMessage(self, keyExchangeMessage): if not self.identityKeyStore.isTrustedIdentity(self.recipientId, keyExchangeMessage.getIdentityKey()): raise UntrustedIdentityException(self.recipientId, keyExchangeMessage.getIdentityKey()) responseMessage = None if keyExchangeMessage.isInitiate(): responseMessage = self.processInitiate(keyExchangeMessage) else: self.processResponse(keyExchangeMessage) return responseMessage def processInitiate(self, keyExchangeMessage): flags = KeyExchangeMessage.RESPONSE_FLAG sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId) if keyExchangeMessage.getVersion() >= 3 and not Curve.verifySignature( keyExchangeMessage.getIdentityKey().getPublicKey(), keyExchangeMessage.getBaseKey().serialize(), keyExchangeMessage.getBaseKeySignature()): raise InvalidKeyException("Bad signature!") builder = SymmetricAxolotlParameters.newBuilder() if not sessionRecord.getSessionState().hasPendingKeyExchange(): builder.setOurIdentityKey(self.identityKeyStore.getIdentityKeyPair())\ .setOurBaseKey(Curve.generateKeyPair())\ .setOurRatchetKey(Curve.generateKeyPair()) else: builder.setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey())\ .setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey())\ .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey()) flags |= KeyExchangeMessage.SIMULTAENOUS_INITIATE_FLAG builder.setTheirBaseKey(keyExchangeMessage.getBaseKey())\ .setTheirRatchetKey(keyExchangeMessage.getRatchetKey())\ .setTheirIdentityKey(keyExchangeMessage.getIdentityKey()) parameters = builder.create() if not sessionRecord.isFresh(): sessionRecord.archiveCurrentState() RatchetingSession.initializeSession(sessionRecord.getSessionState(), min(keyExchangeMessage.getMaxVersion(), CiphertextMessage.CURRENT_VERSION), parameters) self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord) self.identityKeyStore.saveIdentity(self.recipientId, keyExchangeMessage.getIdentityKey()) baseKeySignature = Curve.calculateSignature(parameters.getOurIdentityKey().getPrivateKey(), parameters.getOurBaseKey().getPublicKey().serialize()) return KeyExchangeMessage(sessionRecord.getSessionState().getSessionVersion(), keyExchangeMessage.getSequence(), flags, parameters.getOurBaseKey().getPublicKey(), baseKeySignature, parameters.getOurRatchetKey().getPublicKey(), parameters.getOurIdentityKey().getPublicKey()) def processResponse(self, keyExchangeMessage): sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId) sessionState = sessionRecord.getSessionState() hasPendingKeyExchange = sessionState.hasPendingKeyExchange() isSimultaneousInitiateResponse = keyExchangeMessage.isResponseForSimultaneousInitiate() if not hasPendingKeyExchange \ or sessionState.getPendingKeyExchangeSequence() != keyExchangeMessage.getSequence(): logger.warn("No matching sequence for response. " "Is simultaneous initiate response: %s" % isSimultaneousInitiateResponse) if not isSimultaneousInitiateResponse: raise StaleKeyExchangeException() else: return parameters = SymmetricAxolotlParameters.newBuilder() parameters.setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey())\ .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey())\ .setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey())\ .setTheirBaseKey(keyExchangeMessage.getBaseKey())\ .setTheirRatchetKey(keyExchangeMessage.getRatchetKey())\ .setTheirIdentityKey(keyExchangeMessage.getIdentityKey()) if not sessionRecord.isFresh(): sessionRecord.archiveCurrentState() RatchetingSession.initializeSession(sessionRecord.getSessionState(), min(keyExchangeMessage.getMaxVersion(), CiphertextMessage.CURRENT_VERSION), parameters.create()) if sessionRecord.getSessionState().getSessionVersion() >= 3 and not Curve.verifySignature( keyExchangeMessage.getIdentityKey().getPublicKey(), keyExchangeMessage.getBaseKey().serialize(), keyExchangeMessage.getBaseKeySignature()): raise InvalidKeyException("Base key signature doesn't match!") self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord) self.identityKeyStore.saveIdentity(self.recipientId, keyExchangeMessage.getIdentityKey()) def processInitKeyExchangeMessage(self): try: sequence = KeyHelper.getRandomSequence(65534) + 1 flags = KeyExchangeMessage.INITIATE_FLAG baseKey = Curve.generateKeyPair() ratchetKey = Curve.generateKeyPair() identityKey = self.identityKeyStore.getIdentityKeyPair() baseKeySignature = Curve.calculateSignature(identityKey.getPrivateKey(), baseKey.getPublicKey().serialize()) sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId) sessionRecord.getSessionState().setPendingKeyExchange(sequence, baseKey, ratchetKey, identityKey) self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord) return KeyExchangeMessage(2, sequence, flags, baseKey.getPublicKey(), baseKeySignature, ratchetKey.getPublicKey(), identityKey.getPublicKey()) except InvalidKeyException as e: raise AssertionError(e) python-axolotl-0.1.39/axolotl/protocol/0000755000175000017500000000000013064436273020376 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/protocol/keyexchangemessage.py0000644000175000017500000001073613064436211024607 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from .ciphertextmessage import CiphertextMessage from ..util.byteutil import ByteUtil from . import whisperprotos_pb2 as whisperprotos from ..legacymessageexception import LegacyMessageException from ..invalidversionexception import InvalidVersionException from ..invalidmessageexception import InvalidMessageException from ..invalidkeyexception import InvalidKeyException from ..ecc.curve import Curve from ..identitykey import IdentityKey class KeyExchangeMessage: INITIATE_FLAG = 0x01 RESPONSE_FLAG = 0X02 SIMULTAENOUS_INITIATE_FLAG = 0x04 def __init__(self, messageVersion=None, sequence=None, flags=None, baseKey=None, baseKeySignature=None, ratchetKey=None, identityKey=None, serialized=None): """ :type messageVersion: int :type sequence: int :type flags:int :type baseKey: ECPublicKey :type baseKeySignature: bytearray :type ratchetKey: ECPublicKey :type identityKey: IdentityKey :type serialized: bytearray """ if serialized: try: parts = ByteUtil.split(serialized, 1, len(serialized) - 1) self.version = ByteUtil.highBitsToInt(parts[0][0]) self.supportedVersion = ByteUtil.lowBitsToInt(parts[0][0]) if self.version <= CiphertextMessage.UNSUPPORTED_VERSION: raise LegacyMessageException("Unsupportmessageed legacy version: %s" % self.version) if self.version > CiphertextMessage.CURRENT_VERSION: raise InvalidVersionException("Unkown version: %s" % self.version) message = whisperprotos.KeyExchangeMessage() message.ParseFromString(bytes(parts[1])) if (not message.HasField("id") or not message.HasField("baseKey") or not message.HasField("ratchetKey") or not message.HasField("identityKey") or (self.version >= 3 and not message.HasField("baseKeySignature"))): raise InvalidMessageException("Some required fields are missing!") self.sequence = message.id >> 5 self.flags = message.id & 0x1f self.serialized = serialized self.baseKey = Curve.decodePoint(bytearray(message.baseKey), 0) self.baseKeySignature = message.baseKeySignature self.ratchetKey = Curve.decodePoint(bytearray(message.ratchetKey), 0) self.identityKey = IdentityKey(message.identityKey, 0) except InvalidKeyException as e: raise InvalidMessageException(e) else: self.supportedVersion = CiphertextMessage.CURRENT_VERSION self.version = messageVersion self.sequence = sequence self.flags = flags self.baseKey = baseKey self.baseKeySignature = baseKeySignature self.ratchetKey = ratchetKey self.identityKey = identityKey version = [ByteUtil.intsToByteHighAndLow(self.version, self.supportedVersion)] keyExchangeMessage = whisperprotos.KeyExchangeMessage() keyExchangeMessage.id = (self.sequence << 5) | self.flags keyExchangeMessage.baseKey = baseKey.serialize() keyExchangeMessage.ratchetKey = ratchetKey.serialize() keyExchangeMessage.identityKey = identityKey.serialize() if messageVersion >= 3: keyExchangeMessage.baseKeySignature = baseKeySignature self.serialized = ByteUtil.combine(version, keyExchangeMessage.SerializeToString()) def getVersion(self): return self.version def getBaseKey(self): return self.baseKey def getBaseKeySignature(self): return self.baseKeySignature def getRatchetKey(self): return self.ratchetKey def getIdentityKey(self): return self.identityKey def hasIdentityKey(self): return True def getMaxVersion(self): return self.supportedVersion def isResponse(self): return ((self.flags & self.__class__.RESPONSE_FLAG) != 0) def isInitiate(self): return (self.flags & self.__class__.INITIATE_FLAG) != 0 def isResponseForSimultaneousInitiate(self): return (self.flags & self.__class__.SIMULTAENOUS_INITIATE_FLAG) != 0 def getFlags(self): return self.flags def getSequence(self): return self.sequence def serialize(self): return self.serialized python-axolotl-0.1.39/axolotl/protocol/ciphertextmessage.py0000644000175000017500000000102013064436211024455 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import abc class CiphertextMessage(object): __metaclass__ = abc.ABCMeta UNSUPPORTED_VERSION = 1 CURRENT_VERSION = 3 WHISPER_TYPE = 2 PREKEY_TYPE = 3 SENDERKEY_TYPE = 4 SENDERKEY_DISTRIBUTION_TYPE = 5 # This should be the worst case (worse than V2). So not always accurate, but good enough for padding. ENCRYPTED_MESSAGE_OVERHEAD = 53 @abc.abstractmethod def serialize(self): return @abc.abstractmethod def getType(self): return python-axolotl-0.1.39/axolotl/protocol/senderkeydistributionmessage.py0000644000175000017500000000632613064436211026745 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from .ciphertextmessage import CiphertextMessage from . import whisperprotos_pb2 as whisperprotos from ..util.byteutil import ByteUtil from ..legacymessageexception import LegacyMessageException from ..invalidmessageexception import InvalidMessageException from ..invalidkeyexception import InvalidKeyException from ..ecc.curve import Curve class SenderKeyDistributionMessage(CiphertextMessage): def __init__(self, id=None, iteration=None, chainKey=None, signatureKey=None, serialized=None): """ :type id: int :type iteration: int :type chainKey: bytearray :type signatureKey: ECPublicKey """ assert bool(id is not None and iteration is not None and chainKey is not None and signatureKey is not None)\ ^ bool(serialized),\ "Either pass arguments or serialized data" if serialized: try: messageParts = ByteUtil.split(serialized, 1, len(serialized)- 1) version = messageParts[0][0] message = messageParts[1] if ByteUtil.highBitsToInt(version) < 3: raise LegacyMessageException("Legacy message: %s" % ByteUtil.highBitsToInt(version)) if ByteUtil.highBitsToInt(version) > self.__class__.CURRENT_VERSION: raise InvalidMessageException("Unknown version: %s" % ByteUtil.highBitsToInt(version)) distributionMessage = whisperprotos.SenderKeyDistributionMessage() distributionMessage.ParseFromString(message) if distributionMessage.id is None or distributionMessage.iteration is None\ or distributionMessage.chainKey is None or distributionMessage.signingKey is None: raise InvalidMessageException("Incomplete message") self.serialized = serialized self.id = distributionMessage.id self.iteration = distributionMessage.iteration self.chainKey = distributionMessage.chainKey self.signatureKey = Curve.decodePoint(bytearray(distributionMessage.signingKey), 0) except Exception as e: raise InvalidMessageException(e) else: version = [ByteUtil.intsToByteHighAndLow(self.__class__.CURRENT_VERSION, self.__class__.CURRENT_VERSION)] self.id = id self.iteration = iteration self.chainKey = chainKey self.signatureKey = signatureKey message = whisperprotos.SenderKeyDistributionMessage() message.id = id message.iteration = iteration message.chainKey= bytes(chainKey) message.signingKey = signatureKey.serialize() message = message.SerializeToString() self.serialized = bytes(ByteUtil.combine(version, message)) def serialize(self): return self.serialized def getType(self): return self.__class__.SENDERKEY_DISTRIBUTION_TYPE def getIteration(self): return self.iteration def getChainKey(self): return self.chainKey def getSignatureKey(self): return self.signatureKey def getId(self): return self.idpython-axolotl-0.1.39/axolotl/protocol/whispermessage.py0000644000175000017500000001134513064436211023772 0ustar tarektarek00000000000000# -*- cosing: utf-8 -*- import hmac import hashlib from .ciphertextmessage import CiphertextMessage from ..util.byteutil import ByteUtil from ..ecc.curve import Curve from . import whisperprotos_pb2 as whisperprotos from ..legacymessageexception import LegacyMessageException from ..invalidmessageexception import InvalidMessageException from ..invalidkeyexception import InvalidKeyException class WhisperMessage(CiphertextMessage): MAC_LENGTH = 8 def __init__(self, messageVersion=None, macKey=None, ECPublicKey_senderRatchetKey=None, counter=None, previousCounter=None, ciphertext=None, senderIdentityKey=None, receiverIdentityKey=None, serialized=None): self.serialized = "" if serialized: try: assert type(serialized) in (str, bytes), "Expected serialized %s, got %s" % (str, type(serialized)) messageParts = ByteUtil.split(serialized, 1, len(serialized) - 1 - WhisperMessage.MAC_LENGTH, WhisperMessage.MAC_LENGTH) version = messageParts[0][0] message = messageParts[1] mac = messageParts[2] if ByteUtil.highBitsToInt(version) <= self.__class__.UNSUPPORTED_VERSION: raise LegacyMessageException("Legacy message %s" % ByteUtil.highBitsToInt(version)) if ByteUtil.highBitsToInt(version) > self.__class__.CURRENT_VERSION: raise InvalidMessageException("Unknown version: %s" % ByteUtil.highBitsToInt(version)) whisperMessage = whisperprotos.WhisperMessage() whisperMessage.ParseFromString(message) if not whisperMessage.ciphertext or whisperMessage.counter is None or not whisperMessage.ratchetKey: raise InvalidMessageException("Incomplete message") self.serialized = serialized self.senderRatchetKey = Curve.decodePoint(bytearray(whisperMessage.ratchetKey), 0) self.messageVersion = ByteUtil.highBitsToInt(version) self.counter = whisperMessage.counter self.previousCounter = whisperMessage.previousCounter self.ciphertext = whisperMessage.ciphertext except InvalidKeyException as e: raise InvalidMessageException(e) else: version = ByteUtil.intsToByteHighAndLow(messageVersion, self.__class__.CURRENT_VERSION) message = whisperprotos.WhisperMessage() message.ratchetKey = ECPublicKey_senderRatchetKey.serialize() message.counter = counter message.previousCounter = previousCounter message.ciphertext = ciphertext message = message.SerializeToString() mac = self.getMac(messageVersion, senderIdentityKey, receiverIdentityKey, macKey, ByteUtil.combine(version, message)) self.serialized = bytes(ByteUtil.combine(version, message, mac)) self.senderRatchetKey = ECPublicKey_senderRatchetKey self.counter = counter self.previousCounter = previousCounter self.ciphertext = ciphertext self.messageVersion = messageVersion def getSenderRatchetKey(self): return self.senderRatchetKey def getMessageVersion(self): return self.messageVersion def getCounter(self): return self.counter def getBody(self): return self.ciphertext def verifyMac(self, messageVersion, senderIdentityKey, receiverIdentityKey, macKey): parts = ByteUtil.split(self.serialized, len(self.serialized) - self.__class__.MAC_LENGTH, self.__class__.MAC_LENGTH) ourMac = self.getMac(messageVersion, senderIdentityKey, receiverIdentityKey, macKey, parts[0]) theirMac = parts[1] if ourMac != theirMac: raise InvalidMessageException("Bad Mac!") def getMac(self, messageVersion, senderIdentityKey, receiverIdentityKey, macKey, serialized): mac = hmac.new(macKey, digestmod=hashlib.sha256) if messageVersion >= 3: mac.update(senderIdentityKey.getPublicKey().serialize()) mac.update(receiverIdentityKey.getPublicKey().serialize()) mac.update(bytes(serialized)) fullMac = mac.digest() return ByteUtil.trim(fullMac, self.__class__.MAC_LENGTH) def serialize(self): return self.serialized def getType(self): return CiphertextMessage.WHISPER_TYPE def isLegacy(self, message): return message is not None and \ len(message) >= 1 and \ ByteUtil.highBitsToInt(message[0]) <= CiphertextMessage.UNSUPPORTED_VERSION python-axolotl-0.1.39/axolotl/protocol/__init__.py0000644000175000017500000000005613064436211022500 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- __author__ = 'tarek' python-axolotl-0.1.39/axolotl/protocol/prekeywhispermessage.py0000644000175000017500000000771113064436211025214 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from google.protobuf.message import DecodeError from .ciphertextmessage import CiphertextMessage from ..util.byteutil import ByteUtil from ..ecc.curve import Curve from ..identitykey import IdentityKey from .whispermessage import WhisperMessage from ..invalidversionexception import InvalidVersionException from ..invalidmessageexception import InvalidMessageException from ..legacymessageexception import LegacyMessageException from ..invalidkeyexception import InvalidKeyException from . import whisperprotos_pb2 as whisperprotos class PreKeyWhisperMessage(CiphertextMessage): def __init__(self, messageVersion=None, registrationId=None, preKeyId=None, signedPreKeyId=None, ecPublicBaseKey=None, identityKey=None, whisperMessage=None, serialized=None): if serialized: try: self.version = ByteUtil.highBitsToInt(serialized[0]) if self.version > CiphertextMessage.CURRENT_VERSION: raise InvalidVersionException("Unknown version %s" % self.version) preKeyWhisperMessage = whisperprotos.PreKeyWhisperMessage() preKeyWhisperMessage.ParseFromString(serialized[1:]) if (self.version == 2 and preKeyWhisperMessage.preKeyId is None) or \ (self.version == 3 and preKeyWhisperMessage.signedPreKeyId is None) or \ not preKeyWhisperMessage.baseKey or \ not preKeyWhisperMessage.identityKey or \ not preKeyWhisperMessage.message: raise InvalidMessageException("Incomplete message") self.serialized = serialized self.registrationId = preKeyWhisperMessage.registrationId self.preKeyId = preKeyWhisperMessage.preKeyId if preKeyWhisperMessage.signedPreKeyId is not None: self.signedPreKeyId = preKeyWhisperMessage.signedPreKeyId else: self.signedPreKeyId = -1 self.baseKey = Curve.decodePoint(bytearray(preKeyWhisperMessage.baseKey), 0) self.identityKey = IdentityKey(Curve.decodePoint(bytearray(preKeyWhisperMessage.identityKey), 0)) self.message = WhisperMessage(serialized=preKeyWhisperMessage.message) except (InvalidKeyException, LegacyMessageException, DecodeError) as e: raise InvalidMessageException(e) else: self.version = messageVersion self.registrationId = registrationId self.preKeyId = preKeyId self.signedPreKeyId = signedPreKeyId self.baseKey = ecPublicBaseKey self.identityKey = identityKey self.message = whisperMessage builder = whisperprotos.PreKeyWhisperMessage() builder.signedPreKeyId = signedPreKeyId builder.baseKey = ecPublicBaseKey.serialize() builder.identityKey = identityKey.serialize() builder.message = whisperMessage.serialize() builder.registrationId = registrationId if preKeyId is not None: builder.preKeyId = preKeyId versionBytes = ByteUtil.intsToByteHighAndLow(self.version, self.__class__.CURRENT_VERSION) messageBytes = builder.SerializeToString() self.serialized = bytes(ByteUtil.combine(versionBytes, messageBytes)) def getMessageVersion(self): return self.version def getIdentityKey(self): return self.identityKey def getRegistrationId(self): return self.registrationId def getPreKeyId(self): return self.preKeyId def getSignedPreKeyId(self): return self.signedPreKeyId def getBaseKey(self): return self.baseKey def getWhisperMessage(self): return self.message def serialize(self): return self.serialized def getType(self): return CiphertextMessage.PREKEY_TYPE python-axolotl-0.1.39/axolotl/protocol/senderkeymessage.py0000644000175000017500000000777113064436211024312 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from .ciphertextmessage import CiphertextMessage from ..util.byteutil import ByteUtil from ..legacymessageexception import LegacyMessageException from ..invalidmessageexception import InvalidMessageException from ..invalidkeyexception import InvalidKeyException from ..ecc.curve import Curve from . import whisperprotos_pb2 as whisperprotos class SenderKeyMessage(CiphertextMessage): SIGNATURE_LENGTH = 64 def __init__(self, keyId=None, iteration=None, ciphertext=None, signatureKey=None, serialized=None): assert bool(keyId is not None and iteration is not None and ciphertext is not None and signatureKey is not None) ^ bool(serialized), "Either pass arguments or serialized data" if serialized: try: messageParts = ByteUtil.split(serialized, 1, len(serialized) - 1 - self.__class__.SIGNATURE_LENGTH, self.__class__.SIGNATURE_LENGTH) version = messageParts[0][0] message = messageParts[1] signature = messageParts[2] if ByteUtil.highBitsToInt(version) < 3: raise LegacyMessageException("Legacy message: %s" % ByteUtil.highBitsToInt(version)) if ByteUtil.highBitsToInt(version) > self.__class__.CURRENT_VERSION: raise InvalidMessageException("Unknown version: %s" % ByteUtil.highBitsToInt(version)) senderKeyMessage = whisperprotos.SenderKeyMessage() senderKeyMessage.ParseFromString(message) if senderKeyMessage.id is None or senderKeyMessage.iteration is None or \ senderKeyMessage.ciphertext is None: raise InvalidMessageException("Incomplete message") self.serialized = serialized self.messageVersion = ByteUtil.highBitsToInt(version) self.keyId = senderKeyMessage.id self.iteration = senderKeyMessage.iteration self.ciphertext = senderKeyMessage.ciphertext except Exception as e: raise InvalidMessageException(e) else: version = [ByteUtil.intsToByteHighAndLow(self.__class__.CURRENT_VERSION, self.__class__.CURRENT_VERSION)] message = whisperprotos.SenderKeyMessage() message.id = keyId message.iteration = iteration message.ciphertext = ciphertext message = message.SerializeToString() signature = self.getSignature(signatureKey, bytes(ByteUtil.combine(version, message))) self.serialized = bytes(ByteUtil.combine(version, message, signature)) self.messageVersion = self.__class__.CURRENT_VERSION self.keyId = keyId self.iteration = iteration self.ciphertext = ciphertext def getKeyId(self): return self.keyId def getIteration(self): return self.iteration def getCipherText(self): return self.ciphertext def verifySignature(self, signatureKey): """ :type signatureKey: ECPublicKey """ try: parts = ByteUtil.split(self.serialized, len(self.serialized) - self.__class__.SIGNATURE_LENGTH, self.__class__.SIGNATURE_LENGTH) if not Curve.verifySignature(signatureKey, parts[0], parts[1]): raise InvalidMessageException("Invalid signature!") except InvalidKeyException as e: raise InvalidMessageException(e) def getSignature(self, signatureKey, serialized): """ :type signatureKey: ECPrivateKey :type serialized: bytearray """ try: return Curve.calculateSignature(signatureKey, serialized) except InvalidKeyException as e: raise AssertionError(e) def serialize(self): return self.serialized def getType(self): return CiphertextMessage.SENDERKEY_TYPEpython-axolotl-0.1.39/axolotl/protocol/whisperprotos_pb2.py0000644000175000017500000003252113064436211024436 0ustar tarektarek00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: WhisperTextProtocol.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='WhisperTextProtocol.proto', package='textsecure', serialized_pb=_b('\n\x19WhisperTextProtocol.proto\x12\ntextsecure\"b\n\x0eWhisperMessage\x12\x12\n\nratchetKey\x18\x01 \x01(\x0c\x12\x0f\n\x07\x63ounter\x18\x02 \x01(\r\x12\x17\n\x0fpreviousCounter\x18\x03 \x01(\r\x12\x12\n\nciphertext\x18\x04 \x01(\x0c\"\x8f\x01\n\x14PreKeyWhisperMessage\x12\x16\n\x0eregistrationId\x18\x05 \x01(\r\x12\x10\n\x08preKeyId\x18\x01 \x01(\r\x12\x16\n\x0esignedPreKeyId\x18\x06 \x01(\r\x12\x0f\n\x07\x62\x61seKey\x18\x02 \x01(\x0c\x12\x13\n\x0bidentityKey\x18\x03 \x01(\x0c\x12\x0f\n\x07message\x18\x04 \x01(\x0c\"t\n\x12KeyExchangeMessage\x12\n\n\x02id\x18\x01 \x01(\r\x12\x0f\n\x07\x62\x61seKey\x18\x02 \x01(\x0c\x12\x12\n\nratchetKey\x18\x03 \x01(\x0c\x12\x13\n\x0bidentityKey\x18\x04 \x01(\x0c\x12\x18\n\x10\x62\x61seKeySignature\x18\x05 \x01(\x0c\"E\n\x10SenderKeyMessage\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\titeration\x18\x02 \x01(\r\x12\x12\n\nciphertext\x18\x03 \x01(\x0c\"c\n\x1cSenderKeyDistributionMessage\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\titeration\x18\x02 \x01(\r\x12\x10\n\x08\x63hainKey\x18\x03 \x01(\x0c\x12\x12\n\nsigningKey\x18\x04 \x01(\x0c\x42\x37\n&org.whispersystems.libaxolotl.protocolB\rWhisperProtos') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) _WHISPERMESSAGE = _descriptor.Descriptor( name='WhisperMessage', full_name='textsecure.WhisperMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='ratchetKey', full_name='textsecure.WhisperMessage.ratchetKey', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='counter', full_name='textsecure.WhisperMessage.counter', index=1, number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='previousCounter', full_name='textsecure.WhisperMessage.previousCounter', index=2, number=3, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='ciphertext', full_name='textsecure.WhisperMessage.ciphertext', index=3, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=41, serialized_end=139, ) _PREKEYWHISPERMESSAGE = _descriptor.Descriptor( name='PreKeyWhisperMessage', full_name='textsecure.PreKeyWhisperMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='registrationId', full_name='textsecure.PreKeyWhisperMessage.registrationId', index=0, number=5, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='preKeyId', full_name='textsecure.PreKeyWhisperMessage.preKeyId', index=1, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='signedPreKeyId', full_name='textsecure.PreKeyWhisperMessage.signedPreKeyId', index=2, number=6, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='baseKey', full_name='textsecure.PreKeyWhisperMessage.baseKey', index=3, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='identityKey', full_name='textsecure.PreKeyWhisperMessage.identityKey', index=4, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='message', full_name='textsecure.PreKeyWhisperMessage.message', index=5, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=142, serialized_end=285, ) _KEYEXCHANGEMESSAGE = _descriptor.Descriptor( name='KeyExchangeMessage', full_name='textsecure.KeyExchangeMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='id', full_name='textsecure.KeyExchangeMessage.id', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='baseKey', full_name='textsecure.KeyExchangeMessage.baseKey', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='ratchetKey', full_name='textsecure.KeyExchangeMessage.ratchetKey', index=2, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='identityKey', full_name='textsecure.KeyExchangeMessage.identityKey', index=3, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='baseKeySignature', full_name='textsecure.KeyExchangeMessage.baseKeySignature', index=4, number=5, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=287, serialized_end=403, ) _SENDERKEYMESSAGE = _descriptor.Descriptor( name='SenderKeyMessage', full_name='textsecure.SenderKeyMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='id', full_name='textsecure.SenderKeyMessage.id', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='iteration', full_name='textsecure.SenderKeyMessage.iteration', index=1, number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='ciphertext', full_name='textsecure.SenderKeyMessage.ciphertext', index=2, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=405, serialized_end=474, ) _SENDERKEYDISTRIBUTIONMESSAGE = _descriptor.Descriptor( name='SenderKeyDistributionMessage', full_name='textsecure.SenderKeyDistributionMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='id', full_name='textsecure.SenderKeyDistributionMessage.id', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='iteration', full_name='textsecure.SenderKeyDistributionMessage.iteration', index=1, number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='chainKey', full_name='textsecure.SenderKeyDistributionMessage.chainKey', index=2, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='signingKey', full_name='textsecure.SenderKeyDistributionMessage.signingKey', index=3, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=476, serialized_end=575, ) DESCRIPTOR.message_types_by_name['WhisperMessage'] = _WHISPERMESSAGE DESCRIPTOR.message_types_by_name['PreKeyWhisperMessage'] = _PREKEYWHISPERMESSAGE DESCRIPTOR.message_types_by_name['KeyExchangeMessage'] = _KEYEXCHANGEMESSAGE DESCRIPTOR.message_types_by_name['SenderKeyMessage'] = _SENDERKEYMESSAGE DESCRIPTOR.message_types_by_name['SenderKeyDistributionMessage'] = _SENDERKEYDISTRIBUTIONMESSAGE WhisperMessage = _reflection.GeneratedProtocolMessageType('WhisperMessage', (_message.Message,), dict( DESCRIPTOR = _WHISPERMESSAGE, __module__ = 'WhisperTextProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.WhisperMessage) )) _sym_db.RegisterMessage(WhisperMessage) PreKeyWhisperMessage = _reflection.GeneratedProtocolMessageType('PreKeyWhisperMessage', (_message.Message,), dict( DESCRIPTOR = _PREKEYWHISPERMESSAGE, __module__ = 'WhisperTextProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.PreKeyWhisperMessage) )) _sym_db.RegisterMessage(PreKeyWhisperMessage) KeyExchangeMessage = _reflection.GeneratedProtocolMessageType('KeyExchangeMessage', (_message.Message,), dict( DESCRIPTOR = _KEYEXCHANGEMESSAGE, __module__ = 'WhisperTextProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.KeyExchangeMessage) )) _sym_db.RegisterMessage(KeyExchangeMessage) SenderKeyMessage = _reflection.GeneratedProtocolMessageType('SenderKeyMessage', (_message.Message,), dict( DESCRIPTOR = _SENDERKEYMESSAGE, __module__ = 'WhisperTextProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SenderKeyMessage) )) _sym_db.RegisterMessage(SenderKeyMessage) SenderKeyDistributionMessage = _reflection.GeneratedProtocolMessageType('SenderKeyDistributionMessage', (_message.Message,), dict( DESCRIPTOR = _SENDERKEYDISTRIBUTIONMESSAGE, __module__ = 'WhisperTextProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SenderKeyDistributionMessage) )) _sym_db.RegisterMessage(SenderKeyDistributionMessage) DESCRIPTOR.has_options = True DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n&org.whispersystems.libaxolotl.protocolB\rWhisperProtos')) # @@protoc_insertion_point(module_scope) python-axolotl-0.1.39/axolotl/invalidversionexception.py0000644000175000017500000000011513064436211024047 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class InvalidVersionException(Exception): pass python-axolotl-0.1.39/axolotl/kdf/0000755000175000017500000000000013064436273017301 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/kdf/hkdfv3.py0000644000175000017500000000017713064436211021035 0ustar tarektarek00000000000000# -*- codsing: utf-8 -*- from .hkdf import HKDF class HKDFv3(HKDF): def getIterationStartOffset(self): return 1 python-axolotl-0.1.39/axolotl/kdf/__init__.py0000644000175000017500000000005613064436211021403 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- __author__ = 'tarek' python-axolotl-0.1.39/axolotl/kdf/messagekeys.py0000644000175000017500000000065513064436211022171 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class MessageKeys: def __init__(self, cipherKey, macKey, iv, counter): self.cipherKey = cipherKey self.macKey = macKey self.iv = iv self.counter = counter def getCipherKey(self): return self.cipherKey def getMacKey(self): return self.macKey def getIv(self): return self.iv def getCounter(self): return self.counter python-axolotl-0.1.39/axolotl/kdf/derivedrootsecrets.py0000644000175000017500000000054013064436211023561 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ..util.byteutil import ByteUtil class DerivedRootSecrets: SIZE = 64 def __init__(self, okm): keys = ByteUtil.split(okm, 32, 32) self.rootKey = keys[0] self.chainKey = keys[1] def getRootKey(self): return self.rootKey def getChainKey(self): return self.chainKey python-axolotl-0.1.39/axolotl/kdf/derivedmessagesecrets.py0000644000175000017500000000125613064436211024227 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ..util.byteutil import ByteUtil class DerivedMessageSecrets: SIZE = 80 CIPHER_KEY_LENGTH = 32 MAC_KEY_LENGTH = 32 IV_LENGTH = 16 def __init__(self, okm): keys = ByteUtil.split(okm, self.__class__.CIPHER_KEY_LENGTH, self.__class__.MAC_KEY_LENGTH, self.__class__.IV_LENGTH) self.cipherKey = keys[0] # AES self.macKey = keys[1] # sha256 self.iv = keys[2] def getCipherKey(self): return self.cipherKey def getMacKey(self): return self.macKey def getIv(self): return self.iv python-axolotl-0.1.39/axolotl/kdf/hkdfv2.py0000644000175000017500000000017613064436211021033 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from .hkdf import HKDF class HKDFv2(HKDF): def getIterationStartOffset(self): return 0 python-axolotl-0.1.39/axolotl/kdf/hkdf.py0000644000175000017500000000345513064436211020566 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import abc import hmac import hashlib import math class HKDF(object): __metaclass__ = abc.ABCMeta HASH_OUTPUT_SIZE = 32 @staticmethod def createFor(messageVersion): from .hkdfv2 import HKDFv2 from .hkdfv3 import HKDFv3 if messageVersion == 2: return HKDFv2() elif messageVersion == 3: return HKDFv3() else: raise AssertionError("Unknown version: %s " % messageVersion) def deriveSecrets(self, inputKeyMaterial, info, outputLength, salt=None): salt = salt or bytearray(self.__class__.HASH_OUTPUT_SIZE) prk = self.extract(salt, inputKeyMaterial) return self.expand(prk, info, outputLength) def extract(self, salt, inputKeyMaterial): mac = hmac.new(bytes(salt), digestmod=hashlib.sha256) mac.update(bytes(inputKeyMaterial)) return mac.digest() def expand(self, prk, info, outputSize): iterations = int(math.ceil(float(outputSize) / float(self.__class__.HASH_OUTPUT_SIZE))) mixin = bytearray() results = bytearray() remainingBytes = outputSize for i in range(self.getIterationStartOffset(), iterations + self.getIterationStartOffset()): mac = hmac.new(prk, digestmod=hashlib.sha256) mac.update(bytes(mixin)) if info is not None: mac.update(bytes(info)) updateChr = chr(i % 256) mac.update(updateChr.encode()) stepResult = mac.digest() stepSize = min(remainingBytes, len(stepResult)) results.extend(stepResult[:stepSize]) mixin = stepResult remainingBytes -= stepSize return bytes(results) @abc.abstractmethod def getIterationStartOffset(self): return 0 python-axolotl-0.1.39/axolotl/tests/0000755000175000017500000000000013064436273017677 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/tests/util/0000755000175000017500000000000013064436273020654 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/tests/util/__init__.py0000644000175000017500000000005613064436211022756 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- __author__ = 'tarek' python-axolotl-0.1.39/axolotl/tests/util/test_byteutil.py0000644000175000017500000000147413064436211024124 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import unittest from ...util.byteutil import ByteUtil # from ...util.hexutil import HexUtil class ByteUtilTest(unittest.TestCase): def test_split(self): # okm = HexUtil.decodeHex('02a9aa6c7dbd64f9d3aa92f92a277bf54609dadf0b00' # '828acfc61e3c724b84a7bfbe5efb603030526742e3ee' # '89c7024e884e440f1ff376bb2317b2d64deb7c8322f4' # 'c5015d9d895849411ba1d793a827') data = [i for i in range(0, 80)] a_data = [i for i in range(0, 32)] b_data = [i for i in range(32, 64)] c_data = [i for i in range(64, 80)] a, b, c = ByteUtil.split(data, 32, 32, 16) self.assertEqual(a, a_data) self.assertEqual(b, b_data) self.assertEqual(c, c_data) python-axolotl-0.1.39/axolotl/tests/test_sigs.py0000644000175000017500000001074513064436211022254 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import unittest from ..ecc.curve import Curve from ..util.keyhelper import KeyHelper class Curve25519Test(unittest.TestCase): def test_agreement(self): alicePublic = bytearray([0x05, 0x1b, 0xb7, 0x59, 0x66, 0xf2, 0xe9, 0x3a, 0x36, 0x91, 0xdf, 0xff, 0x94, 0x2b, 0xb2, 0xa4, 0x66, 0xa1, 0xc0, 0x8b, 0x8d, 0x78, 0xca, 0x3f, 0x4d, 0x6d, 0xf8, 0xb8, 0xbf, 0xa2, 0xe4, 0xee, 0x28]) alicePrivate = bytearray([0xc8, 0x06, 0x43, 0x9d, 0xc9, 0xd2, 0xc4, 0x76, 0xff, 0xed, 0x8f, 0x25, 0x80, 0xc0, 0x88, 0x8d, 0x58, 0xab, 0x40, 0x6b, 0xf7, 0xae, 0x36, 0x98, 0x87, 0x90, 0x21, 0xb9, 0x6b, 0xb4, 0xbf, 0x59]) bobPublic = bytearray([0x05, 0x65, 0x36, 0x14, 0x99, 0x3d, 0x2b, 0x15, 0xee, 0x9e, 0x5f, 0xd3, 0xd8, 0x6c, 0xe7, 0x19, 0xef, 0x4e, 0xc1, 0xda, 0xae, 0x18, 0x86, 0xa8, 0x7b, 0x3f, 0x5f, 0xa9, 0x56, 0x5a, 0x27, 0xa2, 0x2f]) bobPrivate = bytearray([0xb0, 0x3b, 0x34, 0xc3, 0x3a, 0x1c, 0x44, 0xf2, 0x25, 0xb6, 0x62, 0xd2, 0xbf, 0x48, 0x59, 0xb8, 0x13, 0x54, 0x11, 0xfa, 0x7b, 0x03, 0x86, 0xd4, 0x5f, 0xb7, 0x5d, 0xc5, 0xb9, 0x1b, 0x44, 0x66]) shared = bytearray([0x32, 0x5f, 0x23, 0x93, 0x28, 0x94, 0x1c, 0xed, 0x6e, 0x67, 0x3b, 0x86, 0xba, 0x41, 0x01, 0x74, 0x48, 0xe9, 0x9b, 0x64, 0x9a, 0x9c, 0x38, 0x06, 0xc1, 0xdd, 0x7c, 0xa4, 0xc4, 0x77, 0xe6, 0x29]) alicePublicKey = Curve.decodePoint(alicePublic, 0) alicePrivateKey = Curve.decodePrivatePoint(alicePrivate) bobPublicKey = Curve.decodePoint(bobPublic, 0) bobPrivateKey = Curve.decodePrivatePoint(bobPrivate) sharedOne = Curve.calculateAgreement(alicePublicKey, bobPrivateKey) sharedTwo = Curve.calculateAgreement(bobPublicKey, alicePrivateKey) self.assertEqual(sharedOne, shared) self.assertEqual(sharedTwo, shared) def test_randomAgreements(self): for i in range(0, 50): alice = Curve.generateKeyPair() bob = Curve.generateKeyPair() sharedAlice = Curve.calculateAgreement(bob.getPublicKey(), alice.getPrivateKey()) sharedBob = Curve.calculateAgreement(alice.getPublicKey(), bob.getPrivateKey()) self.assertEqual(sharedAlice, sharedBob) def test_gensig(self): identityKeyPair = KeyHelper.generateIdentityKeyPair() KeyHelper.generateSignedPreKey(identityKeyPair, 0) def test_signature(self): # aliceIdentityPrivate = bytearray([0xc0, 0x97, 0x24, 0x84, 0x12, 0xe5, 0x8b, 0xf0, 0x5d, 0xf4, 0x87, 0x96, # 0x82, 0x05, 0x13, 0x27, 0x94, 0x17, 0x8e, 0x36, 0x76, 0x37, 0xf5, 0x81, # 0x8f, 0x81, 0xe0, 0xe6, 0xce, 0x73, 0xe8, 0x65]) aliceIdentityPublic = bytearray([0x05, 0xab, 0x7e, 0x71, 0x7d, 0x4a, 0x16, 0x3b, 0x7d, 0x9a, 0x1d, 0x80, 0x71, 0xdf, 0xe9, 0xdc, 0xf8, 0xcd, 0xcd, 0x1c, 0xea, 0x33, 0x39, 0xb6, 0x35, 0x6b, 0xe8, 0x4d, 0x88, 0x7e, 0x32, 0x2c, 0x64]) aliceEphemeralPublic = bytearray([0x05, 0xed, 0xce, 0x9d, 0x9c, 0x41, 0x5c, 0xa7, 0x8c, 0xb7, 0x25, 0x2e, 0x72, 0xc2, 0xc4, 0xa5, 0x54, 0xd3, 0xeb, 0x29, 0x48, 0x5a, 0x0e, 0x1d, 0x50, 0x31, 0x18, 0xd1, 0xa8, 0x2d, 0x99, 0xfb, 0x4a]) aliceSignature = bytearray([0x5d, 0xe8, 0x8c, 0xa9, 0xa8, 0x9b, 0x4a, 0x11, 0x5d, 0xa7, 0x91, 0x09, 0xc6, 0x7c, 0x9c, 0x74, 0x64, 0xa3, 0xe4, 0x18, 0x02, 0x74, 0xf1, 0xcb, 0x8c, 0x63, 0xc2, 0x98, 0x4e, 0x28, 0x6d, 0xfb, 0xed, 0xe8, 0x2d, 0xeb, 0x9d, 0xcd, 0x9f, 0xae, 0x0b, 0xfb, 0xb8, 0x21, 0x56, 0x9b, 0x3d, 0x90, 0x01, 0xbd, 0x81, 0x30, 0xcd, 0x11, 0xd4, 0x86, 0xce, 0xf0, 0x47, 0xbd, 0x60, 0xb8, 0x6e, 0x88]) # alicePrivateKey = Curve.decodePrivatePoint(aliceIdentityPrivate) alicePublicKey = Curve.decodePoint(aliceIdentityPublic, 0) aliceEphemeral = Curve.decodePoint(aliceEphemeralPublic, 0) res = Curve.verifySignature(alicePublicKey, aliceEphemeral.serialize(), bytes(aliceSignature)) self.assertTrue(res) python-axolotl-0.1.39/axolotl/tests/__init__.py0000644000175000017500000000003013064436211021771 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- python-axolotl-0.1.39/axolotl/tests/test_sessioncipher.py0000644000175000017500000001722613064436211024166 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import unittest import sys from ..state.sessionrecord import SessionRecord from ..ecc.curve import Curve from ..identitykeypair import IdentityKeyPair, IdentityKey from ..ratchet.aliceaxolotlparameters import AliceAxolotlParameters from ..ratchet.bobaxolotlparamaters import BobAxolotlParameters from ..ratchet.ratchetingsession import RatchetingSession from ..tests.inmemoryaxolotlstore import InMemoryAxolotlStore from ..sessioncipher import SessionCipher from ..protocol.whispermessage import WhisperMessage class SessionCipherTest(unittest.TestCase): def test_basicSessionV2(self): aliceSessionRecord = SessionRecord() bobSessionRecord = SessionRecord() self.initializeSessionsV2(aliceSessionRecord.getSessionState(), bobSessionRecord.getSessionState()) self.runInteraction(aliceSessionRecord, bobSessionRecord) def test_basicSessionV3(self): aliceSessionRecord = SessionRecord() bobSessionRecord = SessionRecord() self.initializeSessionsV3(aliceSessionRecord.getSessionState(), bobSessionRecord.getSessionState()) self.runInteraction(aliceSessionRecord, bobSessionRecord) def runInteraction(self, aliceSessionRecord, bobSessionRecord): aliceStore = InMemoryAxolotlStore() bobStore = InMemoryAxolotlStore() aliceStore.storeSession(2, 1, aliceSessionRecord) bobStore.storeSession(3, 1, bobSessionRecord) aliceCipher = SessionCipher(aliceStore, aliceStore, aliceStore, aliceStore, 2, 1) bobCipher = SessionCipher(bobStore, bobStore, bobStore, bobStore, 3, 1) alicePlaintext = "This is a plaintext message." message = aliceCipher.encrypt(alicePlaintext) bobPlaintext = bobCipher.decryptMsg(WhisperMessage(serialized=message.serialize())) if sys.version_info >= (3,0): bobPlaintext = bobPlaintext.decode() self.assertEqual(alicePlaintext, bobPlaintext) bobReply = "This is a message from Bob." reply = bobCipher.encrypt(bobReply) receivedReply = aliceCipher.decryptMsg(WhisperMessage(serialized=reply.serialize())) if sys.version_info >= (3,0): receivedReply = receivedReply.decode() self.assertEqual(bobReply, receivedReply) aliceCiphertextMessages = [] alicePlaintextMessages = [] for i in range(0, 50): alicePlaintextMessages.append("смерть за смерть %s" % i) aliceCiphertextMessages.append(aliceCipher.encrypt("смерть за смерть %s" % i)) # shuffle(aliceCiphertextMessages) # shuffle(alicePlaintextMessages) for i in range(0, int(len(aliceCiphertextMessages)/2)): receivedPlaintext = bobCipher.decryptMsg(WhisperMessage(serialized=aliceCiphertextMessages[i].serialize())) self.assertEqual(receivedPlaintext.decode() if sys.version_info >= (3,0) else receivedPlaintext, alicePlaintextMessages[i]) """ List bobCiphertextMessages = new ArrayList<>(); List bobPlaintextMessages = new ArrayList<>(); for (int i=0;i<20;i++) { bobPlaintextMessages.add(("смерть за смерть " + i).getBytes()); bobCiphertextMessages.add(bobCipher.encrypt(("смерть за смерть " + i).getBytes())); } seed = System.currentTimeMillis(); Collections.shuffle(bobCiphertextMessages, new Random(seed)); Collections.shuffle(bobPlaintextMessages, new Random(seed)); for (int i=0;i= (3,0): plaintext = plaintext.decode() self.assertTrue(bobStore.containsSession(self.__class__.ALICE_RECIPIENT_ID, 1)) self.assertTrue(bobStore.loadSession(self.__class__.ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 2) self.assertEqual(originalMessage, plaintext) bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage) self.assertTrue(bobOutgoingMessage.getType() == CiphertextMessage.WHISPER_TYPE) alicePlaintext = aliceSessionCipher.decryptMsg(bobOutgoingMessage) if sys.version_info >= (3,0): alicePlaintext = alicePlaintext.decode() self.assertEqual(alicePlaintext, originalMessage) self.runInteraction(aliceStore, bobStore) aliceStore = InMemoryAxolotlStore() aliceSessionBuilder = SessionBuilder(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) aliceSessionCipher = SessionCipher(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) bobPreKeyPair = Curve.generateKeyPair() bobPreKey = PreKeyBundle(bobStore.getLocalRegistrationId(), 1, 31338, bobPreKeyPair.getPublicKey(), 0, None, None, bobStore.getIdentityKeyPair().getPublicKey()) bobStore.storePreKey(31338, PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair)) aliceSessionBuilder.processPreKeyBundle(bobPreKey) outgoingMessage = aliceSessionCipher.encrypt(originalMessage) try: bobSessionCipher.decryptPkmsg(PreKeyWhisperMessage(serialized=outgoingMessage.serialize())) raise AssertionError("shouldn't be trusted!") except Exception: bobStore.saveIdentity(self.__class__.ALICE_RECIPIENT_ID, PreKeyWhisperMessage(serialized=outgoingMessage.serialize()).getIdentityKey()) plaintext = bobSessionCipher.decryptPkmsg(PreKeyWhisperMessage(serialized=outgoingMessage.serialize())) if sys.version_info >= (3,0): plaintext = plaintext.decode() self.assertEqual(plaintext, originalMessage) bobPreKey = PreKeyBundle(bobStore.getLocalRegistrationId(), 1, 31337, Curve.generateKeyPair().getPublicKey(), 0, None, None, aliceStore.getIdentityKeyPair().getPublicKey()) try: aliceSessionBuilder.processPreKeyBundle(bobPreKey) raise AssertionError("shouldn't be trusted") except Exception: # good pass return def test_basicPreKeyV3(self): aliceStore = InMemoryAxolotlStore() aliceSessionBuilder = SessionBuilder(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) bobStore = InMemoryAxolotlStore() bobPreKeyPair = Curve.generateKeyPair() bobSignedPreKeyPair = Curve.generateKeyPair() bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(), bobSignedPreKeyPair.getPublicKey().serialize()) bobPreKey = PreKeyBundle(bobStore.getLocalRegistrationId(), 1, 31337, bobPreKeyPair.getPublicKey(), 22, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature, bobStore.getIdentityKeyPair().getPublicKey()) aliceSessionBuilder.processPreKeyBundle(bobPreKey) self.assertTrue(aliceStore.containsSession(self.__class__.BOB_RECIPIENT_ID, 1)) self.assertTrue(aliceStore.loadSession(self.__class__.BOB_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3) originalMessage = "L'homme est condamné à être libre" aliceSessionCipher = SessionCipher(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) outgoingMessage = aliceSessionCipher.encrypt(originalMessage) self.assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE) incomingMessage = PreKeyWhisperMessage(serialized=outgoingMessage.serialize()) bobStore.storePreKey(31337, PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair)) bobStore.storeSignedPreKey(22, SignedPreKeyRecord(22, int(time.time() * 1000), bobSignedPreKeyPair, bobSignedPreKeySignature)) bobSessionCipher = SessionCipher(bobStore, bobStore, bobStore, bobStore, self.__class__.ALICE_RECIPIENT_ID, 1) plaintext = bobSessionCipher.decryptPkmsg(incomingMessage) if sys.version_info >= (3,0): plaintext = plaintext.decode() self.assertEqual(originalMessage, plaintext) # @@TODO: in callback assertion # self.assertFalse(bobStore.containsSession(self.__class__.ALICE_RECIPIENT_ID, 1)) self.assertTrue(bobStore.containsSession(self.__class__.ALICE_RECIPIENT_ID, 1)) self.assertTrue(bobStore.loadSession(self.__class__.ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3) self.assertTrue(bobStore.loadSession(self.__class__.ALICE_RECIPIENT_ID, 1).getSessionState().getAliceBaseKey() is not None) self.assertEqual(originalMessage, plaintext) bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage) self.assertTrue(bobOutgoingMessage.getType() == CiphertextMessage.WHISPER_TYPE) alicePlaintext = aliceSessionCipher.decryptMsg(WhisperMessage(serialized=bobOutgoingMessage.serialize())) if sys.version_info >= (3,0): alicePlaintext = alicePlaintext.decode() self.assertEqual(alicePlaintext, originalMessage) self.runInteraction(aliceStore, bobStore) aliceStore = InMemoryAxolotlStore() aliceSessionBuilder = SessionBuilder(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) aliceSessionCipher = SessionCipher(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) bobPreKeyPair = Curve.generateKeyPair() bobSignedPreKeyPair = Curve.generateKeyPair() bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(), bobSignedPreKeyPair.getPublicKey().serialize()) bobPreKey = PreKeyBundle(bobStore.getLocalRegistrationId(), 1, 31338, bobPreKeyPair.getPublicKey(), 23, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature, bobStore.getIdentityKeyPair().getPublicKey()) bobStore.storePreKey(31338, PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair)) bobStore.storeSignedPreKey(23, SignedPreKeyRecord(23, int(time.time() * 1000), bobSignedPreKeyPair, bobSignedPreKeySignature)) aliceSessionBuilder.processPreKeyBundle(bobPreKey) outgoingMessage = aliceSessionCipher.encrypt(originalMessage) try: plaintext = bobSessionCipher.decryptPkmsg(PreKeyWhisperMessage(serialized=outgoingMessage)) raise AssertionError("shouldn't be trusted!") except Exception: bobStore.saveIdentity(self.__class__.ALICE_RECIPIENT_ID, PreKeyWhisperMessage(serialized=outgoingMessage.serialize()).getIdentityKey()) plaintext = bobSessionCipher.decryptPkmsg(PreKeyWhisperMessage(serialized=outgoingMessage.serialize())) if sys.version_info >= (3,0): plaintext = plaintext.decode() self.assertEqual(plaintext, originalMessage) bobPreKey = PreKeyBundle(bobStore.getLocalRegistrationId(), 1, 31337, Curve.generateKeyPair().getPublicKey(), 23, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature, aliceStore.getIdentityKeyPair().getPublicKey()) try: aliceSessionBuilder.process(bobPreKey) raise AssertionError("shouldn't be trusted!") except Exception: # good pass def test_badSignedPreKeySignature(self): aliceStore = InMemoryAxolotlStore() aliceSessionBuilder = SessionBuilder(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) bobIdentityKeyStore = InMemoryIdentityKeyStore() bobPreKeyPair = Curve.generateKeyPair() bobSignedPreKeyPair = Curve.generateKeyPair() bobSignedPreKeySignature = Curve.calculateSignature(bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(), bobSignedPreKeyPair.getPublicKey().serialize()) for i in range(0, len(bobSignedPreKeySignature) * 8): modifiedSignature = bytearray(bobSignedPreKeySignature[:]) modifiedSignature[int(i/8)] ^= 0x01 << (i % 8) bobPreKey = PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1, 31337, bobPreKeyPair.getPublicKey(), 22, bobSignedPreKeyPair.getPublicKey(), modifiedSignature, bobIdentityKeyStore.getIdentityKeyPair().getPublicKey()) try: aliceSessionBuilder.processPreKeyBundle(bobPreKey) except Exception: # good pass bobPreKey = PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1, 31337, bobPreKeyPair.getPublicKey(), 22, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature, bobIdentityKeyStore.getIdentityKeyPair().getPublicKey()) aliceSessionBuilder.processPreKeyBundle(bobPreKey) def test_basicKeyExchange(self): aliceStore = InMemoryAxolotlStore() aliceSessionBuilder = SessionBuilder(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) bobStore = InMemoryAxolotlStore() bobSessionBuilder = SessionBuilder(bobStore, bobStore, bobStore, bobStore, self.__class__.ALICE_RECIPIENT_ID, 1) aliceKeyExchangeMessage = aliceSessionBuilder.processInitKeyExchangeMessage() self.assertTrue(aliceKeyExchangeMessage is not None) aliceKeyExchangeMessageBytes = aliceKeyExchangeMessage.serialize() bobKeyExchangeMessage = bobSessionBuilder.processKeyExchangeMessage(KeyExchangeMessage( serialized=aliceKeyExchangeMessageBytes)) self.assertTrue(bobKeyExchangeMessage is not None) bobKeyExchangeMessageBytes = bobKeyExchangeMessage.serialize() response = aliceSessionBuilder.processKeyExchangeMessage(KeyExchangeMessage( serialized=bobKeyExchangeMessageBytes)) self.assertTrue(response is None) self.assertTrue(aliceStore.containsSession(self.__class__.BOB_RECIPIENT_ID, 1)) self.assertTrue(bobStore.containsSession(self.__class__.ALICE_RECIPIENT_ID, 1)) self.runInteraction(aliceStore, bobStore) aliceStore = InMemoryAxolotlStore() aliceSessionBuilder = SessionBuilder(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) aliceKeyExchangeMessage = aliceSessionBuilder.processInitKeyExchangeMessage() try: bobKeyExchangeMessage = bobSessionBuilder.processKeyExchangeMessage(aliceKeyExchangeMessage) raise AssertionError("This identity shouldn't be trusted!") except UntrustedIdentityException: bobStore.saveIdentity(self.__class__.ALICE_RECIPIENT_ID, aliceKeyExchangeMessage.getIdentityKey()) bobKeyExchangeMessage = bobSessionBuilder.processKeyExchangeMessage(aliceKeyExchangeMessage) self.assertTrue(aliceSessionBuilder.processKeyExchangeMessage(bobKeyExchangeMessage) == None) self.runInteraction(aliceStore, bobStore) def runInteraction(self, aliceStore, bobStore): """ :type aliceStore: AxolotlStore :type bobStore: AxolotlStore """ aliceSessionCipher = SessionCipher(aliceStore, aliceStore, aliceStore, aliceStore, self.__class__.BOB_RECIPIENT_ID, 1) bobSessionCipher = SessionCipher(bobStore, bobStore, bobStore, bobStore, self.__class__.ALICE_RECIPIENT_ID, 1) originalMessage = "smert ze smert" aliceMessage = aliceSessionCipher.encrypt(originalMessage) self.assertTrue(aliceMessage.getType() == CiphertextMessage.WHISPER_TYPE) plaintext = bobSessionCipher.decryptMsg(WhisperMessage(serialized=aliceMessage.serialize())) if sys.version_info >= (3,0): plaintext = plaintext.decode() self.assertEqual(plaintext, originalMessage) bobMessage = bobSessionCipher.encrypt(originalMessage) self.assertTrue(bobMessage.getType() == CiphertextMessage.WHISPER_TYPE) plaintext = aliceSessionCipher.decryptMsg(WhisperMessage(serialized=bobMessage.serialize())) if sys.version_info >= (3,0): plaintext = plaintext.decode() self.assertEqual(plaintext, originalMessage) for i in range(0, 10): loopingMessage = "What do we mean by saying that existence precedes essence? " \ "We mean that man first of all exists, encounters himself, " \ "surges up in the world--and defines himself aftward. %s" % i aliceLoopingMessage = aliceSessionCipher.encrypt(loopingMessage) loopingPlaintext = bobSessionCipher.decryptMsg(WhisperMessage(serialized=aliceLoopingMessage.serialize())) if sys.version_info >= (3,0): loopingPlaintext = loopingPlaintext.decode() self.assertEqual(loopingPlaintext, loopingMessage) for i in range(0, 10): loopingMessage = "What do we mean by saying that existence precedes essence? " \ "We mean that man first of all exists, encounters himself, " \ "surges up in the world--and defines himself aftward. %s" % i bobLoopingMessage = bobSessionCipher.encrypt(loopingMessage) loopingPlaintext = aliceSessionCipher.decryptMsg(WhisperMessage(serialized=bobLoopingMessage.serialize())) if sys.version_info >= (3,0): loopingPlaintext = loopingPlaintext.decode() self.assertEqual(loopingPlaintext, loopingMessage) aliceOutOfOrderMessages = [] for i in range(0, 10): loopingMessage = "What do we mean by saying that existence precedes essence? " \ "We mean that man first of all exists, encounters himself, " \ "surges up in the world--and defines himself aftward. %s" % i aliceLoopingMessage = aliceSessionCipher.encrypt(loopingMessage) aliceOutOfOrderMessages.append((loopingMessage, aliceLoopingMessage)) for i in range(0, 10): loopingMessage = "What do we mean by saying that existence precedes essence? " \ "We mean that man first of all exists, encounters himself, " \ "surges up in the world--and defines himself aftward. %s" % i aliceLoopingMessage = aliceSessionCipher.encrypt(loopingMessage) loopingPlaintext = bobSessionCipher.decryptMsg(WhisperMessage(serialized=aliceLoopingMessage.serialize())) if sys.version_info >= (3,0): loopingPlaintext = loopingPlaintext.decode() self.assertEqual(loopingPlaintext, loopingMessage) for i in range(0, 10): loopingMessage = "You can only desire based on what you know: %s" % i bobLoopingMessage = bobSessionCipher.encrypt(loopingMessage) loopingPlaintext = aliceSessionCipher.decryptMsg(WhisperMessage(serialized=bobLoopingMessage.serialize())) if sys.version_info >= (3,0): loopingPlaintext = loopingPlaintext.decode() self.assertEqual(loopingPlaintext, loopingMessage) for aliceOutOfOrderMessage in aliceOutOfOrderMessages: outOfOrderPlaintext = bobSessionCipher.decryptMsg(WhisperMessage( serialized=aliceOutOfOrderMessage[1].serialize())) if sys.version_info >= (3,0): outOfOrderPlaintext = outOfOrderPlaintext.decode() self.assertEqual(outOfOrderPlaintext, aliceOutOfOrderMessage[0]) python-axolotl-0.1.39/axolotl/tests/kdf/0000755000175000017500000000000013064436273020443 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/tests/kdf/test_hkdf.py0000644000175000017500000001116513064436211022764 0ustar tarektarek00000000000000# -*- coding ;utf-8 -*- import unittest from ...kdf.hkdf import HKDF class HKDFTest(unittest.TestCase): def test_vectorV3(self): ikm = bytearray([0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b]) salt = bytearray([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c]) info = bytearray([0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9]) okm = bytearray([0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65]) actualOutput = HKDF.createFor(3).deriveSecrets(ikm, info, 42, salt=salt) self.assertEqual(okm, actualOutput) def test_vectorLongV3(self): ikm = bytearray([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f]) salt = bytearray([0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf]) info = bytearray([0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff]) okm = bytearray([0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87]) actualOutput = HKDF.createFor(3).deriveSecrets(ikm, info, 82, salt=salt) self.assertEqual(okm, actualOutput) def test_vectorV3_(self): ikm = bytearray([0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b]) salt = bytearray([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c]) info = bytearray([0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9]) okm = bytearray([0x6e, 0xc2, 0x55, 0x6d, 0x5d, 0x7b, 0x1d, 0x81, 0xde, 0xe4, 0x22, 0x2a, 0xd7, 0x48, 0x36, 0x95, 0xdd, 0xc9, 0x8f, 0x4f, 0x5f, 0xab, 0xc0, 0xe0, 0x20, 0x5d, 0xc2, 0xef, 0x87, 0x52, 0xd4, 0x1e, 0x04, 0xe2, 0xe2, 0x11, 0x01, 0xc6, 0x8f, 0xf0, 0x93, 0x94, 0xb8, 0xad, 0x0b, 0xdc, 0xb9, 0x60, 0x9c, 0xd4, 0xee, 0x82, 0xac, 0x13, 0x19, 0x9b, 0x4a, 0xa9, 0xfd, 0xa8, 0x99, 0xda, 0xeb, 0xec]) actualOutput = HKDF.createFor(2).deriveSecrets(ikm, info, 64, salt=salt) self.assertEqual(okm, actualOutput) python-axolotl-0.1.39/axolotl/tests/kdf/__init__.py0000644000175000017500000000005613064436211022545 0ustar tarektarek00000000000000# -*- cosing: utf-8 -*- __author__ = 'tarek' python-axolotl-0.1.39/axolotl/tests/inmemoryprekeystore.py0000644000175000017500000000137413064436211024402 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ..state.prekeystore import PreKeyStore from ..state.prekeyrecord import PreKeyRecord from ..invalidkeyidexception import InvalidKeyIdException class InMemoryPreKeyStore(PreKeyStore): def __init__(self): self.store = {} def loadPreKey(self, preKeyId): if preKeyId not in self.store: raise InvalidKeyIdException("No such prekeyRecord!") return PreKeyRecord(serialized=self.store[preKeyId]) def storePreKey(self, preKeyId, preKeyRecord): self.store[preKeyId] = preKeyRecord.serialize() def containsPreKey(self, preKeyId): return preKeyId in self.store def removePreKey(self, preKeyId): if preKeyId in self.store: del self.store[preKeyId] python-axolotl-0.1.39/axolotl/tests/groups/0000755000175000017500000000000013064436273021216 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/tests/groups/__init__.py0000644000175000017500000000003013064436211023310 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- python-axolotl-0.1.39/axolotl/tests/groups/test_groupcipher.py0000644000175000017500000001317413064436211025154 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import unittest from .inmemorysenderkeystore import InMemorySenderKeyStore from ...groups.groupsessionbuilder import GroupSessionBuilder from ...util.keyhelper import KeyHelper from ...groups.groupcipher import GroupCipher from ...duplicatemessagexception import DuplicateMessageException from ...nosessionexception import NoSessionException from ...groups.senderkeyname import SenderKeyName from ...axolotladdress import AxolotlAddress from ...protocol.senderkeydistributionmessage import SenderKeyDistributionMessage SENDER_ADDRESS = AxolotlAddress("+14150001111", 1) GROUP_SENDER = SenderKeyName("nihilist history reading group", SENDER_ADDRESS); class GroupCipherTest(unittest.TestCase): def test_noSession(self): aliceStore = InMemorySenderKeyStore(); bobStore = InMemorySenderKeyStore(); aliceSessionBuilder = GroupSessionBuilder(aliceStore) bobSessionBuilder = GroupSessionBuilder(bobStore) aliceGroupCipher = GroupCipher(aliceStore, GROUP_SENDER) bobGroupCipher = GroupCipher(bobStore, GROUP_SENDER); sentAliceDistributionMessage = aliceSessionBuilder.create(GROUP_SENDER); receivedAliceDistributionMessage = SenderKeyDistributionMessage(serialized = sentAliceDistributionMessage.serialize()); ciphertextFromAlice = aliceGroupCipher.encrypt("smert ze smert"); try: plaintextFromAlice = bobGroupCipher.decrypt(ciphertextFromAlice); raise AssertionError("Should be no session!"); except NoSessionException as e: pass def test_basicEncryptDecrypt(self): aliceStore = InMemorySenderKeyStore(); bobStore = InMemorySenderKeyStore(); aliceSessionBuilder = GroupSessionBuilder(aliceStore) bobSessionBuilder = GroupSessionBuilder(bobStore) aliceGroupCipher = GroupCipher(aliceStore, GROUP_SENDER) bobGroupCipher = GroupCipher(bobStore, GROUP_SENDER); sentAliceDistributionMessage = aliceSessionBuilder.create(GROUP_SENDER); receivedAliceDistributionMessage = SenderKeyDistributionMessage(serialized = sentAliceDistributionMessage.serialize()); bobSessionBuilder.process(GROUP_SENDER, receivedAliceDistributionMessage) ciphertextFromAlice = aliceGroupCipher.encrypt("smert ze smert") plaintextFromAlice = bobGroupCipher.decrypt(ciphertextFromAlice) self.assertEqual(plaintextFromAlice, "smert ze smert") def test_basicRatchet(self): aliceStore = InMemorySenderKeyStore() bobStore = InMemorySenderKeyStore() aliceSessionBuilder = GroupSessionBuilder(aliceStore) bobSessionBuilder = GroupSessionBuilder(bobStore) aliceGroupCipher = GroupCipher(aliceStore, "groupWithBobInIt") bobGroupCipher = GroupCipher(bobStore, "groupWithBobInIt::aliceUserName") aliceGroupCipher = GroupCipher(aliceStore, GROUP_SENDER) bobGroupCipher = GroupCipher(bobStore, GROUP_SENDER); sentAliceDistributionMessage = aliceSessionBuilder.create(GROUP_SENDER); receivedAliceDistributionMessage = SenderKeyDistributionMessage(serialized = sentAliceDistributionMessage.serialize()); bobSessionBuilder.process(GROUP_SENDER, receivedAliceDistributionMessage) ciphertextFromAlice = aliceGroupCipher.encrypt("smert ze smert") ciphertextFromAlice2 = aliceGroupCipher.encrypt("smert ze smert2") ciphertextFromAlice3 = aliceGroupCipher.encrypt("smert ze smert3") plaintextFromAlice = bobGroupCipher.decrypt(ciphertextFromAlice) try: bobGroupCipher.decrypt(ciphertextFromAlice) raise AssertionError("Should have ratcheted forward!") except DuplicateMessageException as dme: # good pass plaintextFromAlice2 = bobGroupCipher.decrypt(ciphertextFromAlice2) plaintextFromAlice3 = bobGroupCipher.decrypt(ciphertextFromAlice3) self.assertEqual(plaintextFromAlice,"smert ze smert") self.assertEqual(plaintextFromAlice2, "smert ze smert2") self.assertEqual(plaintextFromAlice3, "smert ze smert3") def test_outOfOrder(self): aliceStore = InMemorySenderKeyStore(); bobStore = InMemorySenderKeyStore(); aliceSessionBuilder = GroupSessionBuilder(aliceStore) bobSessionBuilder = GroupSessionBuilder(bobStore) aliceGroupCipher = GroupCipher(aliceStore, "groupWithBobInIt") bobGroupCipher = GroupCipher(bobStore, "groupWithBobInIt::aliceUserName") aliceGroupCipher = GroupCipher(aliceStore, GROUP_SENDER) bobGroupCipher = GroupCipher(bobStore, GROUP_SENDER); sentAliceDistributionMessage = aliceSessionBuilder.create(GROUP_SENDER); receivedAliceDistributionMessage = SenderKeyDistributionMessage(serialized = sentAliceDistributionMessage.serialize()); bobSessionBuilder.process(GROUP_SENDER, receivedAliceDistributionMessage) ciphertexts = [] for i in range(0, 100): ciphertexts.append(aliceGroupCipher.encrypt("up the punks")) while len(ciphertexts) > 0: index = KeyHelper.getRandomSequence(2147483647) % len(ciphertexts) ciphertext = ciphertexts.pop(index) plaintext = bobGroupCipher.decrypt(ciphertext) self.assertEqual(plaintext, "up the punks") def test_encryptNoSession(self): aliceStore = InMemorySenderKeyStore() aliceGroupCipher = GroupCipher(aliceStore, "groupWithBobInIt") try: aliceGroupCipher.encrypt("up the punks") raise AssertionError("Should have failed!") except NoSessionException as nse: # good passpython-axolotl-0.1.39/axolotl/tests/groups/inmemorysenderkeystore.py0000644000175000017500000000105613064436211026410 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ...groups.state.senderkeystore import SenderKeyStore from ...groups.state.senderkeyrecord import SenderKeyRecord class InMemorySenderKeyStore(SenderKeyStore): def __init__(self): self.store = {} def storeSenderKey(self, senderKeyName, senderKeyRecord): self.store[senderKeyName] = senderKeyRecord def loadSenderKey(self, senderKeyName): if senderKeyName in self.store: return SenderKeyRecord(serialized=self.store[senderKeyName].serialize()) return SenderKeyRecord() python-axolotl-0.1.39/axolotl/tests/inmemoryaxolotlstore.py0000644000175000017500000000532713064436211024567 0ustar tarektarek00000000000000# -*- coding: utf8 -*- from ..state.axolotlstore import AxolotlStore from .inmemoryidentitykeystore import InMemoryIdentityKeyStore from .inmemoryprekeystore import InMemoryPreKeyStore from .inmemorysessionstore import InMemorySessionStore from .inmemorysignedprekeystore import InMemorySignedPreKeyStore class InMemoryAxolotlStore(AxolotlStore): def __init__(self): self.identityKeyStore = InMemoryIdentityKeyStore() self.preKeyStore = InMemoryPreKeyStore() self.signedPreKeyStore = InMemorySignedPreKeyStore() self.sessionStore = InMemorySessionStore() def getIdentityKeyPair(self): return self.identityKeyStore.getIdentityKeyPair() def getLocalRegistrationId(self): return self.identityKeyStore.getLocalRegistrationId() def saveIdentity(self, recepientId, identityKey): self.identityKeyStore.saveIdentity(recepientId, identityKey) def isTrustedIdentity(self, recepientId, identityKey): return self.identityKeyStore.isTrustedIdentity(recepientId, identityKey) def loadPreKey(self, preKeyId): return self.preKeyStore.loadPreKey(preKeyId) def storePreKey(self, preKeyId, preKeyRecord): self.preKeyStore.storePreKey(preKeyId, preKeyRecord) def containsPreKey(self, preKeyId): return self.preKeyStore.containsPreKey(preKeyId) def removePreKey(self, preKeyId): self.preKeyStore.removePreKey(preKeyId) def loadSession(self, recepientId, deviceId): return self.sessionStore.loadSession(recepientId, deviceId) def getSubDeviceSessions(self, recepientId): return self.sessionStore.getSubDeviceSessions(recepientId) def storeSession(self, recepientId, deviceId, sessionRecord): self.sessionStore.storeSession(recepientId, deviceId, sessionRecord) def containsSession(self, recepientId, deviceId): return self.sessionStore.containsSession(recepientId, deviceId) def deleteSession(self, recepientId, deviceId): self.sessionStore.deleteSession(recepientId, deviceId) def deleteAllSessions(self, recepientId): self.sessionStore.deleteAllSessions(recepientId) def loadSignedPreKey(self, signedPreKeyId): return self.signedPreKeyStore.loadSignedPreKey(signedPreKeyId) def loadSignedPreKeys(self): return self.signedPreKeyStore.loadSignedPreKeys() def storeSignedPreKey(self, signedPreKeyId, signedPreKeyRecord): self.signedPreKeyStore.storeSignedPreKey(signedPreKeyId, signedPreKeyRecord) def containsSignedPreKey(self, signedPreKeyId): return self.signedPreKeyStore.containsSignedPreKey(signedPreKeyId) def removeSignedPreKey(self, signedPreKeyId): return self.signedPreKeyStore.containsSignedPreKey() python-axolotl-0.1.39/axolotl/legacymessageexception.py0000644000175000017500000000011413064436211023623 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class LegacyMessageException(Exception): pass python-axolotl-0.1.39/axolotl/groups/0000755000175000017500000000000013064436273020054 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/groups/groupcipher.py0000644000175000017500000001171213064436211022747 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import sys from ..invalidkeyidexception import InvalidKeyIdException from ..invalidkeyexception import InvalidKeyException from ..invalidmessageexception import InvalidMessageException from ..duplicatemessagexception import DuplicateMessageException from ..nosessionexception import NoSessionException from ..protocol.senderkeymessage import SenderKeyMessage from ..sessioncipher import AESCipher from ..groups.state.senderkeystore import SenderKeyStore if sys.version_info >= (3, 0): unicode = str class GroupCipher: def __init__(self, senderKeyStore, senderKeyName): """ :type senderKeyStore: SenderKeyStore :type senderKeyName: SenderKeyName """ self.senderKeyStore = senderKeyStore self.senderKeyName = senderKeyName def encrypt(self, paddedPlaintext): """ :type paddedPlaintext: str """ # TODO: make this less ugly and python 2 and 3 compatible # paddedMessage = bytearray(paddedMessage.encode() if (sys.version_info >= (3, 0) and not type(paddedMessage) in (bytes, bytearray)) or type(paddedMessage) is unicode else paddedMessage) if (sys.version_info >= (3, 0) and not type(paddedPlaintext) in (bytes, bytearray)) or type(paddedPlaintext) is unicode: paddedPlaintext = bytearray(paddedPlaintext.encode()) else: paddedPlaintext = bytearray(paddedPlaintext) try: record = self.senderKeyStore.loadSenderKey(self.senderKeyName) senderKeyState = record.getSenderKeyState() senderKey = senderKeyState.getSenderChainKey().getSenderMessageKey() ciphertext = self.getCipherText(senderKey.getIv(), senderKey.getCipherKey(), paddedPlaintext) senderKeyMessage = SenderKeyMessage(senderKeyState.getKeyId(), senderKey.getIteration(), ciphertext, senderKeyState.getSigningKeyPrivate()) senderKeyState.setSenderChainKey(senderKeyState.getSenderChainKey().getNext()) self.senderKeyStore.storeSenderKey(self.senderKeyName, record) return senderKeyMessage.serialize() except InvalidKeyIdException as e: raise NoSessionException(e) def decrypt(self, senderKeyMessageBytes): """ :type senderKeyMessageBytes: bytearray """ try: record = self.senderKeyStore.loadSenderKey(self.senderKeyName) if record.isEmpty(): raise NoSessionException("No sender key for: %s" % self.senderKeyName) senderKeyMessage = SenderKeyMessage(serialized = bytes(senderKeyMessageBytes)) senderKeyState = record.getSenderKeyState(senderKeyMessage.getKeyId()) senderKeyMessage.verifySignature(senderKeyState.getSigningKeyPublic()) senderKey = self.getSenderKey(senderKeyState, senderKeyMessage.getIteration()) plaintext = self.getPlainText(senderKey.getIv(), senderKey.getCipherKey(), senderKeyMessage.getCipherText()) self.senderKeyStore.storeSenderKey(self.senderKeyName, record) return plaintext except (InvalidKeyException, InvalidKeyIdException) as e: raise InvalidMessageException(e) def getSenderKey(self, senderKeyState, iteration): senderChainKey = senderKeyState.getSenderChainKey() if senderChainKey.getIteration() > iteration: if senderKeyState.hasSenderMessageKey(iteration): return senderKeyState.removeSenderMessageKey(iteration) else: raise DuplicateMessageException("Received message with old counter: %s, %s" % (senderChainKey.getIteration(), iteration)) if senderChainKey.getIteration() - iteration > 2000: raise InvalidMessageException("Over 2000 messages into the future!") while senderChainKey.getIteration() < iteration: senderKeyState.addSenderMessageKey(senderChainKey.getSenderMessageKey()) senderChainKey = senderChainKey.getNext() senderKeyState.setSenderChainKey(senderChainKey.getNext()) return senderChainKey.getSenderMessageKey() def getPlainText(self, iv, key, ciphertext): """ :type iv: bytearray :type key: bytearray :type ciphertext: bytearray """ try: cipher = AESCipher(key, iv) plaintext = cipher.decrypt(ciphertext) if sys.version_info >= (3, 0): return plaintext.decode() return plaintext except Exception as e: raise InvalidMessageException(e) def getCipherText(self, iv, key, plaintext): """ :type iv: bytearray :type key: bytearray :type plaintext: bytearray """ cipher = AESCipher(key, iv) return cipher.encrypt(bytes(plaintext))python-axolotl-0.1.39/axolotl/groups/__init__.py0000644000175000017500000000003013064436211022146 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- python-axolotl-0.1.39/axolotl/groups/ratchet/0000755000175000017500000000000013064436273021506 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/groups/ratchet/sendermessagekey.py0000644000175000017500000000130613064436211025406 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ...kdf.hkdfv3 import HKDFv3 from ...util.byteutil import ByteUtil class SenderMessageKey: def __init__(self, iteration, seed): """ :type iteration: int :type seed: bytearray """ derivative = HKDFv3().deriveSecrets(seed, "WhisperGroup".encode(), 48) parts = ByteUtil.split(derivative, 16, 32) self.iteration = iteration self.seed = seed self.iv = parts[0] self.cipherKey = parts[1] def getIteration(self): return self.iteration def getIv(self): return self.iv def getCipherKey(self): return self.cipherKey def getSeed(self): return self.seed python-axolotl-0.1.39/axolotl/groups/ratchet/__init__.py0000644000175000017500000000003013064436211023600 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- python-axolotl-0.1.39/axolotl/groups/ratchet/senderchainkey.py0000644000175000017500000000167013064436211025050 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import hashlib import hmac from .sendermessagekey import SenderMessageKey class SenderChainKey: MESSAGE_KEY_SEED = bytearray([0x01]) CHAIN_KEY_SEED = bytearray([0x02]) def __init__(self, iteration, chainKey): """ :type iteration: int :type chainKey: bytearray """ self.iteration = iteration self.chainKey = chainKey def getIteration(self): return self.iteration def getSenderMessageKey(self): return SenderMessageKey(self.iteration, self.getDerivative(self.__class__.MESSAGE_KEY_SEED, self.chainKey)) def getNext(self): return SenderChainKey(self.iteration + 1, self.getDerivative(self.__class__.CHAIN_KEY_SEED, self.chainKey)) def getSeed(self): return self.chainKey def getDerivative(self, seed, key): mac = hmac.new(bytes(key), bytes(seed), digestmod=hashlib.sha256) return mac.digest() python-axolotl-0.1.39/axolotl/groups/groupsessionbuilder.py0000644000175000017500000000420113064436211024522 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ..protocol.senderkeydistributionmessage import SenderKeyDistributionMessage from ..invalidkeyidexception import InvalidKeyIdException from ..invalidkeyexception import InvalidKeyException from ..util.keyhelper import KeyHelper class GroupSessionBuilder: def __init__(self, senderKeyStore): self.senderKeyStore = senderKeyStore def process(self, senderKeyName, senderKeyDistributionMessage): """ :type senderKeyName: SenderKeyName :type senderKeyDistributionMessage: SenderKeyDistributionMessage """ senderKeyRecord = self.senderKeyStore.loadSenderKey(senderKeyName) senderKeyRecord.addSenderKeyState(senderKeyDistributionMessage.getId(), senderKeyDistributionMessage.getIteration(), senderKeyDistributionMessage.getChainKey(), senderKeyDistributionMessage.getSignatureKey()) self.senderKeyStore.storeSenderKey(senderKeyName, senderKeyRecord) def create(self, senderKeyName): """ :type senderKeyName: SenderKeyName """ try: senderKeyRecord = self.senderKeyStore.loadSenderKey(senderKeyName); if senderKeyRecord.isEmpty() : senderKeyRecord.setSenderKeyState(KeyHelper.generateSenderKeyId(), 0, KeyHelper.generateSenderKey(), KeyHelper.generateSenderSigningKey()); self.senderKeyStore.storeSenderKey(senderKeyName, senderKeyRecord); state = senderKeyRecord.getSenderKeyState(); return SenderKeyDistributionMessage(state.getKeyId(), state.getSenderChainKey().getIteration(), state.getSenderChainKey().getSeed(), state.getSigningKeyPublic()); except (InvalidKeyException, InvalidKeyIdException) as e: raise AssertionError(e) python-axolotl-0.1.39/axolotl/groups/senderkeyname.py0000644000175000017500000000125113064436211023247 0ustar tarektarek00000000000000class SenderKeyName(object): def __init__(self, groupId, senderAxolotlAddress): self.groupId = groupId self.sender = senderAxolotlAddress def getGroupId(self): return self.groupId def getSender(self): return self.sender def serialize(self): return "%s::%s::%s" % (self.groupId, self.sender.getName(), self.sender.getDeviceId()) def __eq__(self, other): if other is None: return False if other.__class__ != SenderKeyName: return False return self.groupId == other.getGroupId() and self.sender == other.getSender() def __hash__(self): return hash(self.groupId) ^ hash(self.sender) python-axolotl-0.1.39/axolotl/groups/state/0000755000175000017500000000000013064436273021174 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/groups/state/__init__.py0000644000175000017500000000003013064436211023266 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- python-axolotl-0.1.39/axolotl/groups/state/senderkeystate.py0000644000175000017500000000764113064436211024600 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ...state import storageprotos_pb2 as storageprotos from ..ratchet.senderchainkey import SenderChainKey from ..ratchet.sendermessagekey import SenderMessageKey from ...ecc.curve import Curve class SenderKeyState: def __init__(self, id=None, iteration=None, chainKey=None, signatureKeyPublic=None, signatureKeyPrivate=None, signatureKeyPair=None, senderKeyStateStructure=None): """ :type id: int :type iteration: int :type chainKey: bytearray :type signatureKeyPublic: ECPublicKey :type signatureKeyPrivate: ECPrivateKey :type signatureKeyPair: ECKeyPair :type senderKeyStateStructure: SenderKeyStateStructure """ assert (bool(id) and bool(iteration) and bool(chainKey)) or \ (bool(senderKeyStateStructure) ^ bool(signatureKeyPublic or signatureKeyPair)) or \ (bool(signatureKeyPublic) ^ bool(signatureKeyPair)), "Missing required arguments" if senderKeyStateStructure: self.senderKeyStateStructure = senderKeyStateStructure else: if signatureKeyPair: signatureKeyPublic = signatureKeyPair.getPublicKey() signatureKeyPrivate = signatureKeyPair.getPrivateKey() self.senderKeyStateStructure = storageprotos.SenderKeyStateStructure() senderChainKeyStructure = self.senderKeyStateStructure.SenderChainKey() senderChainKeyStructure.iteration = iteration senderChainKeyStructure.seed = chainKey self.senderKeyStateStructure.senderChainKey.MergeFrom(senderChainKeyStructure) signingKeyStructure = self.senderKeyStateStructure.SenderSigningKey() signingKeyStructure.public = signatureKeyPublic.serialize() if signatureKeyPrivate: signingKeyStructure.private = signatureKeyPrivate.serialize() self.senderKeyStateStructure.senderKeyId = id self.senderChainKey = senderChainKeyStructure self.senderKeyStateStructure.senderSigningKey.CopyFrom(signingKeyStructure) def getKeyId(self): return self.senderKeyStateStructure.senderKeyId def getSenderChainKey(self): return SenderChainKey(self.senderKeyStateStructure.senderChainKey.iteration, bytearray(self.senderKeyStateStructure.senderChainKey.seed)) def setSenderChainKey(self, chainKey): self.senderKeyStateStructure.senderChainKey.iteration = chainKey.getIteration() self.senderKeyStateStructure.senderChainKey.seed = chainKey.getSeed() def getSigningKeyPublic(self): return Curve.decodePoint(bytearray(self.senderKeyStateStructure.senderSigningKey.public), 0) def getSigningKeyPrivate(self): return Curve.decodePrivatePoint(self.senderKeyStateStructure.senderSigningKey.private) def hasSenderMessageKey(self, iteration): for senderMessageKey in self.senderKeyStateStructure.senderMessageKeys: if senderMessageKey.iteration == iteration: return True return False def addSenderMessageKey(self, senderMessageKey): smk = self.senderKeyStateStructure.SenderMessageKey() smk.iteration = senderMessageKey.iteration smk.seed = senderMessageKey.seed self.senderKeyStateStructure.senderMessageKeys.extend([smk]) def removeSenderMessageKey(self, iteration): keys = self.senderKeyStateStructure.senderMessageKeys result = None for i in range(0, len(keys)): senderMessageKey = keys[i] if senderMessageKey.iteration == iteration: result = senderMessageKey del keys[i] break if result is not None: return SenderMessageKey(result.iteration, bytearray(result.seed)) return None def getStructure(self): return self.senderKeyStateStructure python-axolotl-0.1.39/axolotl/groups/state/senderkeystore.py0000644000175000017500000000063113064436211024604 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import abc class SenderKeyStore(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def storeSenderKey(self, senderKeyId, senderKeyRecord): """ :type senderKeyId: str :type senderKeyRecord: SenderKeyRecord """ @abc.abstractmethod def loadSenderKey(self, senderKeyId): """ :type senderKeyId: str """ python-axolotl-0.1.39/axolotl/groups/state/senderkeyrecord.py0000644000175000017500000000404413064436211024730 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from ...state.storageprotos_pb2 import SenderKeyRecordStructure from .senderkeystate import SenderKeyState from ...invalidkeyidexception import InvalidKeyIdException class SenderKeyRecord: def __init__(self, serialized=None): self.senderKeyStates = [] if serialized: senderKeyRecordStructure = SenderKeyRecordStructure() senderKeyRecordStructure.ParseFromString(serialized) for structure in senderKeyRecordStructure.senderKeyStates: self.senderKeyStates.append(SenderKeyState(senderKeyStateStructure=structure)) def isEmpty(self): return len(self.senderKeyStates) == 0 def getSenderKeyState(self, keyId=None): if keyId is None: if len(self.senderKeyStates): return self.senderKeyStates[0] else: raise InvalidKeyIdException("No key state in record") else: for state in self.senderKeyStates: if state.getKeyId() == keyId: return state raise InvalidKeyIdException("No keys for: %s" % keyId) def addSenderKeyState(self, id, iteration, chainKey, signatureKey): """ :type id: int :type iteration: int :type chainKey: bytearray :type signatureKey: ECPublicKey """ self.senderKeyStates.append(SenderKeyState(id, iteration, chainKey, signatureKey)) def setSenderKeyState(self, id, iteration, chainKey, signatureKey): """ :type id: int :type iteration: int :type chainKey: bytearray :type signatureKey: ECKeyPair """ del self.senderKeyStates[:] self.senderKeyStates.append(SenderKeyState(id, iteration, chainKey, signatureKeyPair=signatureKey)) def serialize(self): recordStructure = SenderKeyRecordStructure() for senderKeyState in self.senderKeyStates: recordStructure.senderKeyStates.extend([senderKeyState.getStructure()]) return recordStructure.SerializeToString()python-axolotl-0.1.39/axolotl/axolotladdress.py0000644000175000017500000000115513064436211022131 0ustar tarektarek00000000000000class AxolotlAddress(object): def __init__(self, name, deviceId): self.name = name self.deviceId = deviceId def getName(self): return self.name def getDeviceId(self): return self.deviceId def __str__(self): return "%s;%s" % (self.name, self.deviceId) def __eq__(self, other): if other is None: return False if other.__class__ != AxolotlAddress: return False return self.name == other.getName() and self.deviceId == other.getDeviceId() def __hash__(self): return hash(self.name) ^ self.deviceId python-axolotl-0.1.39/axolotl/state/0000755000175000017500000000000013064436273017655 5ustar tarektarek00000000000000python-axolotl-0.1.39/axolotl/state/prekeybundle.py0000644000175000017500000000217613064436211022716 0ustar tarektarek00000000000000# -*- cosing: utf-8 -*- class PreKeyBundle: def __init__(self, registrationId, deviceId, preKeyId, ECPublicKey_preKeyPublic, signedPreKeyId, ECPublicKey_signedPreKeyPublic, signedPreKeySignature, identityKey): self.registrationId = registrationId self.deviceId = deviceId self.preKeyId = preKeyId self.preKeyPublic = ECPublicKey_preKeyPublic self.signedPreKeyId = signedPreKeyId self.signedPreKeyPublic = ECPublicKey_signedPreKeyPublic self.signedPreKeySignature = signedPreKeySignature self.identityKey = identityKey def getDeviceId(self): return self.deviceId def getPreKeyId(self): return self.preKeyId def getPreKey(self): return self.preKeyPublic def getSignedPreKeyId(self): return self.signedPreKeyId def getSignedPreKey(self): return self.signedPreKeyPublic def getSignedPreKeySignature(self): return self.signedPreKeySignature def getIdentityKey(self): return self.identityKey def getRegistrationId(self): return self.registrationId python-axolotl-0.1.39/axolotl/state/axolotlstore.py0000644000175000017500000000050713064436211022760 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import abc from .identitykeystore import IdentityKeyStore from .prekeystore import PreKeyStore from .sessionstore import SessionStore from .signedprekeystore import SignedPreKeyStore class AxolotlStore(IdentityKeyStore, PreKeyStore, SignedPreKeyStore, SessionStore): __metaclass__ = abc.ABCMeta python-axolotl-0.1.39/axolotl/state/sessionstore.py0000644000175000017500000000120313064436211022753 0ustar tarektarek00000000000000# -*- cosing: utf-8 -*- import abc class SessionStore(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def loadSession(self, recepientId, deviceId): pass @abc.abstractmethod def getSubDeviceSessions(self, recepientId): pass @abc.abstractmethod def storeSession(self, recepientId, deviceId, sessionRecord): pass @abc.abstractmethod def containsSession(self, recepientId, deviceId): pass @abc.abstractmethod def deleteSession(self, recepientId, deviceId): pass @abc.abstractmethod def deleteAllSessions(self, recepientId): pass python-axolotl-0.1.39/axolotl/state/__init__.py0000644000175000017500000000003013064436211021747 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- python-axolotl-0.1.39/axolotl/state/identitykeystore.py0000644000175000017500000000066713064436211023647 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import abc class IdentityKeyStore(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def getIdentityKeyPair(self): pass @abc.abstractmethod def getLocalRegistrationId(self): pass @abc.abstractmethod def saveIdentity(self, recepientId, identityKey): pass @abc.abstractmethod def isTrustedIdentity(self, recepientId, identityKey): pass python-axolotl-0.1.39/axolotl/state/prekeystore.py0000644000175000017500000000063613064436211022600 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import abc class PreKeyStore(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def loadPreKey(self, preKeyId): pass @abc.abstractmethod def storePreKey(self, preKeyId, preKeyRecord): pass @abc.abstractmethod def containsPreKey(self, preKeyId): pass @abc.abstractmethod def removePreKey(self, preKeyId): pass python-axolotl-0.1.39/axolotl/state/sessionrecord.py0000644000175000017500000000433113064436211023102 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from . import storageprotos_pb2 as storageprotos from .sessionstate import SessionState class SessionRecord: ARCHIVED_STATES_MAX_LENGTH = 40 def __init__(self, sessionState=None, serialized=None): """ :type sessionState: SessionState :type serialized: str """ self.previousStates = [] if sessionState: self.sessionState = sessionState self.fresh = False elif serialized: record = storageprotos.RecordStructure() record.ParseFromString(serialized) self.sessionState = SessionState(record.currentSession) self.fresh = False for previousStructure in record.previousSessions: self.previousStates.append(SessionState(previousStructure)) else: self.fresh = True self.sessionState = SessionState() def hasSessionState(self, version, aliceBaseKey): if self.sessionState.getSessionVersion() == version and aliceBaseKey == self.sessionState.getAliceBaseKey(): return True for state in self.previousStates: if state.getSessionVersion() == version and aliceBaseKey == state.getAliceBaseKey(): return True return False def getSessionState(self): return self.sessionState def getPreviousSessionStates(self): return self.previousStates def isFresh(self): return self.fresh def archiveCurrentState(self): self.promoteState(SessionState()) def promoteState(self, promotedState): self.previousStates.insert(0, self.sessionState) self.sessionState = promotedState if len(self.previousStates) > self.__class__.ARCHIVED_STATES_MAX_LENGTH: self.previousStates.pop() def setState(self, sessionState): self.sessionState = sessionState def serialize(self): previousStructures = [previousState.getStructure() for previousState in self.previousStates] record = storageprotos.RecordStructure() record.currentSession.MergeFrom(self.sessionState.getStructure()) record.previousSessions.extend(previousStructures) return record.SerializeToString() python-axolotl-0.1.39/axolotl/state/sessionstate.py0000644000175000017500000002756213064436211022757 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from . import storageprotos_pb2 as storageprotos from ..identitykeypair import IdentityKey, IdentityKeyPair from ..ratchet.rootkey import RootKey from ..kdf.hkdf import HKDF from ..ecc.curve import Curve from ..ecc.eckeypair import ECKeyPair from ..ratchet.chainkey import ChainKey from ..kdf.messagekeys import MessageKeys class SessionState: def __init__(self, session=None): if session is None: self.sessionStructure = storageprotos.SessionStructure() elif session.__class__ == SessionState: self.sessionStructure = storageprotos.SessionStructure() self.sessionStructure.CopyFrom(session.sessionStructure) else: self.sessionStructure = session def getStructure(self): return self.sessionStructure def getAliceBaseKey(self): return self.sessionStructure.aliceBaseKey def setAliceBaseKey(self, aliceBaseKey): self.sessionStructure.aliceBaseKey = aliceBaseKey def setSessionVersion(self, version): self.sessionStructure.sessionVersion = version def getSessionVersion(self): sessionVersion = self.sessionStructure.sessionVersion return 2 if sessionVersion == 0 else sessionVersion def setRemoteIdentityKey(self, identityKey): self.sessionStructure.remoteIdentityPublic = identityKey.serialize() def setLocalIdentityKey(self, identityKey): self.sessionStructure.localIdentityPublic = identityKey.serialize() def getRemoteIdentityKey(self): if self.sessionStructure.remoteIdentityPublic is None: return None return IdentityKey(self.sessionStructure.remoteIdentityPublic, 0) def getLocalIdentityKey(self): return IdentityKey(self.sessionStructure.localIdentityPublic, 0) def getPreviousCounter(self): return self.sessionStructure.previousCounter def setPreviousCounter(self, previousCounter): self.sessionStructure.previousCounter = previousCounter def getRootKey(self): return RootKey(HKDF.createFor(self.getSessionVersion()), self.sessionStructure.rootKey) def setRootKey(self, rootKey): self.sessionStructure.rootKey = rootKey.getKeyBytes() def getSenderRatchetKey(self): return Curve.decodePoint(bytearray(self.sessionStructure.senderChain.senderRatchetKey), 0) def getSenderRatchetKeyPair(self): publicKey = self.getSenderRatchetKey() privateKey = Curve.decodePrivatePoint(self.sessionStructure.senderChain.senderRatchetKeyPrivate) return ECKeyPair(publicKey, privateKey) def hasReceiverChain(self, ECPublickKey_senderEphemeral): return self.getReceiverChain(ECPublickKey_senderEphemeral) is not None def hasSenderChain(self): return self.sessionStructure.HasField("senderChain") def getReceiverChain(self, ECPublickKey_senderEphemeral): receiverChains = self.sessionStructure.receiverChains index = 0 for receiverChain in receiverChains: chainSenderRatchetKey = Curve.decodePoint(bytearray(receiverChain.senderRatchetKey), 0) if chainSenderRatchetKey == ECPublickKey_senderEphemeral: return (receiverChain, index) index += 1 def getReceiverChainKey(self, ECPublicKey_senderEphemeral): receiverChainAndIndex = self.getReceiverChain(ECPublicKey_senderEphemeral) receiverChain = receiverChainAndIndex[0] if receiverChain is None: return None return ChainKey(HKDF.createFor(self.getSessionVersion()), receiverChain.chainKey.key, receiverChain.chainKey.index) def addReceiverChain(self, ECPublickKey_senderRatchetKey, chainKey): senderRatchetKey = ECPublickKey_senderRatchetKey chain = storageprotos.SessionStructure.Chain() chain.senderRatchetKey = senderRatchetKey.serialize() chain.chainKey.key = chainKey.getKey() chain.chainKey.index = chainKey.getIndex() self.sessionStructure.receiverChains.extend([chain]) if len(self.sessionStructure.receiverChains) > 5: del self.sessionStructure.receiverChains[0] def setSenderChain(self, ECKeyPair_senderRatchetKeyPair, chainKey): senderRatchetKeyPair = ECKeyPair_senderRatchetKeyPair # TODO: This is never used, maybe a bug? senderChain = storageprotos.SessionStructure.Chain() self.sessionStructure.senderChain.senderRatchetKey = senderRatchetKeyPair.getPublicKey().serialize() self.sessionStructure.senderChain.senderRatchetKeyPrivate = senderRatchetKeyPair.getPrivateKey().serialize() self.sessionStructure.senderChain.chainKey.key = chainKey.key self.sessionStructure.senderChain.chainKey.index = chainKey.index def getSenderChainKey(self): chainKeyStructure = self.sessionStructure.senderChain.chainKey return ChainKey(HKDF.createFor(self.getSessionVersion()), chainKeyStructure.key, chainKeyStructure.index) def setSenderChainKey(self, ChainKey_nextChainKey): nextChainKey = ChainKey_nextChainKey self.sessionStructure.senderChain.chainKey.key = nextChainKey.getKey() self.sessionStructure.senderChain.chainKey.index = nextChainKey.getIndex() def hasMessageKeys(self, ECPublickKey_senderEphemeral, counter): senderEphemeral = ECPublickKey_senderEphemeral chainAndIndex = self.getReceiverChain(senderEphemeral) chain = chainAndIndex[0] if chain is None: return False messageKeyList = chain.messageKeys for messageKey in messageKeyList: if messageKey.index == counter: return True return False def removeMessageKeys(self, ECPublicKey_senderEphemeral, counter): senderEphemeral = ECPublicKey_senderEphemeral chainAndIndex = self.getReceiverChain(senderEphemeral) chain = chainAndIndex[0] if chain is None: return None messageKeyList = chain.messageKeys result = None for i in range(0, len(messageKeyList)): messageKey = messageKeyList[i] if messageKey.index == counter: result = MessageKeys(messageKey.cipherKey, messageKey.macKey, messageKey.iv, messageKey.index) del messageKeyList[i] break self.sessionStructure.receiverChains[chainAndIndex[1]].CopyFrom(chain) return result def setMessageKeys(self, ECPublicKey_senderEphemeral, messageKeys): senderEphemeral = ECPublicKey_senderEphemeral chainAndIndex = self.getReceiverChain(senderEphemeral) chain = chainAndIndex[0] messageKeyStructure = chain.messageKeys.add() # storageprotos.SessionStructure.Chain.MessageKey() messageKeyStructure.cipherKey = messageKeys.getCipherKey() messageKeyStructure.macKey = messageKeys.getMacKey() messageKeyStructure.index = messageKeys.getCounter() messageKeyStructure.iv = messageKeys.getIv() # chain.messageKeys.append(messageKeyStructure) self.sessionStructure.receiverChains[chainAndIndex[1]].CopyFrom(chain) def setReceiverChainKey(self, ECPublicKey_senderEphemeral, chainKey): senderEphemeral = ECPublicKey_senderEphemeral chainAndIndex = self.getReceiverChain(senderEphemeral) chain = chainAndIndex[0] chain.chainKey.key = chainKey.getKey() chain.chainKey.index = chainKey.getIndex() # self.sessionStructure.receiverChains[chainAndIndex[1]].ClearField() self.sessionStructure.receiverChains[chainAndIndex[1]].CopyFrom(chain) def setPendingKeyExchange(self, sequence, ourBaseKey, ourRatchetKey, ourIdentityKey): """ :type sequence: int :type ourBaseKey: ECKeyPair :type ourRatchetKey: ECKeyPair :type ourIdentityKey: IdentityKeyPair """ structure = self.sessionStructure.PendingKeyExchange() structure.sequence = sequence structure.localBaseKey = ourBaseKey.getPublicKey().serialize() structure.localBaseKeyPrivate = ourBaseKey.getPrivateKey().serialize() structure.localRatchetKey = ourRatchetKey.getPublicKey().serialize() structure.localRatchetKeyPrivate = ourRatchetKey.getPrivateKey().serialize() structure.localIdentityKey = ourIdentityKey.getPublicKey().serialize() structure.localIdentityKeyPrivate = ourIdentityKey.getPrivateKey().serialize() self.sessionStructure.pendingKeyExchange.MergeFrom(structure) def getPendingKeyExchangeSequence(self): return self.sessionStructure.pendingKeyExchange.sequence def getPendingKeyExchangeBaseKey(self): publicKey = Curve.decodePoint(bytearray(self.sessionStructure.pendingKeyExchange.localBaseKey), 0) privateKey = Curve.decodePrivatePoint(self.sessionStructure.pendingKeyExchange.localBaseKeyPrivate) return ECKeyPair(publicKey, privateKey) def getPendingKeyExchangeRatchetKey(self): publicKey = Curve.decodePoint(bytearray(self.sessionStructure.pendingKeyExchange.localRatchetKey), 0) privateKey = Curve.decodePrivatePoint(self.sessionStructure.pendingKeyExchange.localRatchetKeyPrivate) return ECKeyPair(publicKey, privateKey) def getPendingKeyExchangeIdentityKey(self): publicKey = IdentityKey(bytearray(self.sessionStructure.pendingKeyExchange.localIdentityKey), 0) privateKey = Curve.decodePrivatePoint(self.sessionStructure.pendingKeyExchange.localIdentityKeyPrivate) return IdentityKeyPair(publicKey, privateKey) def hasPendingKeyExchange(self): return self.sessionStructure.HasField("pendingKeyExchange") def setUnacknowledgedPreKeyMessage(self, preKeyId, signedPreKeyId, baseKey): """ :type preKeyId: int :type signedPreKeyId: int :type baseKey: ECPublicKey """ self.sessionStructure.pendingPreKey.signedPreKeyId = signedPreKeyId self.sessionStructure.pendingPreKey.baseKey = baseKey.serialize() if preKeyId is not None: self.sessionStructure.pendingPreKey.preKeyId = preKeyId def hasUnacknowledgedPreKeyMessage(self): return self.sessionStructure.HasField("pendingPreKey") def getUnacknowledgedPreKeyMessageItems(self): preKeyId = None if self.sessionStructure.pendingPreKey.HasField("preKeyId"): preKeyId = self.sessionStructure.pendingPreKey.preKeyId return SessionState.UnacknowledgedPreKeyMessageItems(preKeyId, self.sessionStructure.pendingPreKey.signedPreKeyId, Curve.decodePoint(bytearray(self.sessionStructure.pendingPreKey.baseKey), 0)) def clearUnacknowledgedPreKeyMessage(self): self.sessionStructure.ClearField("pendingPreKey") def setRemoteRegistrationId(self, registrationId): self.sessionStructure.remoteRegistrationId = registrationId def getRemoteRegistrationId(self, registrationId): return self.sessionStructure.remoteRegistrationId def setLocalRegistrationId(self, registrationId): self.sessionStructure.localRegistrationId = registrationId def getLocalRegistrationId(self): return self.sessionStructure.localRegistrationId def serialize(self): return self.sessionStructure.SerializeToString() class UnacknowledgedPreKeyMessageItems: def __init__(self, preKeyId, signedPreKeyId, baseKey): """ :type preKeyId: int :type signedPreKeyId: int :type baseKey: ECPublicKey """ self.preKeyId = preKeyId self.signedPreKeyId = signedPreKeyId self.baseKey = baseKey def getPreKeyId(self): return self.preKeyId def getSignedPreKeyId(self): return self.signedPreKeyId def getBaseKey(self): return self.baseKey python-axolotl-0.1.39/axolotl/state/storageprotos_pb2.py0000644000175000017500000011323613064436211023703 0ustar tarektarek00000000000000# Generated by the protocol buffer compiler. DO NOT EDIT! # source: LocalStorageProtocol.proto import sys _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='LocalStorageProtocol.proto', package='textsecure', serialized_pb=_b('\n\x1aLocalStorageProtocol.proto\x12\ntextsecure\"\xd3\x08\n\x10SessionStructure\x12\x16\n\x0esessionVersion\x18\x01 \x01(\r\x12\x1b\n\x13localIdentityPublic\x18\x02 \x01(\x0c\x12\x1c\n\x14remoteIdentityPublic\x18\x03 \x01(\x0c\x12\x0f\n\x07rootKey\x18\x04 \x01(\x0c\x12\x17\n\x0fpreviousCounter\x18\x05 \x01(\r\x12\x37\n\x0bsenderChain\x18\x06 \x01(\x0b\x32\".textsecure.SessionStructure.Chain\x12:\n\x0ereceiverChains\x18\x07 \x03(\x0b\x32\".textsecure.SessionStructure.Chain\x12K\n\x12pendingKeyExchange\x18\x08 \x01(\x0b\x32/.textsecure.SessionStructure.PendingKeyExchange\x12\x41\n\rpendingPreKey\x18\t \x01(\x0b\x32*.textsecure.SessionStructure.PendingPreKey\x12\x1c\n\x14remoteRegistrationId\x18\n \x01(\r\x12\x1b\n\x13localRegistrationId\x18\x0b \x01(\r\x12\x14\n\x0cneedsRefresh\x18\x0c \x01(\x08\x12\x14\n\x0c\x61liceBaseKey\x18\r \x01(\x0c\x1a\xb9\x02\n\x05\x43hain\x12\x18\n\x10senderRatchetKey\x18\x01 \x01(\x0c\x12\x1f\n\x17senderRatchetKeyPrivate\x18\x02 \x01(\x0c\x12=\n\x08\x63hainKey\x18\x03 \x01(\x0b\x32+.textsecure.SessionStructure.Chain.ChainKey\x12\x42\n\x0bmessageKeys\x18\x04 \x03(\x0b\x32-.textsecure.SessionStructure.Chain.MessageKey\x1a&\n\x08\x43hainKey\x12\r\n\x05index\x18\x01 \x01(\r\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x1aJ\n\nMessageKey\x12\r\n\x05index\x18\x01 \x01(\r\x12\x11\n\tcipherKey\x18\x02 \x01(\x0c\x12\x0e\n\x06macKey\x18\x03 \x01(\x0c\x12\n\n\x02iv\x18\x04 \x01(\x0c\x1a\xcd\x01\n\x12PendingKeyExchange\x12\x10\n\x08sequence\x18\x01 \x01(\r\x12\x14\n\x0clocalBaseKey\x18\x02 \x01(\x0c\x12\x1b\n\x13localBaseKeyPrivate\x18\x03 \x01(\x0c\x12\x17\n\x0flocalRatchetKey\x18\x04 \x01(\x0c\x12\x1e\n\x16localRatchetKeyPrivate\x18\x05 \x01(\x0c\x12\x18\n\x10localIdentityKey\x18\x07 \x01(\x0c\x12\x1f\n\x17localIdentityKeyPrivate\x18\x08 \x01(\x0c\x1aJ\n\rPendingPreKey\x12\x10\n\x08preKeyId\x18\x01 \x01(\r\x12\x16\n\x0esignedPreKeyId\x18\x03 \x01(\x05\x12\x0f\n\x07\x62\x61seKey\x18\x02 \x01(\x0c\"\x7f\n\x0fRecordStructure\x12\x34\n\x0e\x63urrentSession\x18\x01 \x01(\x0b\x32\x1c.textsecure.SessionStructure\x12\x36\n\x10previousSessions\x18\x02 \x03(\x0b\x32\x1c.textsecure.SessionStructure\"J\n\x15PreKeyRecordStructure\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\tpublicKey\x18\x02 \x01(\x0c\x12\x12\n\nprivateKey\x18\x03 \x01(\x0c\"v\n\x1bSignedPreKeyRecordStructure\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\tpublicKey\x18\x02 \x01(\x0c\x12\x12\n\nprivateKey\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x06\"A\n\x18IdentityKeyPairStructure\x12\x11\n\tpublicKey\x18\x01 \x01(\x0c\x12\x12\n\nprivateKey\x18\x02 \x01(\x0c\"\xb8\x03\n\x17SenderKeyStateStructure\x12\x13\n\x0bsenderKeyId\x18\x01 \x01(\r\x12J\n\x0esenderChainKey\x18\x02 \x01(\x0b\x32\x32.textsecure.SenderKeyStateStructure.SenderChainKey\x12N\n\x10senderSigningKey\x18\x03 \x01(\x0b\x32\x34.textsecure.SenderKeyStateStructure.SenderSigningKey\x12O\n\x11senderMessageKeys\x18\x04 \x03(\x0b\x32\x34.textsecure.SenderKeyStateStructure.SenderMessageKey\x1a\x31\n\x0eSenderChainKey\x12\x11\n\titeration\x18\x01 \x01(\r\x12\x0c\n\x04seed\x18\x02 \x01(\x0c\x1a\x33\n\x10SenderMessageKey\x12\x11\n\titeration\x18\x01 \x01(\r\x12\x0c\n\x04seed\x18\x02 \x01(\x0c\x1a\x33\n\x10SenderSigningKey\x12\x0e\n\x06public\x18\x01 \x01(\x0c\x12\x0f\n\x07private\x18\x02 \x01(\x0c\"X\n\x18SenderKeyRecordStructure\x12<\n\x0fsenderKeyStates\x18\x01 \x03(\x0b\x32#.textsecure.SenderKeyStateStructureB4\n#org.whispersystems.libaxolotl.stateB\rStorageProtos') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) _SESSIONSTRUCTURE_CHAIN_CHAINKEY = _descriptor.Descriptor( name='ChainKey', full_name='textsecure.SessionStructure.Chain.ChainKey', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='index', full_name='textsecure.SessionStructure.Chain.ChainKey.index', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='key', full_name='textsecure.SessionStructure.Chain.ChainKey.key', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=752, serialized_end=790, ) _SESSIONSTRUCTURE_CHAIN_MESSAGEKEY = _descriptor.Descriptor( name='MessageKey', full_name='textsecure.SessionStructure.Chain.MessageKey', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='index', full_name='textsecure.SessionStructure.Chain.MessageKey.index', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='cipherKey', full_name='textsecure.SessionStructure.Chain.MessageKey.cipherKey', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='macKey', full_name='textsecure.SessionStructure.Chain.MessageKey.macKey', index=2, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='iv', full_name='textsecure.SessionStructure.Chain.MessageKey.iv', index=3, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=792, serialized_end=866, ) _SESSIONSTRUCTURE_CHAIN = _descriptor.Descriptor( name='Chain', full_name='textsecure.SessionStructure.Chain', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='senderRatchetKey', full_name='textsecure.SessionStructure.Chain.senderRatchetKey', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='senderRatchetKeyPrivate', full_name='textsecure.SessionStructure.Chain.senderRatchetKeyPrivate', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='chainKey', full_name='textsecure.SessionStructure.Chain.chainKey', index=2, number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='messageKeys', full_name='textsecure.SessionStructure.Chain.messageKeys', index=3, number=4, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[_SESSIONSTRUCTURE_CHAIN_CHAINKEY, _SESSIONSTRUCTURE_CHAIN_MESSAGEKEY, ], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=553, serialized_end=866, ) _SESSIONSTRUCTURE_PENDINGKEYEXCHANGE = _descriptor.Descriptor( name='PendingKeyExchange', full_name='textsecure.SessionStructure.PendingKeyExchange', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='sequence', full_name='textsecure.SessionStructure.PendingKeyExchange.sequence', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='localBaseKey', full_name='textsecure.SessionStructure.PendingKeyExchange.localBaseKey', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='localBaseKeyPrivate', full_name='textsecure.SessionStructure.PendingKeyExchange.localBaseKeyPrivate', index=2, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='localRatchetKey', full_name='textsecure.SessionStructure.PendingKeyExchange.localRatchetKey', index=3, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='localRatchetKeyPrivate', full_name='textsecure.SessionStructure.PendingKeyExchange.localRatchetKeyPrivate', index=4, number=5, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='localIdentityKey', full_name='textsecure.SessionStructure.PendingKeyExchange.localIdentityKey', index=5, number=7, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='localIdentityKeyPrivate', full_name='textsecure.SessionStructure.PendingKeyExchange.localIdentityKeyPrivate', index=6, number=8, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=869, serialized_end=1074, ) _SESSIONSTRUCTURE_PENDINGPREKEY = _descriptor.Descriptor( name='PendingPreKey', full_name='textsecure.SessionStructure.PendingPreKey', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='preKeyId', full_name='textsecure.SessionStructure.PendingPreKey.preKeyId', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='signedPreKeyId', full_name='textsecure.SessionStructure.PendingPreKey.signedPreKeyId', index=1, number=3, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='baseKey', full_name='textsecure.SessionStructure.PendingPreKey.baseKey', index=2, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1076, serialized_end=1150, ) _SESSIONSTRUCTURE = _descriptor.Descriptor( name='SessionStructure', full_name='textsecure.SessionStructure', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='sessionVersion', full_name='textsecure.SessionStructure.sessionVersion', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='localIdentityPublic', full_name='textsecure.SessionStructure.localIdentityPublic', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='remoteIdentityPublic', full_name='textsecure.SessionStructure.remoteIdentityPublic', index=2, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='rootKey', full_name='textsecure.SessionStructure.rootKey', index=3, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='previousCounter', full_name='textsecure.SessionStructure.previousCounter', index=4, number=5, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='senderChain', full_name='textsecure.SessionStructure.senderChain', index=5, number=6, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='receiverChains', full_name='textsecure.SessionStructure.receiverChains', index=6, number=7, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='pendingKeyExchange', full_name='textsecure.SessionStructure.pendingKeyExchange', index=7, number=8, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='pendingPreKey', full_name='textsecure.SessionStructure.pendingPreKey', index=8, number=9, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='remoteRegistrationId', full_name='textsecure.SessionStructure.remoteRegistrationId', index=9, number=10, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='localRegistrationId', full_name='textsecure.SessionStructure.localRegistrationId', index=10, number=11, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='needsRefresh', full_name='textsecure.SessionStructure.needsRefresh', index=11, number=12, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='aliceBaseKey', full_name='textsecure.SessionStructure.aliceBaseKey', index=12, number=13, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[_SESSIONSTRUCTURE_CHAIN, _SESSIONSTRUCTURE_PENDINGKEYEXCHANGE, _SESSIONSTRUCTURE_PENDINGPREKEY, ], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=43, serialized_end=1150, ) _RECORDSTRUCTURE = _descriptor.Descriptor( name='RecordStructure', full_name='textsecure.RecordStructure', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='currentSession', full_name='textsecure.RecordStructure.currentSession', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='previousSessions', full_name='textsecure.RecordStructure.previousSessions', index=1, number=2, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1152, serialized_end=1279, ) _PREKEYRECORDSTRUCTURE = _descriptor.Descriptor( name='PreKeyRecordStructure', full_name='textsecure.PreKeyRecordStructure', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='id', full_name='textsecure.PreKeyRecordStructure.id', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='publicKey', full_name='textsecure.PreKeyRecordStructure.publicKey', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='privateKey', full_name='textsecure.PreKeyRecordStructure.privateKey', index=2, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1281, serialized_end=1355, ) _SIGNEDPREKEYRECORDSTRUCTURE = _descriptor.Descriptor( name='SignedPreKeyRecordStructure', full_name='textsecure.SignedPreKeyRecordStructure', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='id', full_name='textsecure.SignedPreKeyRecordStructure.id', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='publicKey', full_name='textsecure.SignedPreKeyRecordStructure.publicKey', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='privateKey', full_name='textsecure.SignedPreKeyRecordStructure.privateKey', index=2, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='signature', full_name='textsecure.SignedPreKeyRecordStructure.signature', index=3, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='timestamp', full_name='textsecure.SignedPreKeyRecordStructure.timestamp', index=4, number=5, type=6, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1357, serialized_end=1475, ) _IDENTITYKEYPAIRSTRUCTURE = _descriptor.Descriptor( name='IdentityKeyPairStructure', full_name='textsecure.IdentityKeyPairStructure', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='publicKey', full_name='textsecure.IdentityKeyPairStructure.publicKey', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='privateKey', full_name='textsecure.IdentityKeyPairStructure.privateKey', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1477, serialized_end=1542, ) _SENDERKEYSTATESTRUCTURE_SENDERCHAINKEY = _descriptor.Descriptor( name='SenderChainKey', full_name='textsecure.SenderKeyStateStructure.SenderChainKey', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='iteration', full_name='textsecure.SenderKeyStateStructure.SenderChainKey.iteration', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='seed', full_name='textsecure.SenderKeyStateStructure.SenderChainKey.seed', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1830, serialized_end=1879, ) _SENDERKEYSTATESTRUCTURE_SENDERMESSAGEKEY = _descriptor.Descriptor( name='SenderMessageKey', full_name='textsecure.SenderKeyStateStructure.SenderMessageKey', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='iteration', full_name='textsecure.SenderKeyStateStructure.SenderMessageKey.iteration', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='seed', full_name='textsecure.SenderKeyStateStructure.SenderMessageKey.seed', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1881, serialized_end=1932, ) _SENDERKEYSTATESTRUCTURE_SENDERSIGNINGKEY = _descriptor.Descriptor( name='SenderSigningKey', full_name='textsecure.SenderKeyStateStructure.SenderSigningKey', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='public', full_name='textsecure.SenderKeyStateStructure.SenderSigningKey.public', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='private', full_name='textsecure.SenderKeyStateStructure.SenderSigningKey.private', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1934, serialized_end=1985, ) _SENDERKEYSTATESTRUCTURE = _descriptor.Descriptor( name='SenderKeyStateStructure', full_name='textsecure.SenderKeyStateStructure', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='senderKeyId', full_name='textsecure.SenderKeyStateStructure.senderKeyId', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='senderChainKey', full_name='textsecure.SenderKeyStateStructure.senderChainKey', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='senderSigningKey', full_name='textsecure.SenderKeyStateStructure.senderSigningKey', index=2, number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( name='senderMessageKeys', full_name='textsecure.SenderKeyStateStructure.senderMessageKeys', index=3, number=4, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[_SENDERKEYSTATESTRUCTURE_SENDERCHAINKEY, _SENDERKEYSTATESTRUCTURE_SENDERMESSAGEKEY, _SENDERKEYSTATESTRUCTURE_SENDERSIGNINGKEY, ], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1545, serialized_end=1985, ) _SENDERKEYRECORDSTRUCTURE = _descriptor.Descriptor( name='SenderKeyRecordStructure', full_name='textsecure.SenderKeyRecordStructure', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( name='senderKeyStates', full_name='textsecure.SenderKeyRecordStructure.senderKeyStates', index=0, number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], options=None, is_extendable=False, extension_ranges=[], oneofs=[ ], serialized_start=1987, serialized_end=2075, ) _SESSIONSTRUCTURE_CHAIN_CHAINKEY.containing_type = _SESSIONSTRUCTURE_CHAIN _SESSIONSTRUCTURE_CHAIN_MESSAGEKEY.containing_type = _SESSIONSTRUCTURE_CHAIN _SESSIONSTRUCTURE_CHAIN.fields_by_name['chainKey'].message_type = _SESSIONSTRUCTURE_CHAIN_CHAINKEY _SESSIONSTRUCTURE_CHAIN.fields_by_name['messageKeys'].message_type = _SESSIONSTRUCTURE_CHAIN_MESSAGEKEY _SESSIONSTRUCTURE_CHAIN.containing_type = _SESSIONSTRUCTURE _SESSIONSTRUCTURE_PENDINGKEYEXCHANGE.containing_type = _SESSIONSTRUCTURE _SESSIONSTRUCTURE_PENDINGPREKEY.containing_type = _SESSIONSTRUCTURE _SESSIONSTRUCTURE.fields_by_name['senderChain'].message_type = _SESSIONSTRUCTURE_CHAIN _SESSIONSTRUCTURE.fields_by_name['receiverChains'].message_type = _SESSIONSTRUCTURE_CHAIN _SESSIONSTRUCTURE.fields_by_name['pendingKeyExchange'].message_type = _SESSIONSTRUCTURE_PENDINGKEYEXCHANGE _SESSIONSTRUCTURE.fields_by_name['pendingPreKey'].message_type = _SESSIONSTRUCTURE_PENDINGPREKEY _RECORDSTRUCTURE.fields_by_name['currentSession'].message_type = _SESSIONSTRUCTURE _RECORDSTRUCTURE.fields_by_name['previousSessions'].message_type = _SESSIONSTRUCTURE _SENDERKEYSTATESTRUCTURE_SENDERCHAINKEY.containing_type = _SENDERKEYSTATESTRUCTURE _SENDERKEYSTATESTRUCTURE_SENDERMESSAGEKEY.containing_type = _SENDERKEYSTATESTRUCTURE _SENDERKEYSTATESTRUCTURE_SENDERSIGNINGKEY.containing_type = _SENDERKEYSTATESTRUCTURE _SENDERKEYSTATESTRUCTURE.fields_by_name['senderChainKey'].message_type = _SENDERKEYSTATESTRUCTURE_SENDERCHAINKEY _SENDERKEYSTATESTRUCTURE.fields_by_name['senderSigningKey'].message_type = _SENDERKEYSTATESTRUCTURE_SENDERSIGNINGKEY _SENDERKEYSTATESTRUCTURE.fields_by_name['senderMessageKeys'].message_type = _SENDERKEYSTATESTRUCTURE_SENDERMESSAGEKEY _SENDERKEYRECORDSTRUCTURE.fields_by_name['senderKeyStates'].message_type = _SENDERKEYSTATESTRUCTURE DESCRIPTOR.message_types_by_name['SessionStructure'] = _SESSIONSTRUCTURE DESCRIPTOR.message_types_by_name['RecordStructure'] = _RECORDSTRUCTURE DESCRIPTOR.message_types_by_name['PreKeyRecordStructure'] = _PREKEYRECORDSTRUCTURE DESCRIPTOR.message_types_by_name['SignedPreKeyRecordStructure'] = _SIGNEDPREKEYRECORDSTRUCTURE DESCRIPTOR.message_types_by_name['IdentityKeyPairStructure'] = _IDENTITYKEYPAIRSTRUCTURE DESCRIPTOR.message_types_by_name['SenderKeyStateStructure'] = _SENDERKEYSTATESTRUCTURE DESCRIPTOR.message_types_by_name['SenderKeyRecordStructure'] = _SENDERKEYRECORDSTRUCTURE SessionStructure = _reflection.GeneratedProtocolMessageType('SessionStructure', (_message.Message,), dict( Chain = _reflection.GeneratedProtocolMessageType('Chain', (_message.Message,), dict( ChainKey = _reflection.GeneratedProtocolMessageType('ChainKey', (_message.Message,), dict( DESCRIPTOR = _SESSIONSTRUCTURE_CHAIN_CHAINKEY, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SessionStructure.Chain.ChainKey) )) , MessageKey = _reflection.GeneratedProtocolMessageType('MessageKey', (_message.Message,), dict( DESCRIPTOR = _SESSIONSTRUCTURE_CHAIN_MESSAGEKEY, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SessionStructure.Chain.MessageKey) )) , DESCRIPTOR = _SESSIONSTRUCTURE_CHAIN, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SessionStructure.Chain) )) , PendingKeyExchange = _reflection.GeneratedProtocolMessageType('PendingKeyExchange', (_message.Message,), dict( DESCRIPTOR = _SESSIONSTRUCTURE_PENDINGKEYEXCHANGE, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SessionStructure.PendingKeyExchange) )) , PendingPreKey = _reflection.GeneratedProtocolMessageType('PendingPreKey', (_message.Message,), dict( DESCRIPTOR = _SESSIONSTRUCTURE_PENDINGPREKEY, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SessionStructure.PendingPreKey) )) , DESCRIPTOR = _SESSIONSTRUCTURE, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SessionStructure) )) _sym_db.RegisterMessage(SessionStructure) _sym_db.RegisterMessage(SessionStructure.Chain) _sym_db.RegisterMessage(SessionStructure.Chain.ChainKey) _sym_db.RegisterMessage(SessionStructure.Chain.MessageKey) _sym_db.RegisterMessage(SessionStructure.PendingKeyExchange) _sym_db.RegisterMessage(SessionStructure.PendingPreKey) RecordStructure = _reflection.GeneratedProtocolMessageType('RecordStructure', (_message.Message,), dict( DESCRIPTOR = _RECORDSTRUCTURE, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.RecordStructure) )) _sym_db.RegisterMessage(RecordStructure) PreKeyRecordStructure = _reflection.GeneratedProtocolMessageType('PreKeyRecordStructure', (_message.Message,), dict( DESCRIPTOR = _PREKEYRECORDSTRUCTURE, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.PreKeyRecordStructure) )) _sym_db.RegisterMessage(PreKeyRecordStructure) SignedPreKeyRecordStructure = _reflection.GeneratedProtocolMessageType('SignedPreKeyRecordStructure', (_message.Message,), dict( DESCRIPTOR = _SIGNEDPREKEYRECORDSTRUCTURE, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SignedPreKeyRecordStructure) )) _sym_db.RegisterMessage(SignedPreKeyRecordStructure) IdentityKeyPairStructure = _reflection.GeneratedProtocolMessageType('IdentityKeyPairStructure', (_message.Message,), dict( DESCRIPTOR = _IDENTITYKEYPAIRSTRUCTURE, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.IdentityKeyPairStructure) )) _sym_db.RegisterMessage(IdentityKeyPairStructure) SenderKeyStateStructure = _reflection.GeneratedProtocolMessageType('SenderKeyStateStructure', (_message.Message,), dict( SenderChainKey = _reflection.GeneratedProtocolMessageType('SenderChainKey', (_message.Message,), dict( DESCRIPTOR = _SENDERKEYSTATESTRUCTURE_SENDERCHAINKEY, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SenderKeyStateStructure.SenderChainKey) )) , SenderMessageKey = _reflection.GeneratedProtocolMessageType('SenderMessageKey', (_message.Message,), dict( DESCRIPTOR = _SENDERKEYSTATESTRUCTURE_SENDERMESSAGEKEY, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SenderKeyStateStructure.SenderMessageKey) )) , SenderSigningKey = _reflection.GeneratedProtocolMessageType('SenderSigningKey', (_message.Message,), dict( DESCRIPTOR = _SENDERKEYSTATESTRUCTURE_SENDERSIGNINGKEY, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SenderKeyStateStructure.SenderSigningKey) )) , DESCRIPTOR = _SENDERKEYSTATESTRUCTURE, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SenderKeyStateStructure) )) _sym_db.RegisterMessage(SenderKeyStateStructure) _sym_db.RegisterMessage(SenderKeyStateStructure.SenderChainKey) _sym_db.RegisterMessage(SenderKeyStateStructure.SenderMessageKey) _sym_db.RegisterMessage(SenderKeyStateStructure.SenderSigningKey) SenderKeyRecordStructure = _reflection.GeneratedProtocolMessageType('SenderKeyRecordStructure', (_message.Message,), dict( DESCRIPTOR = _SENDERKEYRECORDSTRUCTURE, __module__ = 'LocalStorageProtocol_pb2' # @@protoc_insertion_point(class_scope:textsecure.SenderKeyRecordStructure) )) _sym_db.RegisterMessage(SenderKeyRecordStructure) DESCRIPTOR.has_options = True DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n#org.whispersystems.libaxolotl.stateB\rStorageProtos')) # @@protoc_insertion_point(module_scope) python-axolotl-0.1.39/axolotl/state/signedprekeyrecord.py0000644000175000017500000000230513064436211024107 0ustar tarektarek00000000000000# -*- coding; utf-8 -*- from .storageprotos_pb2 import SignedPreKeyRecordStructure from ..ecc.curve import Curve from ..ecc.eckeypair import ECKeyPair class SignedPreKeyRecord: def __init__(self, _id=None, timestamp=None, ecKeyPair=None, signature=None, serialized=None): self.structure = SignedPreKeyRecordStructure() if serialized: self.structure.ParseFromString(serialized) else: self.structure.id = _id self.structure.publicKey = ecKeyPair.getPublicKey().serialize() self.structure.privateKey = ecKeyPair.getPrivateKey().serialize() self.structure.signature = signature self.structure.timestamp = timestamp def getId(self): return self.structure.id def getTimestamp(self): return self.structure.timestamp def getKeyPair(self): publicKey = Curve.decodePoint(bytearray(self.structure.publicKey), 0) privateKey = Curve.decodePrivatePoint(bytearray(self.structure.privateKey)) return ECKeyPair(publicKey, privateKey) def getSignature(self): return self.structure.signature def serialize(self): return self.structure.SerializeToString() python-axolotl-0.1.39/axolotl/state/signedprekeystore.py0000644000175000017500000000104113064436211023761 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- import abc class SignedPreKeyStore(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def loadSignedPreKey(self, signedPreKeyId): pass @abc.abstractmethod def loadSignedPreKeys(self): pass @abc.abstractmethod def storeSignedPreKey(self, signedPreKeyId, signedPreKeyRecord): pass @abc.abstractmethod def containsSignedPreKey(self, signedPreKeyId): pass @abc.abstractmethod def removeSignedPreKey(self, signedPreKeyId): pass python-axolotl-0.1.39/axolotl/state/prekeyrecord.py0000644000175000017500000000164613064436211022724 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- from .storageprotos_pb2 import PreKeyRecordStructure from ..ecc.curve import Curve from ..ecc.eckeypair import ECKeyPair class PreKeyRecord: def __init__(self, _id=None, ecKeyPair=None, serialized=None): self.structure = PreKeyRecordStructure() if serialized: self.structure.ParseFromString(serialized) else: self.structure.id = _id self.structure.publicKey = ecKeyPair.getPublicKey().serialize() self.structure.privateKey = ecKeyPair.getPrivateKey().serialize() def getId(self): return self.structure.id def getKeyPair(self): publicKey = Curve.decodePoint(bytearray(self.structure.publicKey), 0) privateKey = Curve.decodePrivatePoint(bytearray(self.structure.privateKey)) return ECKeyPair(publicKey, privateKey) def serialize(self): return self.structure.SerializeToString() python-axolotl-0.1.39/axolotl/statekeyexchangeexception.py0000644000175000017500000000011713064436211024351 0ustar tarektarek00000000000000# -*- coding: utf-8 -*- class StaleKeyExchangeException(Exception): pass python-axolotl-0.1.39/axolotl/invalidmessageexception.py0000644000175000017500000000036613064436211024016 0ustar tarektarek00000000000000# -*- cofing: utf-8 -*- class InvalidMessageException(Exception): def __init__(self, message, exceptions=None): if exceptions: message += str(exceptions[0]) super(InvalidMessageException, self).__init__(message) python-axolotl-0.1.39/setup.cfg0000644000175000017500000000004613064436273016674 0ustar tarektarek00000000000000[egg_info] tag_build = tag_date = 0