golang pederson commitment 实现,基于椭圆曲线

golang 实现的EC pederson-commitment

EC 曲线使用的是 Edwards25519,由 go-ristretto 包提供,文档参考 https://pkg.go.dev/github.com/bwesterb/go-ristretto?tab=doc ,GitHub库 https://github.com/bwesterb/go-ristretto

另外参考了 https://github.com/threehook/go-pedersen-commitment 的实现,这里的封装是为了实现我自己的一些需求,同时也分享出来给需要的朋友

pederson-commitment 原论文可见 https://link.springer.com/content/pdf/10.1007%2F3-540-46766-1_9.pdf

下面直接上代码了,里面涉及到转字符串的都是是由标准库hex来转,要参考的话需要先导包 “github.com/bwesterb/go-ristretto” ,直接去github下来放到GOPATH下即可

package go_ec_pederson_commitment

import (
	"encoding/hex"
	"github.com/bwesterb/go-ristretto"
	"math/big"
)

/**
基于EC的 pederson commitment
原论文:Non-Interactive and Information-Theoretic Secure Verifiable Secret Sharing
在原论文里是基于循环群的实现,说的是g,h是群里的元素,没有人知道log_g(h)
对应到椭圆曲线的话,就是对G、H的要求是G和H是椭圆曲线上的点,没有人知道 H=aG 中a的值,那么G和H都采用随机选取的方式,应该是满足要求的?! 或者更简单的方式就是G使用基点,H随机选,这里采用都随机生成的方式
秘密x,随机数r, G和H是椭圆曲线上的随机的点, --> c = xG + rH
G,H 由被承诺方选定,r由承诺方选定
*/

//生成两个曲线上的点,用于计算承诺
func ParamsGen() (G, H ristretto.Point) {
	G.Rand()
	H.Rand()
	return G, H
}

func ParamsGenToString() (GString, HString string) {
	var G, H ristretto.Point
	G.Rand()
	H.Rand()
	GBytes, _ := G.MarshalText()
	HBytes, _ := H.MarshalText()
	GString = hex.EncodeToString(GBytes)
	HString = hex.EncodeToString(HBytes)
	return
}

//生成一个随机阶数
func RandomGen() (r ristretto.Scalar) {
	r.Rand()
	return r
}

func RandomGenToNumberString() string {
	var r ristretto.Scalar
	r.Rand()
	return r.BigInt().String()
}

//计算 秘密 的 Pederson 承诺, 返回曲线上的点
func Commit(G, H ristretto.Point, secret []byte, r ristretto.Scalar) (commit ristretto.Point) {
	var x ristretto.Scalar
	x.Derive(secret)
	//c = xG + rH
	var comm ristretto.Point
	comm.Add(G.ScalarMult(&G, &x), H.ScalarMult(&H, &r))
	return comm
}

//计算 秘密 的 Pederson 承诺, 返回字符串
func CommitToString(GString, HString, rString string, secret []byte) (commitString string, err error) {
	var G, H ristretto.Point
	GBytes, _ := hex.DecodeString(GString)
	HBytes, _ := hex.DecodeString(HString)
	err = G.UnmarshalText(GBytes)
	if err != nil {
		return "", err
	}
	err = H.UnmarshalText(HBytes)
	if err != nil {
		return "", err
	}
	var r ristretto.Scalar
	var bigInt big.Int
	bigInt.SetString(rString, 10)
	r.SetBigInt(&bigInt)

	comm := Commit(G, H, secret, r)
	bytes, err := comm.MarshalText()
	if err != nil {
		return "", err
	} else {
		commitString = hex.EncodeToString(bytes)
		return commitString, err
	}
}

//通过原始参数验证承诺
func Open(comm, G, H ristretto.Point, secret []byte, r ristretto.Scalar) bool {
	var x ristretto.Scalar
	x.Derive(secret)
	var calculateComm ristretto.Point
	calculateComm.Add(G.ScalarMult(&G, &x), H.ScalarMult(&H, &r))
	return calculateComm.Equals(&comm)
}

//通过Marshal和hex编码的字符串参数 以及big.Int转字符串得到的 r值 验证承诺
func OpenByString(commString, GString, HString, rString string, secret []byte) bool {
	var G, H, verifyComm ristretto.Point
	verifyCommBytes, _ := hex.DecodeString(commString)
	e := verifyComm.UnmarshalText(verifyCommBytes)
	if e != nil {
		return false
	}
	GBytes, _ := hex.DecodeString(GString)
	e = G.UnmarshalText(GBytes)
	if e != nil {
		return false
	}
	HBytes, _ := hex.DecodeString(HString)
	e = H.UnmarshalText(HBytes)
	if e != nil {
		return false
	}
	var r ristretto.Scalar
	var bigInt big.Int
	bigInt.SetString(rString, 10)
	r.SetBigInt(&bigInt)

	comm := Commit(G, H, secret, r)
	return verifyComm.Equals(&comm)
}

测试

package go_ec_pederson_commitment

import (
	"fmt"
	"testing"
)

func TestParamsGenToString(t *testing.T) {
	GString, HString := ParamsGenToString()
	fmt.Println(GString)
	fmt.Println(HString)
}

func TestRandomGenToNumberString(t *testing.T) {
	rString := RandomGenToNumberString()
	fmt.Println(rString)
}

func TestCommitToString(t *testing.T) {
	type args struct {
		GString string
		HString string
		rString string
		secret  []byte
	}
	tests := []struct {
		name             string
		args             args
		wantCommitString string
		wantErr          bool
	}{
		{
			name: "commit",
			args: args{
				"364732713438655479616d68564b713549766652396c744a7872344e7276545f2d5f5f736f514f79496d38",
				"49756256713151674b63304144486738416a50376c48756b4a7268566d6b5551574b6a626e6e456a62796b",
				"398891056723960618120827012073372943324213998153307115797995179191814376821",
				[]byte("this is the secret message to commit"),
			},
			wantCommitString: "",
			wantErr:          false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			gotCommitString, err := CommitToString(tt.args.GString, tt.args.HString, tt.args.rString, tt.args.secret)
			fmt.Println("commitment: " + gotCommitString)
			if (err != nil) != tt.wantErr {
				t.Errorf("CommitToString() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
/*			if gotCommitString != tt.wantCommitString {
				t.Errorf("CommitToString() = %v, want %v", gotCommitString, tt.wantCommitString)
			}*/
		})
	}
}

func TestOpenByString(t *testing.T) {
	GString := "364732713438655479616d68564b713549766652396c744a7872344e7276545f2d5f5f736f514f79496d38"
	HString := "49756256713151674b63304144486738416a50376c48756b4a7268566d6b5551574b6a626e6e456a62796b"
	rString := "398891056723960618120827012073372943324213998153307115797995179191814376821"
	commString := "7841426c71536e32476b77626a4a4f5836645078586175684f67546a50326650597a4c31695338434e7934"
	commString2 := "7841426c71536e32476b77626a4a4f5836645078586175684f67546a50326650597a4c31695338434e7934"
	commString3 := "22134sfdaaaa12"

	fmt.Println(OpenByString(commString, GString, HString, rString, []byte("this is the secret message to commit")))
	fmt.Println(OpenByString(commString2, GString, HString, rString, []byte("test ")))
	fmt.Println(OpenByString(commString3, GString, HString, rString, []byte("test ")))
}

你可能感兴趣的:(golang,密码学)