Problem: Public key type not verfied during validation

Solution: Validate public key type and write correspoding tests
This commit is contained in:
Vanshdeep Singh 2018-09-05 12:21:49 +02:00
parent 3811e9ff74
commit bda1fb7708
9 changed files with 55 additions and 9 deletions

View File

@ -125,7 +125,7 @@ def run_upsert_validator_new(args, bigchain):
new_validator = { new_validator = {
'public_key': {'value': public_key_from_base64(args.public_key), 'public_key': {'value': public_key_from_base64(args.public_key),
'type': 'ed25519-base58'}, 'type': 'ed25519-base16'},
'power': args.power, 'power': args.power,
'node_id': args.node_id 'node_id': args.node_id
} }

View File

@ -112,3 +112,7 @@ class UnequalValidatorSet(ValidationError):
class InvalidPowerChange(ValidationError): class InvalidPowerChange(ValidationError):
"""Raised if proposed power change in validator set is >=1/3 total power""" """Raised if proposed power change in validator set is >=1/3 total power"""
class InvalidPublicKey(ValidationError):
"""Raised if proposed power change in validator set is >=1/3 total power"""

View File

@ -19,7 +19,9 @@ from bigchaindb.common.schema import (_validate_schema,
TX_SCHEMA_COMMON, TX_SCHEMA_COMMON,
TX_SCHEMA_CREATE) TX_SCHEMA_CREATE)
from . import ValidatorElectionVote from . import ValidatorElectionVote
from .validator_utils import (new_validator_set, encode_validator) from .validator_utils import (new_validator_set,
encode_validator,
validate_asset_public_key)
class ValidatorElection(Transaction): class ValidatorElection(Transaction):
@ -155,6 +157,7 @@ class ValidatorElection(Transaction):
_validate_schema(TX_SCHEMA_COMMON, tx) _validate_schema(TX_SCHEMA_COMMON, tx)
_validate_schema(TX_SCHEMA_CREATE, tx) _validate_schema(TX_SCHEMA_CREATE, tx)
_validate_schema(TX_SCHEMA_VALIDATOR_ELECTION, tx) _validate_schema(TX_SCHEMA_VALIDATOR_ELECTION, tx)
validate_asset_public_key(tx['asset']['data']['public_key'])
@classmethod @classmethod
def create(cls, tx_signers, recipients, metadata=None, asset=None): def create(cls, tx_signers, recipients, metadata=None, asset=None):

View File

@ -1,8 +1,11 @@
import codecs import codecs
import base64
import binascii
from abci.types_pb2 import (Validator, from abci.types_pb2 import (Validator,
PubKey) PubKey)
from bigchaindb.tendermint_utils import public_key_to_base64 from bigchaindb.tendermint_utils import public_key_to_base64
from bigchaindb.common.exceptions import InvalidPublicKey
def encode_validator(v): def encode_validator(v):
@ -35,3 +38,24 @@ def new_validator_set(validators, updates):
new_validators_dict = {**validators_dict, **updates_dict} new_validators_dict = {**validators_dict, **updates_dict}
return list(new_validators_dict.values()) return list(new_validators_dict.values())
def validate_asset_public_key(pk):
pk_binary = pk['value'].encode('utf-8')
encoding = pk['type']
decoder = base64.b64decode
if encoding == 'ed25519-base16':
decoder = base64.b16decode
elif encoding == 'ed25519-base32':
decoder = base64.b32decode
elif encoding == 'ed25519-base64':
decoder = base64.b64decode
try:
pk_decoded = decoder(pk_binary)
if len(pk_decoded) != 32:
raise InvalidPublicKey('Public key should be of size 32 bytes')
except binascii.Error as e:
raise InvalidPublicKey('Invalid `type` specified for public key `value`')

View File

@ -352,7 +352,7 @@ def test_upsert_validator_new_with_tendermint(b, priv_validator_path, user_sk, v
from bigchaindb.commands.bigchaindb import run_upsert_validator_new from bigchaindb.commands.bigchaindb import run_upsert_validator_new
new_args = Namespace(action='new', new_args = Namespace(action='new',
public_key='8eJ8q9ZQpReWyQT5aFCiwtZ5wDZC4eDnCen88p3tQ6ie', public_key='HHG0IQRybpT6nJMIWWFWhMczCLHt6xcm7eP52GnGuPY=',
power=1, power=1,
node_id='unique_node_id_for_test_upsert_validator_new_with_tendermint', node_id='unique_node_id_for_test_upsert_validator_new_with_tendermint',
sk=priv_validator_path, sk=priv_validator_path,
@ -429,6 +429,7 @@ def test_upsert_validator_new_election_invalid_power(caplog, b, priv_validator_p
assert caplog.records[0].msg.__class__ == InvalidPowerChange assert caplog.records[0].msg.__class__ == InvalidPowerChange
@pytest.mark.google
@pytest.mark.abci @pytest.mark.abci
def test_upsert_validator_approve_with_tendermint(b, priv_validator_path, user_sk, validators): def test_upsert_validator_approve_with_tendermint(b, priv_validator_path, user_sk, validators):
from bigchaindb.commands.bigchaindb import (run_upsert_validator_new, from bigchaindb.commands.bigchaindb import (run_upsert_validator_new,
@ -443,6 +444,7 @@ def test_upsert_validator_approve_with_tendermint(b, priv_validator_path, user_s
config={}) config={})
election_id = run_upsert_validator_new(new_args, b) election_id = run_upsert_validator_new(new_args, b)
assert election_id
args = Namespace(action='approve', args = Namespace(action='approve',
election_id=election_id, election_id=election_id,

View File

@ -687,6 +687,6 @@ def new_validator():
node_id = 'fake_node_id' node_id = 'fake_node_id'
return {'public_key': {'value': public_key, return {'public_key': {'value': public_key,
'type': 'ed25519-base58'}, 'type': 'ed25519-base16'},
'power': power, 'power': power,
'node_id': node_id} 'node_id': node_id}

View File

@ -419,10 +419,10 @@ def test_new_validator_set(b):
'value': 'FxjS2/8AFYoIUqF6AcePTc87qOT7e4WGgH+sGCpTUDQ='}, 'value': 'FxjS2/8AFYoIUqF6AcePTc87qOT7e4WGgH+sGCpTUDQ='},
'voting_power': 10} 'voting_power': 10}
node1_new_power = {'public_key': {'value': '1718D2DBFF00158A0852A17A01C78F4DCF3BA8E4FB7B8586807FAC182A535034', node1_new_power = {'public_key': {'value': '1718D2DBFF00158A0852A17A01C78F4DCF3BA8E4FB7B8586807FAC182A535034',
'type': 'ed25519-base58'}, 'type': 'ed25519-base16'},
'power': 20} 'power': 20}
node2 = {'public_key': {'value': '1888A353B181715CA2554701D06C1665BC42C5D936C55EA9C5DBCBDB8B3F02A3', node2 = {'public_key': {'value': '1888A353B181715CA2554701D06C1665BC42C5D936C55EA9C5DBCBDB8B3F02A3',
'type': 'ed25519-base58'}, 'type': 'ed25519-base16'},
'power': 10} 'power': 10}
validators = [node1] validators = [node1]

View File

@ -24,6 +24,19 @@ def test_upsert_validator_valid_election(b_mock, new_validator, node_key):
assert election.validate(b_mock) assert election.validate(b_mock)
def test_upsert_validator_invalid_election_public_key(b_mock, new_validator, node_key):
from bigchaindb.common.exceptions import InvalidPublicKey
for iv in ['ed25519-base32', 'ed25519-base64']:
new_validator['public_key']['type'] = iv
voters = ValidatorElection.recipients(b_mock)
with pytest.raises(InvalidPublicKey):
ValidatorElection.generate([node_key.public_key],
voters,
new_validator, None).sign([node_key.private_key])
def test_upsert_validator_invalid_power_election(b_mock, new_validator, node_key): def test_upsert_validator_invalid_power_election(b_mock, new_validator, node_key):
voters = ValidatorElection.recipients(b_mock) voters = ValidatorElection.recipients(b_mock)
new_validator['power'] = 30 new_validator['power'] = 30

View File

@ -238,7 +238,7 @@ def test_upsert_validator(b, node_key, node_keys, ed25519_node_keys):
power = 1 power = 1
public_key = '9B3119650DF82B9A5D8A12E38953EA47475C09F0C48A4E6A0ECE182944B24403' public_key = '9B3119650DF82B9A5D8A12E38953EA47475C09F0C48A4E6A0ECE182944B24403'
public_key64 = public_key_to_base64(public_key) public_key64 = public_key_to_base64(public_key)
new_validator = {'public_key': {'value': public_key, 'type': 'ed25519-base58'}, new_validator = {'public_key': {'value': public_key, 'type': 'ed25519-base16'},
'node_id': 'some_node_id', 'node_id': 'some_node_id',
'power': power} 'power': power}
@ -280,7 +280,7 @@ def test_get_validator_update(b, node_keys, node_key, ed25519_node_keys):
power = 1 power = 1
public_key = '9B3119650DF82B9A5D8A12E38953EA47475C09F0C48A4E6A0ECE182944B24403' public_key = '9B3119650DF82B9A5D8A12E38953EA47475C09F0C48A4E6A0ECE182944B24403'
public_key64 = public_key_to_base64(public_key) public_key64 = public_key_to_base64(public_key)
new_validator = {'public_key': {'value': public_key, 'type': 'ed25519-base58'}, new_validator = {'public_key': {'value': public_key, 'type': 'ed25519-base16'},
'node_id': 'some_node_id', 'node_id': 'some_node_id',
'power': power} 'power': power}
voters = ValidatorElection.recipients(b) voters = ValidatorElection.recipients(b)
@ -315,7 +315,7 @@ def test_get_validator_update(b, node_keys, node_key, ed25519_node_keys):
# remove validator # remove validator
power = 0 power = 0
new_validator = {'public_key': {'value': public_key, 'type': 'ed25519-base58'}, new_validator = {'public_key': {'value': public_key, 'type': 'ed25519-base16'},
'node_id': 'some_node_id', 'node_id': 'some_node_id',
'power': power} 'power': power}
voters = ValidatorElection.recipients(b) voters = ValidatorElection.recipients(b)