├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── go.mod
├── go.sum
├── pedersen.go
└── pedersen_test.go
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, build with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Ton van de Ven
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | deps:
2 | go get -v github.com/bwesterb/go-ristretto
3 | go get -v github.com/stretchr/testify/assert
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # go-pedersen-commitment
2 | Go version of the Pedersen Commitment Scheme.
3 |
4 | This is a pure Go implementation of the Pedersen Commitment Scheme.
5 | It makes use of Bas Westerbaan's https://github.com/bwesterb/go-ristretto to create commitments.
6 | Pederson Commitments are used for Confidential Transactions. It uses Cryptography and Elliptic Curves to do that.
7 | You can read more about Commitments schemes right here: https://en.wikipedia.org/wiki/Commitment_scheme.
8 |
9 |
10 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/threehook/go-pedersen-commitment
2 |
3 | go 1.14
4 |
5 | require (
6 | github.com/bwesterb/go-ristretto v1.1.1
7 | github.com/stretchr/testify v1.5.1
8 | )
9 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/bwesterb/go-ristretto v1.1.1 h1:ScMQxfIReRWsrKhQ+rR9R4CoaS+9Mf+GqaGP8NQEEJg=
2 | github.com/bwesterb/go-ristretto v1.1.1/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
3 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
8 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
9 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
10 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
11 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
12 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
13 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
14 |
--------------------------------------------------------------------------------
/pedersen.go:
--------------------------------------------------------------------------------
1 | package pedersen
2 |
3 | import (
4 | "github.com/bwesterb/go-ristretto"
5 | "math/big"
6 | )
7 |
8 | // The prime order of the base point is 2^252 + 27742317777372353535851937790883648493.
9 | var n25519, _ = new(big.Int).SetString("7237005577332262213973186563042994240857116359379907606001950938285454250989", 10)
10 |
11 | // Commit to a value x
12 | // H - Random secondary point on the curve
13 | // r - Private key used as blinding factor
14 | // x - The value (number of tokens)
15 | func commitTo(H *ristretto.Point, r, x *ristretto.Scalar) ristretto.Point {
16 | //ec.g.mul(r).add(H.mul(x));
17 | var result, rPoint, transferPoint ristretto.Point
18 | rPoint.ScalarMultBase(r)
19 | transferPoint.ScalarMult(H, x)
20 | result.Add(&rPoint, &transferPoint)
21 | return result
22 | }
23 |
24 | // Generate a random point on the curve
25 | func generateH() ristretto.Point {
26 | var random ristretto.Scalar
27 | var H ristretto.Point
28 | random.Rand()
29 | H.ScalarMultBase(&random)
30 | return H
31 | }
32 |
33 | // Subtract two commitments using homomorphic encryption
34 | func Sub(cX, cY *ristretto.Point) ristretto.Point {
35 | var subPoint ristretto.Point
36 | subPoint.Sub(cX, cY)
37 | return subPoint
38 | }
39 |
40 | // Subtract two known values with blinding factors
41 | // and compute the committed value
42 | // add rX - rY (blinding factor private keys)
43 | // add vX - vY (hidden values)
44 | func SubPrivately(H *ristretto.Point, rX, rY *ristretto.Scalar, vX, vY *big.Int) ristretto.Point {
45 | var rDif ristretto.Scalar
46 | var vDif big.Int
47 | rDif.Sub(rY, rX)
48 | vDif.Sub(vX, vY)
49 | vDif.Mod(&vDif, n25519)
50 |
51 | var vScalar ristretto.Scalar
52 | var rPoint ristretto.Point
53 | vScalar.SetBigInt(&vDif)
54 |
55 | rPoint.ScalarMultBase(&rDif)
56 | var vPoint, result ristretto.Point
57 | vPoint.ScalarMult(H, &vScalar)
58 | result.Add(&rPoint, &vPoint)
59 | return result
60 | }
61 |
--------------------------------------------------------------------------------
/pedersen_test.go:
--------------------------------------------------------------------------------
1 | package pedersen
2 |
3 | import (
4 | "github.com/bwesterb/go-ristretto"
5 | "github.com/stretchr/testify/assert"
6 | "math/big"
7 | "testing"
8 | )
9 |
10 | // Should commit to a sum of two values
11 | func TestCommitToSuccess(t *testing.T) {
12 |
13 | var rX, rY, vX, vY ristretto.Scalar
14 | rX.Rand()
15 | H := generateH() // Secondary point on the Curve
16 | five := big.NewInt(5)
17 |
18 | // Transfer amount of 5 tokens
19 | tC := commitTo(&H, &rX, vX.SetBigInt(five))
20 |
21 | // Alice 10 - 5 = 5
22 | rY.Rand()
23 | ten := big.NewInt(10)
24 | aC1 := commitTo(&H, &rY, vY.SetBigInt(ten))
25 | assert.NotEqual(t, aC1, tC, "Should not be equal")
26 | var aC2 ristretto.Point
27 | aC2.Sub(&aC1, &tC)
28 |
29 | checkAC2 := SubPrivately(&H, &rX, &rY, ten, five)
30 | assert.True(t, checkAC2.Equals(&aC2), "Should be equal")
31 | }
32 |
33 | // Should fail if not using the correct blinding factors
34 | func TestCommitToFails(t *testing.T) {
35 |
36 | var rX, rY, vX, vY ristretto.Scalar
37 | rX.Rand()
38 | H := generateH() // Secondary point on the Curve
39 | five := big.NewInt(5)
40 |
41 | // Transfer amount of 5 tokens
42 | tC := commitTo(&H, &rX, vX.SetBigInt(five))
43 |
44 | // Alice 10 - 5 = 5
45 | rY.Rand()
46 | ten := big.NewInt(10)
47 | aC1 := commitTo(&H, &rY, vY.SetBigInt(ten))
48 | assert.NotEqual(t, aC1, tC, "They should not be equal")
49 | var aC2 ristretto.Point
50 | aC2.Sub(&aC1, &tC)
51 |
52 | // Create different (and wrong) binding factors
53 | rX.Rand()
54 | rY.Rand()
55 | checkAC2 := SubPrivately(&H, &rX, &rY, ten, five)
56 | assert.False(t, checkAC2.Equals(&aC2), "Should not be equal")
57 | }
58 |
--------------------------------------------------------------------------------