Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 11 additions & 42 deletions curve.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,8 @@ package secp256k1
import (
"crypto/elliptic"
"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"

const (
// number of bits in a big.Word
wordBits = 32 << (uint64(^big.Word(0)) >> 63)
Expand Down Expand Up @@ -133,7 +126,18 @@ func (BitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.

// Add returns the sum of (x1,y1) and (x2,y2)
func (BitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
// If one point is at infinity, return the other point.
// Adding the point at infinity to any point will preserve the other point.
if x1.Sign() == 0 && y1.Sign() == 0 {
return x2, y2
}
if x2.Sign() == 0 && y2.Sign() == 0 {
return x1, y1
}
z := new(big.Int).SetInt64(1)
if x1.Cmp(x2) == 0 && y1.Cmp(y2) == 0 {
return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z))
}
return BitCurve.affineFromJacobian(BitCurve.addJacobian(x1, y1, z, x2, y2, z))
}

Expand Down Expand Up @@ -242,41 +246,6 @@ func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
return x3, y3, z3
}

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
}

// ScalarBaseMult returns k*G, where G is the base point of the group and k is
// an integer in big-endian form.
func (BitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
Expand Down
2 changes: 2 additions & 0 deletions panic_cb.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be found in
// the LICENSE file.

// +build !gofuzz cgo

package secp256k1

import "C"
Expand Down
56 changes: 56 additions & 0 deletions scalar_mult_cgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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.

// +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
}
13 changes: 13 additions & 0 deletions scalar_mult_nocgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// 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.

// +build gofuzz !cgo

package secp256k1

import "math/big"

func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
panic("ScalarMult is not available when secp256k1 is built without cgo")
}
2 changes: 2 additions & 0 deletions secp256.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be found in
// the LICENSE file.

// +build !gofuzz cgo

// Package secp256k1 wraps the bitcoin secp256k1 C library.
package secp256k1

Expand Down