// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved. // Use of this source code is governed by a BSD-style license that can be found in // the LICENSE file. //go:build !gofuzz && cgo // +build !gofuzz,cgo package secp256k1 import ( "math/big" "unsafe" ) /* #include "libsecp256k1/include/secp256k1.h" extern int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, const unsigned char *point, const unsigned char *scalar); */ import "C" func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { // Ensure scalar is exactly 32 bytes. We pad always, even if // scalar is 32 bytes long, to avoid a timing side channel. if len(scalar) > 32 { panic("can't handle scalars > 256 bits") } // NOTE: potential timing issue padded := make([]byte, 32) copy(padded[32-len(scalar):], scalar) scalar = padded // Do the multiplication in C, updating point. point := make([]byte, 64) readBits(Bx, point[:32]) readBits(By, point[32:]) pointPtr := (*C.uchar)(unsafe.Pointer(&point[0])) scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0])) res := C.secp256k1_ext_scalar_mul(context, pointPtr, scalarPtr) // Unpack the result and clear temporaries. x := new(big.Int).SetBytes(point[:32]) y := new(big.Int).SetBytes(point[32:]) for i := range point { point[i] = 0 } for i := range padded { scalar[i] = 0 } if res != 1 { return nil, nil } return x, y }