Updated EIP712 filtering signature specs to start with a magic number

Making it impossible for a signature of one type to be valid as another
This commit is contained in:
Alexandre Paillier
2022-08-17 10:45:43 +02:00
parent 3ee1fa419a
commit 9e4df4b655
4 changed files with 23 additions and 2 deletions

View File

@@ -816,19 +816,21 @@ If activated, fields will be by default hidden unless they receive a field name
Name substitution commands should come right after the contract address from the domain has been sent with a *SEND STRUCT IMPLEMENTATION*. Name substitution commands should come right after the contract address from the domain has been sent with a *SEND STRUCT IMPLEMENTATION*.
Perfect moment to do it is when the domain implementation has been sent, just before sending the message implementation. Perfect moment to do it is when the domain implementation has been sent, just before sending the message implementation.
The first byte is used so that a signature of one type cannot be valid as another type.
The signature is computed on : The signature is computed on :
chain ID (BE) || contract address || schema hash || display name 183 || chain ID (BE) || contract address || schema hash || display name
##### Field name substitution ##### Field name substitution
Name substitution commands should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). Name substitution commands should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones).
The first byte is used so that a signature of one type cannot be valid as another type.
The signature is computed on : The signature is computed on :
chain ID (BE) || contract address || schema hash || field path || display name 72 || chain ID (BE) || contract address || schema hash || field path || display name
#### Coding #### Coding

View File

@@ -65,6 +65,20 @@ static bool verify_filtering_signature(uint8_t dname_length,
cx_sha256_init(&hash_ctx); cx_sha256_init(&hash_ctx);
// Magic number, makes it so a signature of one type can't be used as another
switch (type) {
case FILTERING_STRUCT_FIELD:
hash_byte(FILTERING_MAGIC_STRUCT_FIELD, (cx_hash_t *) &hash_ctx);
break;
case FILTERING_CONTRACT_NAME:
hash_byte(FILTERING_MAGIC_CONTRACT_NAME, (cx_hash_t *) &hash_ctx);
break;
default:
apdu_response_code = APDU_RESPONSE_INVALID_DATA;
PRINTF("Invalid filtering type when verifying signature!\n");
return false;
}
// Chain ID // Chain ID
chain_id = __builtin_bswap64(eip712_context->chain_id); chain_id = __builtin_bswap64(eip712_context->chain_id);
hash_nbytes((uint8_t *) &chain_id, sizeof(chain_id), (cx_hash_t *) &hash_ctx); hash_nbytes((uint8_t *) &chain_id, sizeof(chain_id), (cx_hash_t *) &hash_ctx);

View File

@@ -6,6 +6,9 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#define FILTERING_MAGIC_CONTRACT_NAME 0b10110111 // 183
#define FILTERING_MAGIC_STRUCT_FIELD 0b01001000 // ~183 = 72
typedef enum { FILTERING_CONTRACT_NAME, FILTERING_STRUCT_FIELD } e_filtering_type; typedef enum { FILTERING_CONTRACT_NAME, FILTERING_STRUCT_FIELD } e_filtering_type;
bool provide_filtering_info(const uint8_t *const payload, uint8_t length, e_filtering_type type); bool provide_filtering_info(const uint8_t *const payload, uint8_t length, e_filtering_type type);

View File

@@ -246,6 +246,7 @@ def send_filtering_contract_name(display_name: str):
global sig_ctx global sig_ctx
msg = bytearray() msg = bytearray()
msg.append(183)
msg += sig_ctx["chainid"] msg += sig_ctx["chainid"]
msg += sig_ctx["caddr"] msg += sig_ctx["caddr"]
msg += sig_ctx["schema_hash"] msg += sig_ctx["schema_hash"]
@@ -262,6 +263,7 @@ def send_filtering_field_name(display_name):
path_str = ".".join(current_path) path_str = ".".join(current_path)
msg = bytearray() msg = bytearray()
msg.append(72)
msg += sig_ctx["chainid"] msg += sig_ctx["chainid"]
msg += sig_ctx["caddr"] msg += sig_ctx["caddr"]
msg += sig_ctx["schema_hash"] msg += sig_ctx["schema_hash"]