diff --git a/duniterpy/helpers.py b/duniterpy/helpers.py index 251a53f095f9838880836784e23d3066d93467ad..0baaa2bba895a905f743ea52cfa7356b7e2f822a 100644 --- a/duniterpy/helpers.py +++ b/duniterpy/helpers.py @@ -1,4 +1,5 @@ from typing import Union +from libnacl.encode import hex_decode, hex_encode def ensure_bytes(data: Union[str, bytes]) -> bytes: @@ -39,3 +40,23 @@ def xor_bytes(b1: bytes, b2: bytes) -> bytearray: for i1, i2 in zip(b1, b2): result.append(i1 ^ i2) return result + + +def convert_seedhex_to_seed(seedhex: str) -> bytes: + """ + Convert seedhex to seed + + :param seedhex: seed coded in hexadecimal base + :rtype bytes: + """ + return bytes(hex_decode(seedhex.encode("utf-8"))) + + +def convert_seed_to_seedhex(seed: bytes) -> str: + """ + Convert seed to seedhex + + :param seed: seed + :rtype str: + """ + return hex_encode(seed).decode("utf-8") diff --git a/duniterpy/key/signing_key.py b/duniterpy/key/signing_key.py index d8fc172cd27826e90731bf33162c7b972e3054e7..184df266420c396f320b5d1b0c3e8936cf21d8d1 100644 --- a/duniterpy/key/signing_key.py +++ b/duniterpy/key/signing_key.py @@ -12,7 +12,7 @@ from libnacl.utils import load_key from pylibscrypt import scrypt from .base58 import Base58Encoder -from ..helpers import ensure_bytes, xor_bytes +from ..helpers import ensure_bytes, xor_bytes, convert_seedhex_to_seed, convert_seed_to_seedhex SEED_LENGTH = 32 # Length of the key crypto_sign_BYTES = 64 @@ -68,6 +68,42 @@ class SigningKey(libnacl.sign.Signer): return cls(seed) + def save_seedhex_file(self, path: str) -> None: + """ + Save hexadecimal seed file from seed + + :param path: Authentication file path + """ + seedhex = convert_seed_to_seedhex(self.seed) + with open(path, 'w') as fh: + fh.write(seedhex) + + @staticmethod + def from_seedhex_file(path: str) -> SigningKeyType: + """ + Return SigningKey instance from Seedhex file + + :param str path: Hexadecimal seed file path + """ + with open(path, 'r') as fh: + seedhex = fh.read() + return SigningKey.from_seedhex(seedhex) + + @classmethod + def from_seedhex(cls: Type[SigningKeyType], seedhex: str) -> SigningKeyType: + """ + Return SigningKey instance from Seedhex + + :param str seedhex: Hexadecimal seed string + """ + regex_seedhex = compile("([0-9a-fA-F]{64})") + match = search(regex_seedhex, seedhex) + if not match: + raise Exception('Error: Bad seed hexadecimal format') + seedhex = match.groups()[0] + seed = convert_seedhex_to_seed(seedhex) + return cls(seed) + def save_private_key(self, path: str) -> None: """ Save authentication file @@ -111,8 +147,8 @@ class SigningKey(libnacl.sign.Signer): pubsec_content = fh.read() # line patterns - regex_pubkey = compile("pub: ([1-9A-HJ-NP-Za-km-z]+)", MULTILINE) - regex_signkey = compile("sec: ([1-9A-HJ-NP-Za-km-z]+)", MULTILINE) + regex_pubkey = compile("pub: ([1-9A-HJ-NP-Za-km-z]{43,44})", MULTILINE) + regex_signkey = compile("sec: ([1-9A-HJ-NP-Za-km-z]{88,90})", MULTILINE) # check public key field match = search(regex_pubkey, pubsec_content)