Skip to content

Commit 9126ab9

Browse files
committed
remove function selector computation logic
1 parent 2c0463c commit 9126ab9

3 files changed

Lines changed: 32 additions & 110 deletions

File tree

README.md

Lines changed: 12 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,14 @@ signature = sign(message, key)
199199

200200
- `signature`: The generated signature.
201201

202-
### 7. `build_input_text(plaintext, user_aes_key, sender, contract, func_sig, signing_key)`
202+
### 7. `build_input_text(plaintext, user_aes_key, sender, contract, func_selector, signing_key)`
203203

204204
**Purpose:** Builds input text by encrypting the plaintext and signing it.
205205

206206
**Usage:**
207207

208208
```python
209-
int_cipher_text, signature = build_input_text(plaintext, user_aes_key, sender, contract, func_sig, signing_key)
209+
int_cipher_text, signature = build_input_text(plaintext, user_aes_key, sender, contract, func_selector, signing_key)
210210
```
211211

212212
**Parameters:**
@@ -215,22 +215,22 @@ int_cipher_text, signature = build_input_text(plaintext, user_aes_key, sender, c
215215
- `user_aes_key`: The user's AES key.
216216
- `sender`: The sender's address.
217217
- `contract`: The contract address.
218-
- `func_sig`: The function signature.
218+
- `func_selector`: The function selector.
219219
- `signing_key`: The private key used for signing.
220220

221221
**Returns:**
222222

223223
- `int_cipher_text`: The integer representation of the ciphertext.
224224
- `signature`: The generated signature.
225225

226-
### 8. `build_string_input_text(plaintext, user_aes_key, sender, contract, func_sig, signing_key)`
226+
### 8. `build_string_input_text(plaintext, user_aes_key, sender, contract, func_selector, signing_key)`
227227

228228
**Purpose:** Builds input text by encrypting the plaintext and signing it.
229229

230230
**Usage:**
231231

232232
```python
233-
int_cipher_text, signature = build_string_input_text(plaintext, user_aes_key, sender, contract, func_sig, signing_key)
233+
int_cipher_text, signature = build_string_input_text(plaintext, user_aes_key, sender, contract, func_selector, signing_key)
234234
```
235235

236236
**Parameters:**
@@ -239,7 +239,7 @@ int_cipher_text, signature = build_string_input_text(plaintext, user_aes_key, se
239239
- `user_aes_key`: The user's AES key.
240240
- `sender`: The sender's address.
241241
- `contract`: The contract address.
242-
- `func_sig`: The function signature.
242+
- `func_selector`: The function selector.
243243
- `signing_key`: The private key used for signing.
244244

245245
**Returns:**
@@ -299,43 +299,7 @@ plaintext = decrypt_rsa(private_key_bytes, ciphertext)
299299

300300
- `plaintext`: The decrypted message.
301301

302-
### 12. `keccak256(data)`
303-
304-
**Purpose:** Computes the Keccak-256 hash of the provided data.
305-
306-
**Usage:**
307-
308-
```python
309-
hash_value = keccak256(data)
310-
```
311-
312-
**Parameters:**
313-
314-
- `data`: The data to be hashed.
315-
316-
**Returns:**
317-
318-
- `hash_value`: The computed hash.
319-
320-
### 13. `get_func_sig(function_signature)`
321-
322-
**Purpose:** Computes the function signature hash using Keccak-256.
323-
324-
**Usage:**
325-
326-
```python
327-
func_sig_hash = get_func_sig(function_signature)
328-
```
329-
330-
**Parameters:**
331-
332-
- `function_signature`: The function signature string.
333-
334-
**Returns:**
335-
336-
- `func_sig_hash`: The first 4 bytes of the computed hash.
337-
338-
### 14. `decrypt_uint(ciphertext, user_key)`
302+
### 12. `decrypt_uint(ciphertext, user_key)`
339303

340304
**Purpose:** Decrypts a value stored in a contract using a user key
341305

@@ -354,7 +318,7 @@ plaintext = decrypt_uint(ciphertext, user_key)
354318

355319
- `result`: The decrypted value.
356320

357-
### 15. `decrypt_string(ciphertext, user_key)`
321+
### 13. `decrypt_string(ciphertext, user_key)`
358322

359323
**Purpose:** Decrypts a value stored in a contract using a user key
360324

@@ -643,25 +607,7 @@ valid, gas_estimate = is_gas_units_estimation_valid(web3, tx)
643607
- `valid`: Boolean indicating if the gas units are sufficient.
644608
- `gas_estimate`: The estimated gas units.
645609

646-
### 16. `get_function_signature(function_abi)`
647-
648-
**Purpose:** Generates the function signature from the ABI.
649-
650-
**Usage:**
651-
652-
```python
653-
func_sig = get_function_signature(function_abi)
654-
```
655-
656-
**Parameters:**
657-
658-
- `function_abi`: The ABI of the function.
659-
660-
**Returns:**
661-
662-
- `func_sig`: The function signature.
663-
664-
### 17. `deploy_contract(contract, kwargs, tx_params)`
610+
### 16. `deploy_contract(contract, kwargs, tx_params)`
665611

666612
**Purpose:** Deploys a contract with the given parameters.
667613

@@ -681,7 +627,7 @@ tx_receipt = deploy_contract(contract, kwargs, tx_params)
681627

682628
- `tx_receipt`: The transaction receipt.
683629

684-
### 18. `exec_func_via_transaction(func, tx_params)`
630+
### 17. `exec_func_via_transaction(func, tx_params)`
685631

686632
**Purpose:** Executes a contract function via a transaction.
687633

@@ -700,7 +646,7 @@ tx_receipt = exec_func_via_transaction(func, tx_params)
700646

701647
- `tx_receipt`: The transaction receipt.
702648

703-
### 19. `sign_and_send_tx(web3, private_key, transaction)`
649+
### 18. `sign_and_send_tx(web3, private_key, transaction)`
704650

705651
**Purpose:** Signs and sends a transaction.
706652

@@ -720,7 +666,7 @@ tx_receipt = sign_and_send_tx(web3, private_key, transaction)
720666

721667
- `tx_receipt`: The transaction receipt.
722668

723-
### 20. `decrypt_value(contract_value, user_key)`
669+
### 19. `decrypt_value(contract_value, user_key)`
724670

725671
**Purpose:** Decrypts a value stored in a contract using a user key.
726672

coti/crypto_utils.py

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from Crypto.Cipher import AES
2-
from Crypto.Hash import keccak
32
from Crypto.Random import get_random_bytes
43
from cryptography.hazmat.primitives import hashes
54
from cryptography.hazmat.primitives import serialization
@@ -10,7 +9,7 @@
109

1110
block_size = AES.block_size
1211
address_size = 20
13-
func_sig_size = 4
12+
function_selector_size = 4
1413
ct_size = 32
1514
key_size = 32
1615

@@ -74,22 +73,24 @@ def generate_aes_key():
7473
return key
7574

7675

77-
def sign_input_text(sender, addr, func_sig, ct, key):
76+
def sign_input_text(sender, addr, function_selector, ct, key):
77+
function_selector_bytes = bytes.fromhex(function_selector[2:])
78+
7879
# Ensure all input sizes are the correct length
7980
if len(sender) != address_size:
8081
raise ValueError(f"Invalid sender address length: {len(sender)} bytes, must be {address_size} bytes")
8182
if len(addr) != address_size:
8283
raise ValueError(f"Invalid contract address length: {len(addr)} bytes, must be {address_size} bytes")
83-
if len(func_sig) != func_sig_size:
84-
raise ValueError(f"Invalid signature size: {len(func_sig)} bytes, must be {func_sig_size} bytes")
84+
if len(function_selector_bytes) != function_selector_size:
85+
raise ValueError(f"Invalid signature size: {len(function_selector_bytes)} bytes, must be {function_selector_size} bytes")
8586
if len(ct) != ct_size:
8687
raise ValueError(f"Invalid ct length: {len(ct)} bytes, must be {ct_size} bytes")
8788
# Ensure the key is the correct length
8889
if len(key) != key_size:
8990
raise ValueError(f"Invalid key length: {len(key)} bytes, must be {key_size} bytes")
9091

9192
# Create the message to be signed by appending all inputs
92-
message = sender + addr + func_sig + ct
93+
message = sender + addr + function_selector_bytes + ct
9394

9495
return sign(message, key)
9596

@@ -102,7 +103,7 @@ def sign(message, key):
102103
return signature
103104

104105

105-
def build_input_text(plaintext, user_aes_key, sender, contract, func_sig, signing_key):
106+
def build_input_text(plaintext, user_aes_key, sender, contract, function_selector, signing_key):
106107
sender_address_bytes = bytes.fromhex(sender.address[2:])
107108
contract_address_bytes = bytes.fromhex(contract.address[2:])
108109

@@ -113,18 +114,16 @@ def build_input_text(plaintext, user_aes_key, sender, contract, func_sig, signin
113114
ciphertext, r = encrypt(user_aes_key, plaintext_bytes)
114115
ct = ciphertext + r
115116

116-
# Create the function signature
117-
func_hash = get_func_sig(func_sig)
118117
# Sign the message
119-
signature = sign_input_text(sender_address_bytes, contract_address_bytes, func_hash, ct, signing_key)
118+
signature = sign_input_text(sender_address_bytes, contract_address_bytes, function_selector, ct, signing_key)
120119

121120
# Convert the ct to an integer
122121
int_cipher_text = int.from_bytes(ct, byteorder='big')
123122

124123
return int_cipher_text, signature
125124

126125

127-
def build_string_input_text(plaintext, user_aes_key, sender, contract, func_sig, signing_key):
126+
def build_string_input_text(plaintext, user_aes_key, sender, contract, function_selector, signing_key):
128127
input_text = {
129128
'ciphertext': {
130129
'value': []
@@ -145,7 +144,7 @@ def build_string_input_text(plaintext, user_aes_key, sender, contract, func_sig,
145144
user_aes_key,
146145
sender,
147146
contract,
148-
func_sig,
147+
function_selector,
149148
signing_key
150149
)
151150

@@ -173,10 +172,18 @@ def decrypt_uint(ciphertext, user_key):
173172

174173

175174
def decrypt_string(ciphertext, user_key):
175+
if 'value' in ciphertext or hasattr(ciphertext, 'value'): # format when reading ciphertext from an event
176+
__ciphertext = ciphertext['value']
177+
elif isinstance(ciphertext, tuple): # format when reading ciphertext from state variable
178+
__ciphertext = ciphertext[0]
179+
else:
180+
raise RuntimeError('Unrecognized ciphertext format')
181+
176182
decrypted_string = ""
177183

178-
for value in ciphertext['value']:
184+
for value in __ciphertext:
179185
decrypted = decrypt_uint(value, user_key)
186+
180187
byte_length = (decrypted.bit_length() + 7) // 8 # calculate the byte length
181188

182189
# Convert the integer to bytes
@@ -225,26 +232,3 @@ def decrypt_rsa(private_key_bytes, ciphertext):
225232
)
226233
)
227234
return plaintext
228-
229-
230-
# Function to compute Keccak-256 hash
231-
def keccak256(data):
232-
# Create Keccak-256 hash object
233-
hash_obj = keccak.new(digest_bits=256)
234-
235-
# Update hash object with data
236-
hash_obj.update(data)
237-
238-
# Compute hash and return
239-
return hash_obj.digest()
240-
241-
242-
def get_func_sig(function_signature):
243-
# Convert function signature to bytes
244-
function_signature_bytes = function_signature.encode('utf-8')
245-
246-
# Compute Keccak-256 hash on the function signature
247-
function_signature_bytes_hash = keccak256(function_signature_bytes)
248-
249-
# Take first 4 bytes of the hash
250-
return function_signature_bytes_hash[:4]

coti/utils.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,6 @@ def is_gas_units_estimation_valid(web3, tx):
111111
return False, estimate_gas
112112

113113

114-
def get_function_signature(function_abi):
115-
# Extract the input types from the ABI
116-
input_types = ','.join([param['type'] for param in function_abi.get('inputs', [])])
117-
118-
# Generate the function signature
119-
return f"{function_abi['name']}({input_types})"
120-
121-
122114
def deploy_contract(contract, kwargs, tx_params):
123115
func = contract.constructor(**kwargs)
124116
return exec_func_via_transaction(func, tx_params)

0 commit comments

Comments
 (0)