Image for post
Image for post

The ECDSA signature method is used to sign a message with a private key. So rather than sharing the signature, could we give a share of the signature to a number of nodes, and who must come together to share the signature, and they can only recover it if enough hosts come together to share their shares. In this case, we will use Shamir Secret Shares (SSS). We thus have n shares, and where we can recover the share using t nodes:

Image for post
Image for post

For ECDSA, Alice signs the message with the following:

Bob will check with:

The following is an outline of the code [here]:

import sys
import random
import hashlib
import libnum
import tss
from tss import share_secret, Hash
import base64
from secp256k1 import curve,scalar_mult,point_addmsg="Hello"
thres=3
n_shares=6
if (len(sys.argv)>1):
msg=(sys.argv[1])
if (len(sys.argv)>2):
thres=int(sys.argv[2])
if (len(sys.argv)>3):
shares=int(sys.argv[3])
# Alice's key pair (dA,QA)
dA = random.randint(0, curve.n-1)
QA = scalar_mult(dA,curve.g)
h=int(hashlib.sha256(msg.encode()).hexdigest(),16)k = random.randint(0, curve.n-1)rpoint = scalar_mult(k,curve.g)r = rpoint[0] % curve.n# Bob takes m and (r,s) and checks
inv_k = libnum.invmod(k,curve.n)
s = (inv_k*(h+r*dA)) % curve.nprint (f"Msg: {msg}\n\nAlice's private key={dA}\nAlice's public key={QA}\nk= {k}\n\nr={r}\ns={s}")# To check signatureinv_s = libnum.invmod(s,curve.n)
c = inv_s
u1=(h*c) % curve.n
u2=(r*c) % curve.n
P = point_add(scalar_mult(u1,curve.g), scalar_mult(u2,QA))
res = P[0] % curve.n
print (f"\nResult r={res}")
if (res==r):
print("Signature matches!")
## The signature is (r,s). For shares - we only do for r here secret=r
shares = tss.share_secret(thres, n_shares, secret, 'my-id', Hash.NONE)
print ("Using t shares")
reconstructed_secret = tss.reconstruct_secret(shares[0:thres])
print ("Secret:\t",secret)print ("===Shares===")
for x in range (0,thres):
print (base64.b64encode(shares[x]))
print ("\nReconstructed:\t",reconstructed_secret.decode())
print ("\nNow sharing s")
secret=s
shares = tss.share_secret(thres, n_shares, secret, 'my-id', Hash.NONE)
reconstructed_secret = tss.reconstruct_secret(shares[0:thres])print ("Secret:\t",secret)print ("===Shares (showing a few)===")
for x in range (0,thres):
print (base64.b64encode(shares[x]))
print ("\nReconstructed:\t",reconstructed_secret.decode())

And a sample run [here]:

Msg: HelloAlice's private key=24717110312959500398894080358434843509578578934054314213246494970478133031767
Alice's public key=(87531740538625017975357079156707681014534748755964202251330009337208067796042, 38148151312816124635784137975068946355154271184135375253990123903870980798553)
k= 67679870494495400649203854546733381935582201499769568232654302572052878179396
r=76175175749926314353139927368125446231633516634661818556116920398835217992524
s=46725313239594522980520655465965498046518288553336671629019598746369932257443
Result r=76175175749926314353139927368125446231633516634661818556116920398835217992524
Signature matches!
Using t shares
Secret: 76175175749926314353139927368125446231633516634661818556116920398835217992524
===Shares===
b'bXktaWQAAAAAAAAAAAAAAAAEAE4BVSwdX3EMTA6I8KFFdd3EUriKEgYNVeOrWTkARvfVxBJ8R6idLd1N5ZEIDGvBsYdLJNbYE9FA5AOrvOz2DhQS6rssZkHDpbUgcCI+Epk='
b'bXktaWQAAAAAAAAAAAAAAAAEAE4C6EBufzWPi11wwRDsFUsolGM8GubYne4Dj3wELfPm7smOqiq36mwOv5pSuH6kyhKJFnPA+edd5psN/nfxtobPry/hozUnr5GbelMyad8='
b'bXktaWQAAAAAAAAAAAAAAAAEAE4DkAEXLPYL7vVAAgEOkF7v7sOZNdcZIjUmZWe5YAnO+3w7Ds7V/lkZltHIdvLPqnOt21JB1ASGPji6wmxqfhulv5J1zTPu2aWVjg1+jAg='
b'bXktaWQAAAAAAAAAAAAAAAAEAE4ELXn7gKHc5BQTKjlRX5Z9GJcFVBgakWM2Hvk0yD/9LrVjRvBzq7NiZBS7kZXLaOXEaD6KcE1bj4tXtqzh2CX1BwuWkQrIk8knMUBkNXU='
Reconstructed: 76175175749926314353139927368125446231633516634661818556116920398835217992524Now sharing s
Secret: 46725313239594522980520655465965498046518288553336671629019598746369932257443
===Shares (showing a few)===
b'bXktaWQAAAAAAAAAAAAAAAAEAE4BGv+HC/FCsk7v/nloTwCoxc+7G4VzHlgUMTaetUl0DWL43ECmDQxtw4JObiKGV3E6VN7qTvNX1JQ/tZWk44P0hVtyqh9eg/ZXKsqlOVc='
b'bXktaWQAAAAAAAAAAAAAAAAEAE4CS+Gjz4YOcEemlhJSxCvtRfGNVT8MHd6yzDTlop4JUF7fZU/ENCbofsbqc1GkqmkvLr4BdyXGDl9amd6KPODub8quj8/RC8MBwanEWNI='
b'bXktaWQAAAAAAAAAAAAAAAAEAE4Du/ST0MGxmd6JcahoWITgcIr9lRUXFWxVDFg5I6e3tE9vJ0MpAU+JVL5EEMZrD7hhO/4NkGWMEndNf7owciLBH7CrU3zi0slSOp3ywU4='
b'bXktaWQAAAAAAAAAAAAAAAAEAE4EXNJ7FxpZkaqJzAkPO+TiU7GMXbRtTUXV/CYhPxyPtNUotzbkF41iOxzzto/7klso2tL8JMUvN8PUSXNUSF9Kh3pJduEWIRkIvNryypo='
Reconstructed: 46725313239594522980520655465965498046518288553336671629019598746369932257443

And the code:

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. EU Citizen. Auld Reekie native. Old World Breaker. New World Creator.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store