From 5dd0317f5da02210b941303c7ec4e9e748311a69 Mon Sep 17 00:00:00 2001 From: Ethan Kosakovsky Date: Sun, 19 Apr 2020 02:48:32 +0000 Subject: [PATCH] Refactor for API layer --- bipentropy/app.py | 64 ++++++++++++++++++++++++++++++++++++++++ bipentropy/bipentropy.py | 13 ++++---- test_entropy.py | 30 +++++++++++++------ 3 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 bipentropy/app.py diff --git a/bipentropy/app.py b/bipentropy/app.py new file mode 100644 index 0000000..5a4499e --- /dev/null +++ b/bipentropy/app.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Copyright (c) 2020 Ethan Kosakovsky +# +# 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. + +import bipentropy + + +def bip39(xprv_string, language, words, index): + # 83696968'/39'/language'/words'/index' + language_lookup = { + 'english': 0, + 'japanese': 1, + 'korean': 2, + 'spanish': 3, + 'chinese_simplified': 4, + 'chinese_traditional': 5, + 'french': 6, + 'italian': 7, + 'czech': 8 + } + lang_code = language_lookup[language] + e = bipentropy.BIPEntropy() + path = f"83696968p/39p/{lang_code}p/{words}p/{index}p" + + entropy = e.bip32_xprv_to_entropy(path, xprv_string) + return e.entropy_to_bip39(entropy, words, language) + + +def wif(xprv_string, index): + # m/83696968'/0'/index' + e = bipentropy.BIPEntropy() + path = f"83696968p/0p/{index}p" + return e.entropy_to_wif(e.bip32_xprv_to_entropy(path, xprv_string)) + + +def hex(xprv_string, index, width): + # m/83696968'/0'/index' + e = bipentropy.BIPEntropy() + path = f"83696968p/128169p/{width}p/{index}p" + return e.bip32_xprv_to_hex(path, width, xprv_string) + + +def xprv(xprv_string, index): + # 83696968'/32'/index' + e = bipentropy.BIPEntropy() + path = f"83696968p/32p/{index}p" + return e.bip32_xprv_to_xprv(path, xprv_string) diff --git a/bipentropy/bipentropy.py b/bipentropy/bipentropy.py index f7c5b27..77bbf09 100644 --- a/bipentropy/bipentropy.py +++ b/bipentropy/bipentropy.py @@ -27,12 +27,14 @@ class BIPEntropy(object): + def __decorate_path(self, path): + return path.replace("m/", "").replace("'", "p") def __get_k_from_node(self, node): return to_bytes_32(node.secret_exponent()) def __derive_k(self, path, xprv): - path = path.replace("m/", "").replace("'", "p") + path = self.__decorate_path(path) node = xprv.subkey_for_path(path) return self.__get_k_from_node(node) @@ -50,15 +52,14 @@ def bip32_xprv_to_entropy(self, path, xprv_string): raise ValueError('ERROR: Invalid xprv') return self.__hmac_sha512(self.__derive_k(path, xprv)) - def bip32_xprv_to_hex(self, index, width, xprv_string): + def bip32_xprv_to_hex(self, path, width, xprv_string): # export entropy as hex - path = f"83696968p/128169p/{width}p/{index}p" + path = self.__decorate_path(path) ent = self.bip32_xprv_to_entropy(path, xprv_string) return ent[0:width].hex() - def bip32_xprv_to_xprv(self, index, xprv_string): - # app_no = 32 => XPRV to XPRV - path = f"83696968p/32p/{index}p" + def bip32_xprv_to_xprv(self, path, xprv_string): + path = self.__decorate_path(path) node = BTC.parse.bip32_prv(xprv_string).subkey_for_path(path) # if API to pycoin hadn't been shitcoined: diff --git a/test_entropy.py b/test_entropy.py index 4136745..430a176 100644 --- a/test_entropy.py +++ b/test_entropy.py @@ -20,6 +20,7 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from bipentropy import bipentropy +from bipentropy import app import pytest XPRV = 'xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb' @@ -62,7 +63,7 @@ def test_wif_from_entropy(): entropy = e.bip32_xprv_to_entropy("m/83696968'/0'/0'", XPRV) assert e.entropy_to_wif(entropy) == 'L11mqGbaozsMYDHS7dfZ2bPGL2viSH6zHr69MKwvpxuw7cCR4M1u' -def test_applications(): +def test_mnemonic(): e = bipentropy.BIPEntropy() entropy = e.bip32_xprv_to_entropy("m/83696968'/39'/0'/12'/0'", XPRV) assert entropy[:16].hex() == 'f0337580e36fd50ef8734cd9dcfb9a78' @@ -79,19 +80,30 @@ def test_applications(): assert e.entropy_to_bip39(entropy, 24) == \ 'fabric crumble art inhale hurt crouch helmet since bike bomb twelve frog bicycle toward fox grant pulp spend sibling bunker caution nurse brain prison' -def test_xprv_application(): +def test_xprv(): e = bipentropy.BIPEntropy() - result = e.bip32_xprv_to_xprv(0, XPRV) + result = e.bip32_xprv_to_xprv("83696968'/32'/0'", XPRV) assert result == 'xprv9s21ZrQH143K3KJoGoKpsDsWdDNDBKs1wqFymBpCGJtrYXrfKzykGDBadZq5SrNde22F83X9qhFZr4uyV9TptTgLqCBc6XFN9tssphdxVeg' -@pytest.mark.parametrize('index, width, expect', [ - (0, 32, '4f4ea2ef43af14e51f2453221d50762fc3767e2287dc524ca58f10e5225a6ead'), - (0, 64, '4fc6759ef9c0e12aed757ad874706a3955ef125c8f8eabb3909aeda028f5e285bf496a23265bac09f537f4cc5e1efa689f5625ded2cd996c042b2657263c6816'), - (1234, 64, 'e1a35aeae27cb3c93b0d437e94b64a891cdff9ac250537ec675d0e6a2680f1d2edf9927f4c5233b19b15fdea4063a8b62f85ff8666176d226741ed192075a8db'), +@pytest.mark.parametrize('path, width, expect', [ + ("83696968'/128169'/32'/0'", 32, '4f4ea2ef43af14e51f2453221d50762fc3767e2287dc524ca58f10e5225a6ead'), + ("83696968'/128169'/64'/0'", 64, '4fc6759ef9c0e12aed757ad874706a3955ef125c8f8eabb3909aeda028f5e285bf496a23265bac09f537f4cc5e1efa689f5625ded2cd996c042b2657263c6816'), + ("83696968'/128169'/64'/1234'", 64, 'e1a35aeae27cb3c93b0d437e94b64a891cdff9ac250537ec675d0e6a2680f1d2edf9927f4c5233b19b15fdea4063a8b62f85ff8666176d226741ed192075a8db'), ]) -def test_hex_application(index, width, expect): +def test_hex(path, width, expect): e = bipentropy.BIPEntropy() - assert e.bip32_xprv_to_hex(index, width, XPRV) == expect + assert e.bip32_xprv_to_hex(path, width, XPRV) == expect + +def test_bipentropy_applications(): + assert app.bip39(XPRV, 'english', 18, 0) == \ + 'gate neutral humble top among february junior once buyer van sand subject clip enable trade crime future protect' + + assert app.xprv(XPRV, 0) == \ + 'xprv9s21ZrQH143K3KJoGoKpsDsWdDNDBKs1wqFymBpCGJtrYXrfKzykGDBadZq5SrNde22F83X9qhFZr4uyV9TptTgLqCBc6XFN9tssphdxVeg' + + assert app.wif(XPRV, 0) == 'L11mqGbaozsMYDHS7dfZ2bPGL2viSH6zHr69MKwvpxuw7cCR4M1u' + + assert app.hex(XPRV, 0, 32) == '4f4ea2ef43af14e51f2453221d50762fc3767e2287dc524ca58f10e5225a6ead' if __name__ == "__main__": pytest.main()