github.com/arjunbeliever/ignite@v0.0.0-20220406110515-46bbbbec2587/crypto/secp256k1/scalar_mult_cgo.go (about)

     1  // Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  // +build !gofuzz
     6  // +build cgo
     7  
     8  package secp256k1
     9  
    10  import (
    11  	"math/big"
    12  	"unsafe"
    13  )
    14  
    15  /*
    16  
    17  #include "libsecp256k1/include/secp256k1.h"
    18  
    19  extern int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, const unsigned char *point, const unsigned char *scalar);
    20  
    21  */
    22  import "C"
    23  
    24  func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
    25  	// Ensure scalar is exactly 32 bytes. We pad always, even if
    26  	// scalar is 32 bytes long, to avoid a timing side channel.
    27  	if len(scalar) > 32 {
    28  		panic("can't handle scalars > 256 bits")
    29  	}
    30  	// NOTE: potential timing issue
    31  	padded := make([]byte, 32)
    32  	copy(padded[32-len(scalar):], scalar)
    33  	scalar = padded
    34  
    35  	// Do the multiplication in C, updating point.
    36  	point := make([]byte, 64)
    37  	readBits(Bx, point[:32])
    38  	readBits(By, point[32:])
    39  
    40  	pointPtr := (*C.uchar)(unsafe.Pointer(&point[0]))
    41  	scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0]))
    42  	res := C.secp256k1_ext_scalar_mul(context, pointPtr, scalarPtr)
    43  
    44  	// Unpack the result and clear temporaries.
    45  	x := new(big.Int).SetBytes(point[:32])
    46  	y := new(big.Int).SetBytes(point[32:])
    47  	for i := range point {
    48  		point[i] = 0
    49  	}
    50  	for i := range padded {
    51  		scalar[i] = 0
    52  	}
    53  	if res != 1 {
    54  		return nil, nil
    55  	}
    56  	return x, y
    57  }