Skip to content
Snippets Groups Projects
Commit 8350b987 authored by matograine's avatar matograine
Browse files

[mod] #320 #301 change check_public_key() behavior

    * create has_pubkey_checksum()
    * create is_pubkey_and_check()
    * change use of check_public_key in tx, balance and history commands.
    * use is_pubkey_and_check() in `id` command and solve #320
    * create tests for is_pubkey_and_check, has_pubkey_checksum() and check_public_key()

    * change imports in silkaj.money to prevent loop dependency
parent 47650302
No related branches found
No related tags found
No related merge requests found
...@@ -19,32 +19,50 @@ import re ...@@ -19,32 +19,50 @@ import re
from nacl import encoding, hash from nacl import encoding, hash
from silkaj.constants import PUBKEY_PATTERN from silkaj.constants import PUBKEY_PATTERN
from silkaj.tools import message_exit
PUBKEY_DELIMITED_PATTERN = "^{0}$".format(PUBKEY_PATTERN) PUBKEY_DELIMITED_PATTERN = "^{0}$".format(PUBKEY_PATTERN)
CHECKSUM_PATTERN = "[1-9A-HJ-NP-Za-km-z]{3}" CHECKSUM_PATTERN = "[1-9A-HJ-NP-Za-km-z]{3}"
PUBKEY_CHECKSUM_PATTERN = "^{0}:{1}$".format(PUBKEY_PATTERN, CHECKSUM_PATTERN) PUBKEY_CHECKSUM_PATTERN = "^{0}:{1}$".format(PUBKEY_PATTERN, CHECKSUM_PATTERN)
def check_public_key(pubkey, display_error): def is_pubkey_and_check(uid_pubkey):
""" """
Check public key format checks if the given arguments contains a pubkey.
Check pubkey checksum which could be append after the pubkey If so, verifies the checksum if needed and returns the pubkey.
If check pass: return pubkey Exits if the checksum is wrong.
Else, return False
""" """
if re.search(re.compile(PUBKEY_DELIMITED_PATTERN), pubkey): if re.search(re.compile(PUBKEY_PATTERN), uid_pubkey):
return pubkey if has_pubkey_checksum(uid_pubkey, True):
elif re.search(re.compile(PUBKEY_CHECKSUM_PATTERN), pubkey): return check_public_key(uid_pubkey)
pubkey, checksum = pubkey.split(":") return uid_pubkey
checksum_calculed = gen_checksum(pubkey)
if checksum_calculed == checksum:
return pubkey
else:
print("Error: Wrong checksum for following public key:")
return False return False
elif display_error:
print("Error: bad format for following public key:", pubkey) def has_pubkey_checksum(pubkey, display_error=True):
"""
Checks if a pubkey has a checksum.
Exits if the pubkey is invalid.
"""
if re.search(re.compile(PUBKEY_DELIMITED_PATTERN), pubkey):
return False return False
elif re.search(re.compile(PUBKEY_CHECKSUM_PATTERN), pubkey):
return True
elif display_error:
message_exit("Error: bad format for following public key: " + pubkey)
return
def check_public_key(pubkey_checksum):
"""
Check pubkey checksum which could be append after the pubkey
If check pass: return pubkey
"""
pubkey, checksum = pubkey_checksum.split(":")
if checksum == gen_checksum(pubkey):
return pubkey
message_exit("Error: Wrong checksum for following public key: " + pubkey)
def gen_checksum(pubkey): def gen_checksum(pubkey):
......
...@@ -22,7 +22,10 @@ from silkaj.network_tools import ClientInstance ...@@ -22,7 +22,10 @@ from silkaj.network_tools import ClientInstance
from silkaj.blockchain_tools import HeadBlock from silkaj.blockchain_tools import HeadBlock
from silkaj.tools import CurrencySymbol, message_exit, coroutine from silkaj.tools import CurrencySymbol, message_exit, coroutine
from silkaj.auth import auth_method from silkaj.auth import auth_method
from silkaj.wot import check_public_key
# had to import wot to prevent loop dependency. No use here.
from silkaj import wot
from silkaj.crypto_tools import has_pubkey_checksum, check_public_key
from silkaj.tui import display_amount from silkaj.tui import display_amount
from duniterpy.api.bma import tx, blockchain from duniterpy.api.bma import tx, blockchain
...@@ -43,17 +46,19 @@ async def cmd_amount(ctx, pubkeys): ...@@ -43,17 +46,19 @@ async def cmd_amount(ctx, pubkeys):
): ):
if not pubkeys: if not pubkeys:
message_exit("You should specify one or many pubkeys") message_exit("You should specify one or many pubkeys")
pubkey_list = list()
for pubkey in pubkeys: for pubkey in pubkeys:
pubkey = check_public_key(pubkey, True) if has_pubkey_checksum(pubkey):
if not pubkey: pubkey_list.append(check_public_key(pubkey))
return else:
pubkey_list.append(pubkey)
total = [0, 0] total = [0, 0]
for pubkey in pubkeys: for pubkey in pubkey_list:
inputs_balance = await get_amount_from_pubkey(pubkey) inputs_balance = await get_amount_from_pubkey(pubkey)
await show_amount_from_pubkey(pubkey, inputs_balance) await show_amount_from_pubkey(pubkey, inputs_balance)
total[0] += inputs_balance[0] total[0] += inputs_balance[0]
total[1] += inputs_balance[1] total[1] += inputs_balance[1]
if len(pubkeys) > 1: if len(pubkey_list) > 1:
await show_amount_from_pubkey("Total", total) await show_amount_from_pubkey("Total", total)
else: else:
key = auth_method() key = auth_method()
......
...@@ -24,7 +24,7 @@ from click import command, option, FloatRange ...@@ -24,7 +24,7 @@ from click import command, option, FloatRange
from silkaj.cli_tools import MutuallyExclusiveOption from silkaj.cli_tools import MutuallyExclusiveOption
from silkaj.network_tools import ClientInstance from silkaj.network_tools import ClientInstance
from silkaj.blockchain_tools import HeadBlock from silkaj.blockchain_tools import HeadBlock
from silkaj.crypto_tools import check_public_key from silkaj.crypto_tools import check_public_key, has_pubkey_checksum
from silkaj.tools import message_exit, CurrencySymbol, coroutine from silkaj.tools import message_exit, CurrencySymbol, coroutine
from silkaj.auth import auth_method from silkaj.auth import auth_method
from silkaj import money from silkaj import money
...@@ -204,14 +204,11 @@ def check_transaction_values( ...@@ -204,14 +204,11 @@ def check_transaction_values(
""" """
checkComment(comment) checkComment(comment)
for i, outputAddress in enumerate(outputAddresses): for i, outputAddress in enumerate(outputAddresses):
outputAddresses[i] = check_public_key(outputAddress, True) if has_pubkey_checksum(outputAddress):
if not outputAddresses[i]: outputAddresses[i] = check_public_key(outputAddress)
message_exit(outputAddress)
if outputBackChange: if outputBackChange:
pubkey = outputBackChange if has_pubkey_checksum(outputBackChange):
outputBackChange = check_public_key(outputBackChange, True) outputBackChange = check_public_key(outputBackChange)
if not outputBackChange:
message_exit(pubkey)
if enough_source: if enough_source:
message_exit( message_exit(
issuer_pubkey + " pubkey doesn’t have enough money for this transaction." issuer_pubkey + " pubkey doesn’t have enough money for this transaction."
......
...@@ -24,7 +24,7 @@ from duniterpy.documents.transaction import Transaction ...@@ -24,7 +24,7 @@ from duniterpy.documents.transaction import Transaction
from silkaj.network_tools import ClientInstance from silkaj.network_tools import ClientInstance
from silkaj.tools import coroutine from silkaj.tools import coroutine
from silkaj.tui import convert_time from silkaj.tui import convert_time
from silkaj.crypto_tools import check_public_key from silkaj.crypto_tools import check_public_key, has_pubkey_checksum
from silkaj.wot import identity_of, identities_from_pubkeys from silkaj.wot import identity_of, identities_from_pubkeys
from silkaj.money import get_amount_from_pubkey, amount_in_current_base, UDValue from silkaj.money import get_amount_from_pubkey, amount_in_current_base, UDValue
from silkaj.tools import CurrencySymbol from silkaj.tools import CurrencySymbol
...@@ -35,8 +35,8 @@ from silkaj.tools import CurrencySymbol ...@@ -35,8 +35,8 @@ from silkaj.tools import CurrencySymbol
@option("--uids", "-u", is_flag=True, help="Display uids") @option("--uids", "-u", is_flag=True, help="Display uids")
@coroutine @coroutine
async def transaction_history(pubkey, uids): async def transaction_history(pubkey, uids):
if not check_public_key(pubkey, True): if has_pubkey_checksum(pubkey):
return pubkey = check_public_key(pubkey)
client = ClientInstance().client client = ClientInstance().client
ud_value = await UDValue().ud_value ud_value = await UDValue().ud_value
......
...@@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License ...@@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>. along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
""" """
import re
import click import click
from time import time from time import time
from tabulate import tabulate from tabulate import tabulate
...@@ -24,7 +25,7 @@ from duniterpy.api.bma import wot, blockchain ...@@ -24,7 +25,7 @@ from duniterpy.api.bma import wot, blockchain
from duniterpy.api.errors import DuniterError from duniterpy.api.errors import DuniterError
from silkaj.network_tools import ClientInstance from silkaj.network_tools import ClientInstance
from silkaj.crypto_tools import check_public_key from silkaj.crypto_tools import is_pubkey_and_check
from silkaj.tools import message_exit, coroutine from silkaj.tools import message_exit, coroutine
from silkaj.tui import convert_time from silkaj.tui import convert_time
from silkaj.blockchain_tools import BlockchainParams from silkaj.blockchain_tools import BlockchainParams
...@@ -159,7 +160,10 @@ def date_approximation(block_id, time_first_block, avgentime): ...@@ -159,7 +160,10 @@ def date_approximation(block_id, time_first_block, avgentime):
@coroutine @coroutine
async def id_pubkey_correspondence(id_pubkey): async def id_pubkey_correspondence(id_pubkey):
client = ClientInstance().client client = ClientInstance().client
if check_public_key(id_pubkey, False): # determine if id_pubkey is a pubkey
checked_pubkey = is_pubkey_and_check(id_pubkey)
if checked_pubkey:
id_pubkey = checked_pubkey
try: try:
idty = await identity_of(id_pubkey) idty = await identity_of(id_pubkey)
print( print(
...@@ -169,6 +173,7 @@ async def id_pubkey_correspondence(id_pubkey): ...@@ -169,6 +173,7 @@ async def id_pubkey_correspondence(id_pubkey):
) )
except: except:
message_exit("No matching identity") message_exit("No matching identity")
# if not ; then it is a uid
else: else:
pubkeys = await wot_lookup(id_pubkey) pubkeys = await wot_lookup(id_pubkey)
print("Public keys found matching '{}':\n".format(id_pubkey)) print("Public keys found matching '{}':\n".format(id_pubkey))
......
...@@ -19,7 +19,7 @@ import pytest ...@@ -19,7 +19,7 @@ import pytest
from silkaj import crypto_tools from silkaj import crypto_tools
# test gen_checksum
@pytest.mark.parametrize( @pytest.mark.parametrize(
"pubkey, checksum", "pubkey, checksum",
[ [
...@@ -28,3 +28,86 @@ from silkaj import crypto_tools ...@@ -28,3 +28,86 @@ from silkaj import crypto_tools
) )
def test_gen_checksum(pubkey, checksum): def test_gen_checksum(pubkey, checksum):
assert checksum == crypto_tools.gen_checksum(pubkey) assert checksum == crypto_tools.gen_checksum(pubkey)
# test check_pubkey
@pytest.mark.parametrize(
"pubkey, checksum, expected",
[
("J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX", "KAv", None),
(
"J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX",
"KA",
"Error: Wrong checksum for following public key: J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX",
),
],
)
def test_check_pubkey(pubkey, checksum, expected, capsys):
pubkey_with_ck = str(pubkey + ":" + checksum)
if expected == None:
assert pubkey == crypto_tools.check_public_key(pubkey_with_ck)
else:
with pytest.raises(SystemExit) as pytest_exit:
test = crypto_tools.check_public_key(pubkey_with_ck)
assert capsys.readouterr() == expected
assert pytest_exit.type == SystemExit
# test has_pubkey_checksum
@pytest.mark.parametrize(
"pubkey, display_error, expected",
[
("J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX:KAv", True, True),
("J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX", True, False),
("Youpi", False, None),
("Youpi", True, "Error: bad format for following public key: Youpi"),
],
)
def test_has_pubkey_checksum(pubkey, display_error, expected, capsys):
if isinstance(expected, str):
with pytest.raises(SystemExit) as pytest_exit:
test = crypto_tools.has_pubkey_checksum(pubkey, display_error)
assert capsys.readouterr() == expected
assert pytest_exit.type == SystemExit
else:
assert expected == crypto_tools.has_pubkey_checksum(pubkey, display_error)
# test is_pubkey_and_check
@pytest.mark.parametrize(
"uid_pubkey, expected",
[
(
"J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX:KAv",
"J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX",
),
(
"J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX",
"J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX",
),
("Youpi", False),
],
)
def test_is_pubkey_and_check(uid_pubkey, expected):
assert expected == crypto_tools.is_pubkey_and_check(uid_pubkey)
# test is_pubkey_and_check errors
@pytest.mark.parametrize(
"uid_pubkey, expected",
[
(
"J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX:KA",
"Error: bad format for following public key: J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX:KA",
),
(
"J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX:KAt",
"Error: Wrong checksum for following public key: J4c8CARmP9vAFNGtHRuzx14zvxojyRWHW2darguVqjtX",
),
],
)
def test_is_pubkey_and_check(uid_pubkey, expected, capsys):
with pytest.raises(SystemExit) as pytest_exit:
test = crypto_tools.is_pubkey_and_check(uid_pubkey)
assert capsys.readouterr() == expected
assert pytest_exit.type == SystemExit
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment