# Path: axolotl/groups/ratchet/senderchainkey.py
# 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()
# 
# Path: axolotl/groups/ratchet/sendermessagekey.py
# 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
# 
# Path: axolotl/ecc/curve.py
# 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())


from ...state import storageprotos_pb2 as storageprotos
from ..ratchet.senderchainkey import SenderChainKey
from ..ratchet.sendermessagekey import SenderMessageKey
from ...ecc.curve import Curve
        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:

# Path: axolotl/groups/ratchet/senderchainkey.py
# 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()
# 
# Path: axolotl/groups/ratchet/sendermessagekey.py
# 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
# 
# Path: axolotl/ecc/curve.py
# 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())


# Path: axolotl/groups/state/senderkeystate.py
from ...state import storageprotos_pb2 as storageprotos
from ..ratchet.senderchainkey import SenderChainKey
from ..ratchet.sendermessagekey import SenderMessageKey
from ...ecc.curve import Curve

        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))