58 lines
1.4 KiB
Go
58 lines
1.4 KiB
Go
// 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
|
|
}
|