"""
Eddsa Ed25519 key handling
From
https://github.com/n-y-z-o/nyzoVerifier/blob/b73bc25ba3094abe3470ec070ce306885ad9a18f/src/main/java/co/nyzo/verifier/KeyUtil.java

plus
https://github.com/n-y-z-o/nyzoVerifier/blob/17509f03a7f530c0431ce85377db9b35688c078e/src/main/java/co/nyzo/verifier/util/SignatureUtil.java
"""

# Uses https://github.com/warner/python-ed25519 , c binding, fast


import ed25519
import hashlib
from pynyzo.byteutil import ByteUtil


class KeyUtil:

    @staticmethod
    def main():
        """Temp test, not to be used"""
        signing_key, verifying_key = ed25519.create_keypair()
        print("Original private key", ByteUtil.bytes_as_string_with_dashes(signing_key.to_bytes()[:32]))
        # signing key has signing + verifying, we keep the first 32 to only get the private part.
        print("Original public key", ByteUtil.bytes_as_string_with_dashes(verifying_key.to_bytes()))

    @staticmethod
    def generateSeed(hashable_keyword: str='') -> bytes:
        """Generate a private key, with optional keyword to get reproducible tests results or later HD Wallet."""
        if len(hashable_keyword):
            seed = hashlib.sha256(hashable_keyword).digest()
            signing_key = ed25519.SigningKey(seed)
        else:
            signing_key, _ = ed25519.create_keypair()
        return signing_key.to_bytes()[:32]

    @staticmethod
    def private_to_public(private: str) -> str:
        """Temp Test"""
        keydata = bytes.fromhex(private)
        signing_key = ed25519.SigningKey(keydata)
        verifying_key = signing_key.get_verifying_key()
        vkey_hex = verifying_key.to_ascii(encoding="hex")
        return vkey_hex.decode('utf-8')

    @staticmethod
    def get_from_private_seed_file(filename: str):
        """returns priv and pub key - as object - from the stored nyzo text id format"""
        with open(filename) as f:
            nyzo = f.read(80).replace('-', '').encode('utf-8').strip()
            signing_key = ed25519.SigningKey(nyzo, encoding="hex")
            verifying_key = signing_key.get_verifying_key()
        return signing_key, verifying_key

    @staticmethod
    def get_from_private_seed(seed: str):
        """returns priv and pub key - as object - from an hex seed"""
        seed = seed.replace('-', '').encode('utf-8').strip()
        signing_key = ed25519.SigningKey(seed, encoding="hex")
        verifying_key = signing_key.get_verifying_key()
        return signing_key, verifying_key


    @staticmethod
    def save_to_private_seed_file(filename: str, key: bytes) -> None:
        """Saves the privkey to the nyzo formatted file"""
        nyzo_format = ByteUtil.bytes_as_string_with_dashes(key)
        with open(filename, 'w') as f:
            f.write(nyzo_format)

    @staticmethod
    def sign_bytes(bytes_to_sign: bytes, private_key: ed25519.SigningKey) -> bytes:
        sig = private_key.sign(bytes_to_sign)
        return sig

    @staticmethod
    def signature_is_valid(signature: bytes, signed_bytes: bytes, public_id: bytes) -> bool:
        verifying_key = ed25519.VerifyingKey(public_id)
        # todo: cache key from id, see https://github.com/n-y-z-o/nyzoVerifier/blob/17509f03a7f530c0431ce85377db9b35688c078e/src/main/java/co/nyzo/verifier/util/SignatureUtil.java
        try:
            verifying_key.verify(signature, signed_bytes)
            # print("signature is good")
            return True
        except ed25519.BadSignatureError:
            # print("signature is bad!")
            return False


if __name__ == "__main__":
    KeyUtil.main()
    # KeyUtil.private_to_public('nyzo-formatted-private-key'.replace('-', ''))



[((582, 606), 'ed25519.create_keypair', 'ed25519.create_keypair', ([], {}), '()\n', (604, 606), False, 'import ed25519\n'), ((1512, 1539), 'ed25519.SigningKey', 'ed25519.SigningKey', (['keydata'], {}), '(keydata)\n', (1530, 1539), False, 'import ed25519\n'), ((2341, 2381), 'ed25519.SigningKey', 'ed25519.SigningKey', (['seed'], {'encoding': '"""hex"""'}), "(seed, encoding='hex')\n", (2359, 2381), False, 'import ed25519\n'), ((2651, 2692), 'pynyzo.byteutil.ByteUtil.bytes_as_string_with_dashes', 'ByteUtil.bytes_as_string_with_dashes', (['key'], {}), '(key)\n', (2687, 2692), False, 'from pynyzo.byteutil import ByteUtil\n'), ((3069, 3100), 'ed25519.VerifyingKey', 'ed25519.VerifyingKey', (['public_id'], {}), '(public_id)\n', (3089, 3100), False, 'import ed25519\n'), ((1222, 1246), 'ed25519.SigningKey', 'ed25519.SigningKey', (['seed'], {}), '(seed)\n', (1240, 1246), False, 'import ed25519\n'), ((1290, 1314), 'ed25519.create_keypair', 'ed25519.create_keypair', ([], {}), '()\n', (1312, 1314), False, 'import ed25519\n'), ((1984, 2024), 'ed25519.SigningKey', 'ed25519.SigningKey', (['nyzo'], {'encoding': '"""hex"""'}), "(nyzo, encoding='hex')\n", (2002, 2024), False, 'import ed25519\n'), ((1154, 1186), 'hashlib.sha256', 'hashlib.sha256', (['hashable_keyword'], {}), '(hashable_keyword)\n', (1168, 1186), False, 'import hashlib\n')]