# Copyright (c) 2021 <NAME>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


# Imports
from bip_utils import (
    Bip32KeyError,
    Bip32ChainCode, Bip32Depth, Bip32KeyIndex, Bip32FingerPrint, Bip32KeyData,
    Bip32PublicKey, Bip32PrivateKey
)
from bip_utils.bip.bip32.bip32_const import Bip32Const
from tests.ecc.test_ecc import *

# Public keys for testing
TEST_PUB_KEYS = [
    {
        "key": TEST_ED25519_PUB_KEY,
        "fprint": b"6ff1e466",
        "key_id": b"6ff1e46644e62d8d44ee2fffb45960d350202c4b",
        "ext": "<KEY>",
    },
    {
        "key": TEST_ED25519_BLAKE2B_PUB_KEY,
        "fprint": b"23e1ef48",
        "key_id": b"23e1ef48982188655152d7e651b754e562eb018e",
        "ext": "<KEY>",
    },
    {
        "key": TEST_ED25519_MONERO_PUB_KEY,
        "fprint": b"41a4a2c0",
        "key_id": b"41a4a2c0cfa0c22ee6b00a6033fff32bd7aa9959",
        "ext": "<KEY>",
    },
    {
        "key": TEST_NIST256P1_PUB_KEY,
        "fprint": b"5fa155ff",
        "key_id": b"5fa155ff09510ec6ca9dd3f8e51b06e327bf4845",
        "ext": "<KEY>",
    },
    {
        "key": TEST_SECP256K1_PUB_KEY,
        "fprint": b"<KEY>",
        "key_id": b"e168bdf4a501ed739b5a94731bd13d0044efd7c7",
        "ext": "<KEY>",
    },
    {
        "key": TEST_SR25519_PUB_KEY,
        "fprint": b"7bde84a2",
        "key_id": b"7bde84a21e328728228f4fc69a24f57d85f7d1a4",
        "ext": "<KEY>",
    },
]

# Private keys for testing
TEST_PRIV_KEYS = [
    {
        "key": TEST_ED25519_PRIV_KEY,
        "ext": "<KEY>",
    },
    {
        "key": TEST_ED25519_BLAKE2B_PRIV_KEY,
        "ext": "<KEY>",
    },
    {
        "key": TEST_ED25519_MONERO_PRIV_KEY,
        "ext": "<KEY>",
    },
    {
        "key": TEST_NIST256P1_PRIV_KEY,
        "ext": "<KEY>",
    },
    {
        "key": TEST_SECP256K1_PRIV_KEY,
        "ext": "<KEY>",
    },
]

# Invalid public keys for testing
TEST_INVALID_PUB_KEYS = [
    {"keys": TEST_VECT_ED25519_PUB_KEY_INVALID, "curve": EllipticCurveTypes.ED25519},
    {"keys": TEST_VECT_ED25519_PUB_KEY_INVALID, "curve": EllipticCurveTypes.ED25519_BLAKE2B},
    {"keys": TEST_VECT_ED25519_PUB_KEY_INVALID, "curve": EllipticCurveTypes.ED25519_MONERO},
    {"keys": TEST_VECT_NIST256P1_PUB_KEY_INVALID, "curve": EllipticCurveTypes.NIST256P1},
    {"keys": TEST_VECT_SECP256K1_PUB_KEY_INVALID, "curve": EllipticCurveTypes.SECP256K1},
    {"keys": TEST_VECT_SR25519_PUB_KEY_INVALID, "curve": EllipticCurveTypes.SR25519},
]

# Invalid private keys for testing
TEST_INVALID_PRIV_KEYS = [
    {"keys": TEST_VECT_ED25519_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.ED25519},
    {"keys": TEST_VECT_ED25519_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.ED25519_BLAKE2B},
    {"keys": TEST_VECT_ED25519_MONERO_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.ED25519_MONERO},
    {"keys": TEST_VECT_NIST256P1_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.NIST256P1},
    {"keys": TEST_VECT_SECP256K1_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.SECP256K1},
    {"keys": TEST_VECT_SR25519_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.SR25519},
]

# Key data for testing
TEST_KEY_DATA = Bip32KeyData(Bip32Const.MAIN_NET_KEY_NET_VERSIONS,
                             Bip32Depth(0),
                             Bip32KeyIndex(0),
                             Bip32ChainCode(),
                             Bip32FingerPrint())


#
# Tests
#
class Bip32KeyDataTests(unittest.TestCase):
    # Test private key
    def test_priv_key(self):
        for i, test in enumerate(TEST_PRIV_KEYS):
            test_pub = TEST_PUB_KEYS[i]

            # FromBytesOrKeyObject (object)
            self.__test_priv_key_obj(Bip32PrivateKey.FromBytesOrKeyObject(test["key"], TEST_KEY_DATA, test["key"].CurveType()), test, test_pub)
            # FromBytesOrKeyObject (bytes)
            self.__test_priv_key_obj(Bip32PrivateKey.FromBytesOrKeyObject(test["key"].Raw().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test, test_pub)
            # FromBytes (bytes)
            self.__test_priv_key_obj(Bip32PrivateKey.FromBytes(test["key"].Raw().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test, test_pub)

    # Test public key
    def test_pub_key(self):
        for test in TEST_PUB_KEYS:
            # FromBytesOrKeyObject (object)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytesOrKeyObject(test["key"], TEST_KEY_DATA, test["key"].CurveType()), test)
            # FromBytesOrKeyObject (compressed)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytesOrKeyObject(test["key"].RawCompressed().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test)
            # FromBytesOrKeyObject (uncompressed)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytesOrKeyObject(test["key"].RawUncompressed().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test)
            # FromBytes (compressed)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytes(test["key"].RawCompressed().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test)
            # FromBytes (uncompressed)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytes(test["key"].RawUncompressed().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test)

    # Test invalid keys
    def test_invalid_keys(self):
        # Invalid private keys
        for test in TEST_INVALID_PRIV_KEYS:
            for key in test["keys"]:
                self.assertRaises(Bip32KeyError, Bip32PrivateKey.FromBytesOrKeyObject, key, TEST_KEY_DATA, test["curve"])
        # Invalid public keys
        for test in TEST_INVALID_PUB_KEYS:
            for key in test["keys"]:
                self.assertRaises(Bip32KeyError, Bip32PublicKey.FromBytesOrKeyObject, key, TEST_KEY_DATA, test["curve"])

    # Test private key object
    def __test_priv_key_obj(self, priv_key_obj, test_priv, test_pub):
        self.assertEqual(test_priv["key"].CurveType(), priv_key_obj.CurveType())
        self.assertTrue(isinstance(priv_key_obj.KeyObject(), type(test_priv["key"])))
        self.assertTrue(priv_key_obj.Data() is TEST_KEY_DATA)

        self.assertEqual(test_priv["key"].Raw().ToBytes(), priv_key_obj.Raw().ToBytes())
        self.assertEqual(test_priv["key"].Raw().ToBytes(), bytes(priv_key_obj.Raw()))
        self.assertEqual(test_priv["key"].Raw().ToHex(), priv_key_obj.Raw().ToHex())
        self.assertEqual(test_priv["key"].Raw().ToHex(), str(priv_key_obj.Raw()))

        self.assertEqual(test_priv["ext"],priv_key_obj.ToExtended())
        # Public key associated to the private one
        self.__test_pub_key_obj(priv_key_obj.PublicKey(), test_pub)

    # Test public key object
    def __test_pub_key_obj(self, pub_key_obj, test):
        self.assertEqual(test["key"].CurveType(), pub_key_obj.CurveType())
        self.assertTrue(isinstance(pub_key_obj.KeyObject(), type(test["key"])))
        self.assertTrue(pub_key_obj.Data() is TEST_KEY_DATA)

        self.assertEqual(test["key"].RawCompressed().ToBytes(), pub_key_obj.RawCompressed().ToBytes())
        self.assertEqual(test["key"].RawCompressed().ToBytes(), bytes(pub_key_obj.RawCompressed()))
        self.assertEqual(test["key"].RawCompressed().ToHex(), pub_key_obj.RawCompressed().ToHex())
        self.assertEqual(test["key"].RawCompressed().ToHex(), str(pub_key_obj.RawCompressed()))

        self.assertEqual(test["key"].RawUncompressed().ToBytes(), pub_key_obj.RawUncompressed().ToBytes())
        self.assertEqual(test["key"].RawUncompressed().ToBytes(), bytes(pub_key_obj.RawUncompressed()))
        self.assertEqual(test["key"].RawUncompressed().ToHex(), pub_key_obj.RawUncompressed().ToHex())
        self.assertEqual(test["key"].RawUncompressed().ToHex(), str(pub_key_obj.RawUncompressed()))

        self.assertEqual(binascii.unhexlify(test["fprint"]),pub_key_obj.FingerPrint().ToBytes())
        self.assertEqual(binascii.unhexlify(test["key_id"]),pub_key_obj.KeyIdentifier())
        self.assertEqual(test["ext"],pub_key_obj.ToExtended())

# Copyright (c) 2021 <NAME>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


# Imports
from bip_utils import (
    Bip32KeyError,
    Bip32ChainCode, Bip32Depth, Bip32KeyIndex, Bip32FingerPrint, Bip32KeyData,
    Bip32PublicKey, Bip32PrivateKey
)
from bip_utils.bip.bip32.bip32_const import Bip32Const
from tests.ecc.test_ecc import *

# Public keys for testing
TEST_PUB_KEYS = [
    {
        "key": TEST_ED25519_PUB_KEY,
        "fprint": b"6ff1e466",
        "key_id": b"6ff1e46644e62d8d44ee2fffb45960d350202c4b",
        "ext": "<KEY>",
    },
    {
        "key": TEST_ED25519_BLAKE2B_PUB_KEY,
        "fprint": b"23e1ef48",
        "key_id": b"23e1ef48982188655152d7e651b754e562eb018e",
        "ext": "<KEY>",
    },
    {
        "key": TEST_ED25519_MONERO_PUB_KEY,
        "fprint": b"41a4a2c0",
        "key_id": b"41a4a2c0cfa0c22ee6b00a6033fff32bd7aa9959",
        "ext": "<KEY>",
    },
    {
        "key": TEST_NIST256P1_PUB_KEY,
        "fprint": b"5fa155ff",
        "key_id": b"5fa155ff09510ec6ca9dd3f8e51b06e327bf4845",
        "ext": "<KEY>",
    },
    {
        "key": TEST_SECP256K1_PUB_KEY,
        "fprint": b"<KEY>",
        "key_id": b"e168bdf4a501ed739b5a94731bd13d0044efd7c7",
        "ext": "<KEY>",
    },
    {
        "key": TEST_SR25519_PUB_KEY,
        "fprint": b"7bde84a2",
        "key_id": b"7bde84a21e328728228f4fc69a24f57d85f7d1a4",
        "ext": "<KEY>",
    },
]

# Private keys for testing
TEST_PRIV_KEYS = [
    {
        "key": TEST_ED25519_PRIV_KEY,
        "ext": "<KEY>",
    },
    {
        "key": TEST_ED25519_BLAKE2B_PRIV_KEY,
        "ext": "<KEY>",
    },
    {
        "key": TEST_ED25519_MONERO_PRIV_KEY,
        "ext": "<KEY>",
    },
    {
        "key": TEST_NIST256P1_PRIV_KEY,
        "ext": "<KEY>",
    },
    {
        "key": TEST_SECP256K1_PRIV_KEY,
        "ext": "<KEY>",
    },
]

# Invalid public keys for testing
TEST_INVALID_PUB_KEYS = [
    {"keys": TEST_VECT_ED25519_PUB_KEY_INVALID, "curve": EllipticCurveTypes.ED25519},
    {"keys": TEST_VECT_ED25519_PUB_KEY_INVALID, "curve": EllipticCurveTypes.ED25519_BLAKE2B},
    {"keys": TEST_VECT_ED25519_PUB_KEY_INVALID, "curve": EllipticCurveTypes.ED25519_MONERO},
    {"keys": TEST_VECT_NIST256P1_PUB_KEY_INVALID, "curve": EllipticCurveTypes.NIST256P1},
    {"keys": TEST_VECT_SECP256K1_PUB_KEY_INVALID, "curve": EllipticCurveTypes.SECP256K1},
    {"keys": TEST_VECT_SR25519_PUB_KEY_INVALID, "curve": EllipticCurveTypes.SR25519},
]

# Invalid private keys for testing
TEST_INVALID_PRIV_KEYS = [
    {"keys": TEST_VECT_ED25519_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.ED25519},
    {"keys": TEST_VECT_ED25519_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.ED25519_BLAKE2B},
    {"keys": TEST_VECT_ED25519_MONERO_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.ED25519_MONERO},
    {"keys": TEST_VECT_NIST256P1_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.NIST256P1},
    {"keys": TEST_VECT_SECP256K1_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.SECP256K1},
    {"keys": TEST_VECT_SR25519_PRIV_KEY_INVALID, "curve": EllipticCurveTypes.SR25519},
]

# Key data for testing
TEST_KEY_DATA = Bip32KeyData(Bip32Const.MAIN_NET_KEY_NET_VERSIONS,
                             Bip32Depth(0),
                             Bip32KeyIndex(0),
                             Bip32ChainCode(),
                             Bip32FingerPrint())


#
# Tests
#
class Bip32KeyDataTests(unittest.TestCase):
    # Test private key
    def test_priv_key(self):
        for i, test in enumerate(TEST_PRIV_KEYS):
            test_pub = TEST_PUB_KEYS[i]

            # FromBytesOrKeyObject (object)
            self.__test_priv_key_obj(Bip32PrivateKey.FromBytesOrKeyObject(test["key"], TEST_KEY_DATA, test["key"].CurveType()), test, test_pub)
            # FromBytesOrKeyObject (bytes)
            self.__test_priv_key_obj(Bip32PrivateKey.FromBytesOrKeyObject(test["key"].Raw().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test, test_pub)
            # FromBytes (bytes)
            self.__test_priv_key_obj(Bip32PrivateKey.FromBytes(test["key"].Raw().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test, test_pub)

    # Test public key
    def test_pub_key(self):
        for test in TEST_PUB_KEYS:
            # FromBytesOrKeyObject (object)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytesOrKeyObject(test["key"], TEST_KEY_DATA, test["key"].CurveType()), test)
            # FromBytesOrKeyObject (compressed)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytesOrKeyObject(test["key"].RawCompressed().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test)
            # FromBytesOrKeyObject (uncompressed)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytesOrKeyObject(test["key"].RawUncompressed().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test)
            # FromBytes (compressed)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytes(test["key"].RawCompressed().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test)
            # FromBytes (uncompressed)
            self.__test_pub_key_obj(Bip32PublicKey.FromBytes(test["key"].RawUncompressed().ToBytes(), TEST_KEY_DATA, test["key"].CurveType()), test)

    # Test invalid keys
    def test_invalid_keys(self):
        # Invalid private keys
        for test in TEST_INVALID_PRIV_KEYS:
            for key in test["keys"]:
                self.assertRaises(Bip32KeyError, Bip32PrivateKey.FromBytesOrKeyObject, key, TEST_KEY_DATA, test["curve"])
        # Invalid public keys
        for test in TEST_INVALID_PUB_KEYS:
            for key in test["keys"]:
                self.assertRaises(Bip32KeyError, Bip32PublicKey.FromBytesOrKeyObject, key, TEST_KEY_DATA, test["curve"])

    # Test private key object
    def __test_priv_key_obj(self, priv_key_obj, test_priv, test_pub):
        self.assertEqual(test_priv["key"].CurveType(), priv_key_obj.CurveType())
        self.assertTrue(isinstance(priv_key_obj.KeyObject(), type(test_priv["key"])))
        self.assertTrue(priv_key_obj.Data() is TEST_KEY_DATA)

        self.assertEqual(test_priv["key"].Raw().ToBytes(), priv_key_obj.Raw().ToBytes())
        self.assertEqual(test_priv["key"].Raw().ToBytes(), bytes(priv_key_obj.Raw()))
        self.assertEqual(test_priv["key"].Raw().ToHex(), priv_key_obj.Raw().ToHex())
        self.assertEqual(test_priv["key"].Raw().ToHex(), str(priv_key_obj.Raw()))

        self.assertEqual(test_priv["ext"],priv_key_obj.ToExtended())
        # Public key associated to the private one
        self.__test_pub_key_obj(priv_key_obj.PublicKey(), test_pub)

    # Test public key object
    def __test_pub_key_obj(self, pub_key_obj, test):
        self.assertEqual(test["key"].CurveType(), pub_key_obj.CurveType())
        self.assertTrue(isinstance(pub_key_obj.KeyObject(), type(test["key"])))
        self.assertTrue(pub_key_obj.Data() is TEST_KEY_DATA)

        self.assertEqual(test["key"].RawCompressed().ToBytes(), pub_key_obj.RawCompressed().ToBytes())
        self.assertEqual(test["key"].RawCompressed().ToBytes(), bytes(pub_key_obj.RawCompressed()))
        self.assertEqual(test["key"].RawCompressed().ToHex(), pub_key_obj.RawCompressed().ToHex())
        self.assertEqual(test["key"].RawCompressed().ToHex(), str(pub_key_obj.RawCompressed()))

        self.assertEqual(test["key"].RawUncompressed().ToBytes(), pub_key_obj.RawUncompressed().ToBytes())
        self.assertEqual(test["key"].RawUncompressed().ToBytes(), bytes(pub_key_obj.RawUncompressed()))
        self.assertEqual(test["key"].RawUncompressed().ToHex(), pub_key_obj.RawUncompressed().ToHex())
        self.assertEqual(test["key"].RawUncompressed().ToHex(), str(pub_key_obj.RawUncompressed()))

        self.assertEqual(binascii.unhexlify(test["fprint"]),pub_key_obj.FingerPrint().ToBytes())
        self.assertEqual(binascii.unhexlify(test["key_id"]),pub_key_obj.KeyIdentifier())
        self.assertEqual(test["ext"],pub_key_obj.ToExtended())

# Copyright (c) 2021 <NAME> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # Imports # Public keys for testing # Private keys for testing # Invalid public keys for testing # Invalid private keys for testing # Key data for testing # # Tests # # Test private key # FromBytesOrKeyObject (object) # FromBytesOrKeyObject (bytes) # FromBytes (bytes) # Test public key # FromBytesOrKeyObject (object) # FromBytesOrKeyObject (compressed) # FromBytesOrKeyObject (uncompressed) # FromBytes (compressed) # FromBytes (uncompressed) # Test invalid keys # Invalid private keys # Invalid public keys # Test private key object # Public key associated to the private one # Test public key object