Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active July 12, 2023 13:00
Show Gist options
  • Save salrashid123/c936fcbaa40c403232351f67c17ee12f to your computer and use it in GitHub Desktop.
Save salrashid123/c936fcbaa40c403232351f67c17ee12f to your computer and use it in GitHub Desktop.
Threshold key generation and signing with serialization to file
package main
import (
"encoding/base64"
"flag"
"fmt"
"io/ioutil"
"os"
"go.dedis.ch/kyber/v3/pairing/bn256"
"go.dedis.ch/kyber/v3/share"
"go.dedis.ch/kyber/v3/sign/bls"
"go.dedis.ch/kyber/v3/sign/tbls"
)
var ()
func main() {
flag.Parse()
// test threshold key Threshold signing
msg := []byte("Hello threshold Boneh-Lynn-Shacham")
suite := bn256.NewSuite()
n := 3 // alice bob carols
t := 2 // atleast 2 of three
fmt.Printf("Using (t,n): (%d,%d)\n", t, n)
secret := suite.G1().Scalar().Pick(suite.RandomStream())
priPoly := share.NewPriPoly(suite.G2(), t, secret, suite.RandomStream())
pubPoly := priPoly.Commit(suite.G2().Point().Base())
pubbin, err := pubPoly.Commit().MarshalBinary()
if err != nil {
panic(err)
}
pubstr := base64.StdEncoding.EncodeToString(pubbin)
fmt.Printf("Public Key: %s\n", pubstr)
sigShares := make([][]byte, 0)
/// create key share and write to files
for i, x := range pubPoly.Shares(n) {
//fmt.Printf("PubShare x %d : %s\n", i, x.V.String())
ival := x.I
pval, err := x.V.MarshalBinary()
if err != nil {
panic(err)
}
fmt.Printf(" Public Key Share Index: %d\n", ival)
fmt.Printf(" Public Key Share: %s\n", base64.StdEncoding.EncodeToString(pval))
f, err := os.Create(fmt.Sprintf("%d.pub", i))
if err != nil {
panic(err)
}
_, err = f.Write(pval)
if err != nil {
panic(err)
}
f.Close()
}
for i, x := range priPoly.Shares(n) {
//fmt.Printf("PriShare %d : %s\n", i, x.String())
ival := x.I
pval, err := x.V.MarshalBinary()
if err != nil {
panic(err)
}
fmt.Printf(" Private Key Share Index: %d\n", ival)
fmt.Printf(" Private Key Share: %s\n", base64.StdEncoding.EncodeToString(pval))
f, err := os.Create(fmt.Sprintf("%d.priv", i))
if err != nil {
panic(err)
}
_, err = f.Write(pval)
if err != nil {
panic(err)
}
f.Close()
}
// load keys from files
priv_keys_index := []int{0, 1}
pub_keys_index := []int{0, 2}
ps := []*share.PriShare{}
pp := []*share.PubShare{}
for _, x := range pub_keys_index {
puval, err := ioutil.ReadFile(fmt.Sprintf("%d.pub", x))
if err != nil {
panic(err)
}
rpv := suite.G2().Point()
err = rpv.UnmarshalBinary(puval)
if err != nil {
panic(err)
}
rpr := &share.PubShare{
I: x,
V: rpv,
}
pp = append(pp, rpr)
}
for _, x := range priv_keys_index {
pval, err := ioutil.ReadFile(fmt.Sprintf("%d.priv", x))
if err != nil {
panic(err)
}
rv := suite.G2().Scalar()
err = rv.UnmarshalBinary(pval)
if err != nil {
panic(err)
}
rr := &share.PriShare{
I: x,
V: rv,
}
ps = append(ps, rr)
//fmt.Printf("Reconstructed PrivShare rr %d : %s\n", x, rr.V.String())
}
for _, x := range ps {
sig, err := tbls.Sign(suite, x, msg)
if err != nil {
panic(err)
}
//fmt.Printf("Share %d: %x\n", x, sig)
sigShares = append(sigShares, sig)
}
fmt.Printf("Partial Signatures:\n")
for _, x := range sigShares {
fmt.Printf(" %s\n", base64.StdEncoding.EncodeToString(x))
}
rps, err := share.RecoverPubPoly(suite.G2(), pp, t, n)
if err != nil {
panic(err)
}
sig, err := tbls.Recover(suite, rps, msg, sigShares, t, n)
if err != nil {
panic(err)
}
fmt.Printf("Signature from key index %v %s\n", priv_keys_index, base64.StdEncoding.EncodeToString(sig))
err = bls.Verify(suite, rps.Commit(), msg, sig)
if err != nil {
panic(err)
}
fmt.Printf("Signature Verified using Partial Public Keys from index %v\n", pub_keys_index)
b := suite.G2().Point()
pbin, err := base64.StdEncoding.DecodeString(pubstr)
if err != nil {
panic(err)
}
err = b.UnmarshalBinary(pbin)
if err != nil {
panic(err)
}
err = bls.Verify(suite, b, msg, sig)
if err != nil {
panic(err)
}
fmt.Println("Signature Verified From Full Public")
}
@salrashid123
Copy link
Author

Sample output of key generation and signatures with t,n=2,3

$ go run main.go 
Using (t,n):   (2,3)
Public Key:  SKwCfvuwyRPxvxcU/+1rpKq9asTyUWq3UUYOC74oys4HOdl+m+Uof7XYPyslyX+J7i6lkcyAXENK8VZBh6adwDoWKvHTrkXsVK9O7IOyY69gF/sWzyK0uz3RaQOfcexeQJAX13z5TApxUEuHuIs7eB++NaX1eiJACUxZosnKRZ0=
  Public Key Share Index: 0
  Public Key Share: c5M81sPtGl9Otea0TFx/G5a6wgh/it7+6wqspoLsg/MxEDX5t9a96NLQomggRuQ18ntpCYR7atvxUqg4qdUoAHOJF8STj916RSS5hHfSHydjVnWWXY9p3HenT8yPH45YWLfTQLEyEp+r0zgNjd0QynoZbT4DcZl5UD2za0PPGD0=
  Public Key Share Index: 1
  Public Key Share: HAbWgWbVvn6nUqOENe9rtXvXVK6zpLzssML8N/vTuTMwujPQ2mC5+lDO2QfbW3QbESuWzGd5aYHmrRYS+pk6sn/GSkt3T7zf0JfS7PXSk4Kt4dbix0nzff0fSSJmiYnHHd0Fhs+2omRR/k/vRjz/oRY5FX5RiY2az4BerHSOalY=
  Public Key Share Index: 2
  Public Key Share: QuQuaJ4uIAHx6CeAzbUisnwoH8zA1dNoTVgwmPnv/ex2juXZO0Vt/2wtnOSgopZ2In6dw1X+23oSevPQ6A/bs2O7E/73aTS5xwUaEqM8nQZRZFfZjsBkXUyUHUjdqihYJueHBVLsnqUxqvYBSz7iZXxYQv/C6fOrLcy/GQs0l0A=
  Private Key Share Index: 0
  Private Key Share: c7adJDYwiSC4zGyE3EGd0ZAhb9xufg98b5wwdNK++Gc=
  Private Key Share Index: 1
  Private Key Share: C/bIqUQGkiwE9zznChELj8vAwhfLORgOENW4KKoxuS8=
  Private Key Share Index: 2
  Private Key Share: M+v2EZyAIzD7kfoBmWVVbzXtomYgH1nDzD40N9lQ7Fg=
Partial Signatures:
   AAAZNo7nR4jTTcgzPkjvOgcWp5qArnF44Jc/8vqQAefe8nYcyQSFdeGss0lBAZmEgXiBmr6k55zh/VqkQnzH5isC
   AAFWRDTIu6gU4OmkYgoMJIfk+Pw6lEPVVVRaCRrA8rUm0wo3OXfIaWs3z+gN9SEPiXVlaUyN3Y3JCSFGMn2w7+Te
Signature from key index [0 1]  LbmtEGp8bKwlTPaEwGPY6nPh+VCVla7McxoMDztgi7KH51kP3gGHmv6mJUL5L89eiOb4FxeMAsnOgxsdDNNM1g==
Signature Verified using Partial Public Keys from index [0 2]
Signature Verified From Full Public

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment