# 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/kdf/hkdf.py
# 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


import unittest
from ...ratchet.chainkey import ChainKey
from ...kdf.hkdf import HKDF
# -*- coding: utf-8 -*-




class ChainKeyTest(unittest.TestCase):
    def test_chainKeyDerivationV2(self):
        seed = bytearray([0x8a, 0xb7, 0x2d, 0x6f, 0x4c, 0xc5, 0xac, 0x0d, 0x38, 0x7e, 0xaf, 0x46, 0x33, 0x78, 0xdd,
                          0xb2, 0x8e, 0xdd, 0x07, 0x38, 0x5b, 0x1c, 0xb0, 0x12, 0x50, 0xc7, 0x15, 0x98, 0x2e, 0x7a,

# 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/kdf/hkdf.py
# 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


# Path: axolotl/tests/ratchet/test_chainkey.py
import unittest
from ...ratchet.chainkey import ChainKey
from ...kdf.hkdf import HKDF

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




class ChainKeyTest(unittest.TestCase):
    def test_chainKeyDerivationV2(self):
        seed = bytearray([0x8a, 0xb7, 0x2d, 0x6f, 0x4c, 0xc5, 0xac, 0x0d, 0x38, 0x7e, 0xaf, 0x46, 0x33, 0x78, 0xdd,
                          0xb2, 0x8e, 0xdd, 0x07, 0x38, 0x5b, 0x1c, 0xb0, 0x12, 0x50, 0xc7, 0x15, 0x98, 0x2e, 0x7a,

                          0xd4, 0x8f])