Skip to content

pallet_revive: Change address derivation to use hashing#7662

Merged
athei merged 5 commits intomasterfrom
at/amapping
Feb 28, 2025
Merged

pallet_revive: Change address derivation to use hashing#7662
athei merged 5 commits intomasterfrom
at/amapping

Conversation

@athei
Copy link
Member

@athei athei commented Feb 21, 2025

Fixes #6723

Motivation

Internal auditors recommended to not truncate Polkadot Addresses when deriving Ethereum addresses from it. Reasoning is that they are raw public keys where truncating could lead to collisions when weaknesses in those curves are discovered in the future. Additionally, some pallets generate account addresses in a way where only the suffix we were truncating contains any entropy. The changes in this PR act as a safe guard against those two points.

Changes made

We change the to_address function to first hash the AccountId32 and then use trailing 20 bytes as AccountId20. If the AccountId32 ends with 12x 0xEE we keep our current behaviour of just truncating those trailing bytes.

Security Discussion

This will allow us to still recover the original AccountId20 because those are constructed by just adding those 12 bytes. Please note that generating an ed25519 key pair where the trailing 12 bytes are 0xEE is theoretically possible as 96bits is not a huge search space. However, this cannot be used as an attack vector. It will merely allow this address to interact with pallet_revive without registering as the fallback account is the same as the actual address. The ultimate vanity address. In practice, this is not relevant since the 0xEE addresses are not valid public keys for sr25519 which is used almost everywhere.

tl:dr: We keep truncating in case of an Ethereum address derived account id. This is safe as those are already derived via keccak. In every other case where we have to assume that the account id might be a public key. Therefore we first hash and then take the trailing bytes.

Do we need a Migration for Westend

No. We changed the name of the mapping. This means the runtime will not try to read the old data. Ethereum keys are unaffected by this change. We just advise people to re-register their AccountId32 in case they need to use it as it is a very small circle of users (just 3 addresses registered). This will not cause disturbance on Westend.

@athei athei added the T7-smart_contracts This PR/Issue is related to smart contracts. label Feb 21, 2025
Comment on lines -31 to +32
let eve = [5u8; 20];
api::terminate(&eve);
input!(beneficiary: &[u8; 20],);
api::terminate(&beneficiary);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code made assumptions about how the address is derived. So it had to be changed.

} else {
// this is an (ed|sr)25510 derived address
// avoid truncating the public key by hashing it first
let account_hash = blake2_256(account_bytes);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blake2 is faster. Eth code will never need to deal with this hash so it is fine to not use keccak.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auditors recommended to move to keccak to be consistent with other protocols. While not strictly necessary it is just out of caution. Performance should not matter as we are just hashing a few bytes.

@athei
Copy link
Member Author

athei commented Feb 21, 2025

/cmd prdoc --audience runtime_dev --bump major

@paritytech-workflow-stopper
Copy link

All GitHub workflows were cancelled due to failure one of the required jobs.
Failed workflow url: https://github.com/paritytech/polkadot-sdk/actions/runs/13457612073
Failed job name: build-rustdoc

Copy link
Contributor

@pgherveou pgherveou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, glad we don't even need a migration

Copy link
Contributor

@TorstenStueber TorstenStueber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

ethabi = { workspace = true }
ethereum-types = { workspace = true, features = ["codec", "rlp", "serialize"] }
hex = { workspace = true }
hex-literal = { workspace = true }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please use array-bytes as used in the rest of the code base?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both seem to be widely used in the code base. Should we transition away from hex-literal?

alexander:~/Developer/polkadot-sdk% cargo tree -i hex-literal --depth 1 | wc -l
      22
alexander:~/Developer/polkadot-sdk% cargo tree -i array-bytes --depth 1 | wc -l
      34

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point we tried to push for array-bytes, but all the other are coming back over time :P

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just looked into array-bytes. It is not a replacement since it does the conversion at runtime. But we often need it at compile time as literal. Or do you mean the hex crate? I removed the direct dependency but we are still indirectly depending on it via ethereum-types. We will move away eventually to the newer alloy crates.

@athei athei mentioned this pull request Feb 25, 2025
6 tasks
@athei
Copy link
Member Author

athei commented Feb 28, 2025

Moved back to keccak as hash after consultation with auditors.

@athei athei added this pull request to the merge queue Feb 28, 2025
Merged via the queue into master with commit 4087e2d Feb 28, 2025
247 of 254 checks passed
@athei athei deleted the at/amapping branch February 28, 2025 13:48
athei added a commit that referenced this pull request Mar 3, 2025
Fixes #6723

Internal auditors recommended to not truncate Polkadot Addresses when
deriving Ethereum addresses from it. Reasoning is that they are raw
public keys where truncating could lead to collisions when weaknesses in
those curves are discovered in the future. Additionally, some pallets
generate account addresses in a way where only the suffix we were
truncating contains any entropy. The changes in this PR act as a safe
guard against those two points.

We change the `to_address` function to first hash the AccountId32 and
then use trailing 20 bytes as `AccountId20`. If the `AccountId32` ends
with 12x 0xEE we keep our current behaviour of just truncating those
trailing bytes.

This will allow us to still recover the original `AccountId20` because
those are constructed by just adding those 12 bytes. Please note that
generating an ed25519 key pair where the trailing 12 bytes are 0xEE is
theoretically possible as 96bits is not a huge search space. However,
this cannot be used as an attack vector. It will merely allow this
address to interact with `pallet_revive` without registering as the
fallback account is the same as the actual address. The ultimate vanity
address. In practice, this is not relevant since the 0xEE addresses are
not valid public keys for sr25519 which is used almost everywhere.

tl:dr: We keep truncating in case of an Ethereum address derived account
id. This is safe as those are already derived via keccak. In every other
case where we have to assume that the account id might be a public key.
Therefore we first hash and then take the trailing bytes.

No. We changed the name of the mapping. This means the runtime will not
try to read the old data. Ethereum keys are unaffected by this change.
We just advise people to re-register their AccountId32 in case they need
to use it as it is a very small circle of users (just 3 addresses
registered). This will not cause disturbance on Westend.

---------

Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@patriciobcs patriciobcs moved this from Backlog to Audited in Security Audit (PRs) - Parity Security Mar 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T7-smart_contracts This PR/Issue is related to smart contracts.

Projects

Development

Successfully merging this pull request may close these issues.

Audit Address mapping

5 participants