github.com/incognitochain/go-incognito-sdk@v1.0.1/privacy/point.go (about)

     1  package privacy
     2  
     3  import (
     4  	"crypto/subtle"
     5  	"encoding/hex"
     6  	"errors"
     7  	"fmt"
     8  	C25519 "github.com/incognitochain/go-incognito-sdk/privacy/curve25519"
     9  )
    10  
    11  type Point struct {
    12  	key C25519.Key
    13  }
    14  
    15  func RandomPoint() *Point {
    16  	sc := RandomScalar()
    17  	return new(Point).ScalarMultBase(sc)
    18  }
    19  
    20  func (p Point) PointValid() bool {
    21  	var point C25519.ExtendedGroupElement
    22  	return point.FromBytes(&p.key)
    23  }
    24  
    25  func (p Point) GetKey() C25519.Key {
    26  	return p.key
    27  }
    28  
    29  func (p *Point) SetKey(a *C25519.Key) (*Point, error) {
    30  	if p == nil {
    31  		p = new(Point)
    32  	}
    33  	p.key = *a
    34  
    35  	var point C25519.ExtendedGroupElement
    36  	if !point.FromBytes(&p.key) {
    37  		return nil, errors.New("Invalid point value")
    38  	}
    39  	return p, nil
    40  }
    41  
    42  func (p *Point) Set(q *Point) *Point {
    43  	if p == nil {
    44  		p = new(Point)
    45  	}
    46  	p.key = q.key
    47  	return p
    48  }
    49  
    50  func (p Point) MarshalText() []byte {
    51  	return []byte(fmt.Sprintf("%x", p.key[:]))
    52  }
    53  
    54  func (p *Point) UnmarshalText(data []byte) (*Point, error) {
    55  	if p == nil {
    56  		p = new(Point)
    57  	}
    58  
    59  	byteSlice, _ := hex.DecodeString(string(data))
    60  	if len(byteSlice) != Ed25519KeySize {
    61  		return nil, errors.New("Incorrect key size")
    62  	}
    63  	copy(p.key[:], byteSlice)
    64  	return p, nil
    65  }
    66  
    67  func (p Point) ToBytes() [Ed25519KeySize]byte {
    68  	return p.key.ToBytes()
    69  }
    70  
    71  func (p Point) ToBytesS() []byte {
    72  	slice := p.key.ToBytes()
    73  	return slice[:]
    74  }
    75  
    76  func (p *Point) FromBytes(b [Ed25519KeySize]byte) (*Point, error) {
    77  	if p == nil {
    78  		p = new(Point)
    79  	}
    80  	p.key.FromBytes(b)
    81  
    82  	var point C25519.ExtendedGroupElement
    83  	if !point.FromBytes(&p.key) {
    84  		return nil, errors.New("Invalid point value")
    85  	}
    86  
    87  	return p, nil
    88  }
    89  
    90  func (p *Point) FromBytesS(b []byte) (*Point, error) {
    91  	if len(b) != Ed25519KeySize {
    92  		return nil, errors.New("Invalid Ed25519 Key Size")
    93  	}
    94  
    95  	if p == nil {
    96  		p = new(Point)
    97  	}
    98  	var array [Ed25519KeySize]byte
    99  	copy(array[:], b)
   100  	p.key.FromBytes(array)
   101  
   102  	var point C25519.ExtendedGroupElement
   103  	if !point.FromBytes(&p.key) {
   104  		return nil, errors.New("Invalid point value")
   105  	}
   106  
   107  	return p, nil
   108  }
   109  
   110  func (p *Point) Identity() *Point {
   111  	if p == nil {
   112  		p = new(Point)
   113  	}
   114  	p.key = C25519.Identity
   115  	return p
   116  }
   117  
   118  func (p Point) IsIdentity() bool {
   119  	if p.key == C25519.Identity {
   120  		return true
   121  	}
   122  	return false
   123  }
   124  
   125  // does a * G where a is a scalar and G is the curve basepoint
   126  func (p *Point) ScalarMultBase(a *Scalar) *Point {
   127  	if p == nil {
   128  		p = new(Point)
   129  	}
   130  	key := C25519.ScalarmultBase(&a.key)
   131  	p.key = *key
   132  	return p
   133  }
   134  
   135  func (p *Point) ScalarMult(pa *Point, a *Scalar) *Point {
   136  	if p == nil {
   137  		p = new(Point)
   138  	}
   139  	key := C25519.ScalarMultKey(&pa.key, &a.key)
   140  	p.key = *key
   141  	return p
   142  }
   143  
   144  func (p *Point) MultiScalarMultCached(scalarLs []*Scalar, pointPreComputedLs [][8]C25519.CachedGroupElement) *Point {
   145  	nSc := len(scalarLs)
   146  
   147  	if nSc != len(pointPreComputedLs) {
   148  		panic("Cannot MultiscalarMul with different size inputs")
   149  	}
   150  
   151  	scalarKeyLs := make([]*C25519.Key, nSc)
   152  	for i := 0; i < nSc; i++ {
   153  		scalarKeyLs[i] = &scalarLs[i].key
   154  	}
   155  	key := C25519.MultiScalarMultKeyCached(pointPreComputedLs, scalarKeyLs)
   156  	res, _ := new(Point).SetKey(key)
   157  	return res
   158  }
   159  
   160  func (p *Point) MultiScalarMult(scalarLs []*Scalar, pointLs []*Point) *Point {
   161  	nSc := len(scalarLs)
   162  	nPoint := len(pointLs)
   163  
   164  	if nSc != nPoint {
   165  		panic("Cannot MultiscalarMul with different size inputs")
   166  	}
   167  
   168  	scalarKeyLs := make([]*C25519.Key, nSc)
   169  	pointKeyLs := make([]*C25519.Key, nSc)
   170  	for i := 0; i < nSc; i++ {
   171  		scalarKeyLs[i] = &scalarLs[i].key
   172  		pointKeyLs[i] = &pointLs[i].key
   173  	}
   174  	key := C25519.MultiScalarMultKey(pointKeyLs, scalarKeyLs)
   175  	res, _ := new(Point).SetKey(key)
   176  	return res
   177  }
   178  
   179  func (p *Point) InvertScalarMultBase(a *Scalar) *Point {
   180  	if p == nil {
   181  		p = new(Point)
   182  	}
   183  	inv := new(Scalar).Invert(a)
   184  	p.ScalarMultBase(inv)
   185  	return p
   186  }
   187  
   188  func (p *Point) InvertScalarMult(pa *Point, a *Scalar) *Point {
   189  	inv := new(Scalar).Invert(a)
   190  	p.ScalarMult(pa, inv)
   191  	return p
   192  }
   193  
   194  func (p *Point) Derive(pa *Point, a *Scalar, b *Scalar) *Point {
   195  	c := new(Scalar).Add(a, b)
   196  	return p.InvertScalarMult(pa, c)
   197  }
   198  
   199  func (p *Point) Add(pa, pb *Point) *Point {
   200  	if p == nil {
   201  		p = new(Point)
   202  	}
   203  	res := p.key
   204  	C25519.AddKeys(&res, &pa.key, &pb.key)
   205  	p.key = res
   206  	return p
   207  }
   208  
   209  // aA + bB
   210  func (p *Point) AddPedersen(a *Scalar, A *Point, b *Scalar, B *Point) *Point {
   211  	if p == nil {
   212  		p = new(Point)
   213  	}
   214  
   215  	var A_Precomputed [8]C25519.CachedGroupElement
   216  	Ae := new(C25519.ExtendedGroupElement)
   217  	Ae.FromBytes(&A.key)
   218  	C25519.GePrecompute(&A_Precomputed, Ae)
   219  
   220  	var B_Precomputed [8]C25519.CachedGroupElement
   221  	Be := new(C25519.ExtendedGroupElement)
   222  	Be.FromBytes(&B.key)
   223  	C25519.GePrecompute(&B_Precomputed, Be)
   224  
   225  	var key C25519.Key
   226  	C25519.AddKeys3_3(&key, &a.key, &A_Precomputed, &b.key, &B_Precomputed)
   227  	p.key = key
   228  	return p
   229  }
   230  
   231  func (p *Point) AddPedersenCached(a *Scalar, APreCompute [8]C25519.CachedGroupElement, b *Scalar, BPreCompute [8]C25519.CachedGroupElement) *Point {
   232  	if p == nil {
   233  		p = new(Point)
   234  	}
   235  
   236  	var key C25519.Key
   237  	C25519.AddKeys3_3(&key, &a.key, &APreCompute, &b.key, &BPreCompute)
   238  	p.key = key
   239  	return p
   240  }
   241  
   242  func (p *Point) Sub(pa, pb *Point) *Point {
   243  	if p == nil {
   244  		p = new(Point)
   245  	}
   246  	res := p.key
   247  	C25519.SubKeys(&res, &pa.key, &pb.key)
   248  	p.key = res
   249  	return p
   250  }
   251  
   252  func IsPointEqual(pa *Point, pb *Point) bool {
   253  	tmpa := pa.ToBytesS()
   254  	tmpb := pb.ToBytesS()
   255  
   256  	return subtle.ConstantTimeCompare(tmpa, tmpb) == 1
   257  }
   258  
   259  func HashToPointFromIndex(index int64, padStr string) *Point {
   260  	array := C25519.GBASE.ToBytes()
   261  	msg := array[:]
   262  	msg = append(msg, []byte(padStr)...)
   263  	msg = append(msg, []byte(string(index))...)
   264  
   265  	keyHash := C25519.Key(C25519.Keccak256(msg))
   266  	keyPoint := keyHash.HashToPoint()
   267  
   268  	p, _ := new(Point).SetKey(keyPoint)
   269  	return p
   270  }
   271  
   272  func HashToPoint(b []byte) *Point {
   273  	keyHash := C25519.Key(C25519.Keccak256(b))
   274  	keyPoint := keyHash.HashToPoint()
   275  
   276  	p, _ := new(Point).SetKey(keyPoint)
   277  	return p
   278  }