2

I'm trying to split a private key into shares using tinysig but am having difficulty. I.e. I'm trying to create an MPC wallet.

Ultimately I want to generate a private key, split it into two shares, A and B. Then, to sign a transaction, I first sign with the A share, and secondly, with the B share. When these two signatures are combined, the resulting signature should be exactly the same as if I had signed the transaction with the whole private key. If I understand correctly, this is how MPC wallets work; the private key is never used for transactions, except when being split into shares.

I'm following the tinysig demo here. In the __init__ of the ThresholdSignature class, a private and public key pair are generated using the paillier library:

ecdsa_setup = ECDSASetup(curve="P-256")
ecnil = ThresholdSignature(N, C, setup=ecdsa_setup)

digging deeper into the paillier library shows that the default key size when generating keys is 3072.

If I try to find out the client's private key in the ecnil object, I see something like this:

>>> ecnil.clients[0].he_private_key.p
1322540765134244050371558100270455080768241889825994905711046398184532557104286689136295277284168173854372246435905653838526464280537545493894139213411679655515088520049467017464526077811636444175659304736362528466466788629548227450207765055215007479912989709924853834845148824534623329793593949387411494503721018866801854037655742139763213075725258583416032422034089664742984187737249851052791666117076311431407610324513278720182788419411449665024038573592513723
>>> ecnil.clients[0].he_private_key.q
2284723268498922442467539110301303113041396131923481892914304164561860516362704406582357150386060442220415604374817669817782608284218360611971475754798359898054270836755192466701829211135957771688507906420521463101430090812282615974325344598670919411450138371876632456288671211630413157360230608646088568665029609192353084475386230592428901701657079883001218882863749314535183212389843720395778273220367267835720610100215510411774932266742652445986156432050732757

If i try to convert that to an address using web3, it doesn't work because the size of the int is not correct:

from web3 import Web3
from eth_account import Account
web3 = Web3()
acct = Account.from_key(web3.toHex(2284723268498922442467539110301303113041396131923481892914304164561860516362704406582357150386060442220415604374817669817782608284218360611971475754798359898054270836755192466701829211135957771688507906420521463101430090812282615974325344598670919411450138371876632456288671211630413157360230608646088568665029609192353084475386230592428901701657079883001218882863749314535183212389843720395778273220367267835720610100215510411774932266742652445986156432050732757))

ValueError: The private key must be exactly 32 bytes long, instead of 386 bytes.

So, if I modify the src file tecdsa.py of tinysig to generate a private key of the correct length (this line)

pub_key, priv_key = paillier.generate_paillier_keypair(n_length=512)

Then the he_private_key.q and he_private_key.p integers are the correct size to generate a valid ethereum wallet address, but I get an OverFlow error later in the process:

from tinysig.setup import DSASetup, ECDSASetup
from tinysig.tecdsa import ThresholdSignature
N,C=3,1
ecdsa_setup = ECDSASetup(curve="P-256")
ecnil = ThresholdSignature(N, C, setup=ecdsa_setup)
client_id = 1
ecnil.distributed_key_generation_protocol(client_id)
ecnil.ts_prep_protocol(client_id)
message = 'hello world'
ecnil.ts_online_protocol(message, client_id)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "tinysig/tecdsa.py", line 794, in ts_online_protocol
    self.decrypt_reconstruct_unmask_verify_sig_local(message, label_enc_sig, client)
  File "tinysig/tecdsa.py", line 738, in decrypt_reconstruct_unmask_verify_sig_local
    dec_sh_per_node = [client.he_private_key.decrypt(enc_sh) for enc_sh in enc_sh_per_node]
  File "tinysig/tecdsa.py", line 738, in <listcomp>
    dec_sh_per_node = [client.he_private_key.decrypt(enc_sh) for enc_sh in enc_sh_per_node]
  File "phe/paillier.py", line 291, in decrypt
    return encoded.decode()
  File "phe/encoding.py", line 221, in decode
    raise OverflowError('Overflow detected in decrypted number')
OverflowError: Overflow detected in decrypted number
>>> 

Any idea how I can use tinysig to a) generate a valid ethereum private key and b) split that key into shares which can be used in combination to sign transactions?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.