# 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/kdf/derivedrootsecrets.py
# 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
# 
# Path: axolotl/ratchet/chainkey.py
# 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()


from ..ecc.curve import Curve
from ..kdf.derivedrootsecrets import DerivedRootSecrets
from .chainkey import ChainKey
# -*- coding: utf-8 -*-



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,
                                                    "WhisperRatchet".encode(),
                                                    DerivedRootSecrets.SIZE,
                                                    salt=self.key)

# 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/kdf/derivedrootsecrets.py
# 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
# 
# Path: axolotl/ratchet/chainkey.py
# 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()


# Path: axolotl/ratchet/rootkey.py
from ..ecc.curve import Curve
from ..kdf.derivedrootsecrets import DerivedRootSecrets
from .chainkey import ChainKey

# -*- coding: utf-8 -*-



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,
                                                    "WhisperRatchet".encode(),
                                                    DerivedRootSecrets.SIZE,
                                                    salt=self.key)

        derivedSecrets = DerivedRootSecrets(derivedSecretBytes)