6c36218ef3
Use Non-Adjacent Form (NAF) of large numbers to reduce ScalarMult computation times. Preliminary results indicate around a 8-9% speed improvement according to BenchmarkScalarMult. The algorithm used is 3.77 from Guide to Elliptical Curve Crytography by Hankerson, et al. This closes #3
73 lines
2.4 KiB
Go
73 lines
2.4 KiB
Go
// Copyright (c) 2014-2015 Conformal Systems LLC.
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// This file is ignored during the regular build due to the following build tag.
|
|
// This build tag is set during go generate.
|
|
// +build gensecp256k1
|
|
|
|
package btcec
|
|
|
|
import "encoding/binary"
|
|
|
|
// secp256k1BytePoints are dummy points used so the code which generates the
|
|
// real values can compile.
|
|
var secp256k1BytePoints = []byte{}
|
|
|
|
// getDoublingPoints returns all the possible G^(2^i) for i in
|
|
// 0..n-1 where n is the curve's bit size (256 in the case of secp256k1)
|
|
// the coordinates are recorded as Jacobian coordinates.
|
|
func (curve *KoblitzCurve) getDoublingPoints() [][3]fieldVal {
|
|
doublingPoints := make([][3]fieldVal, curve.BitSize)
|
|
|
|
// initialize px, py, pz to the Jacobian coordinates for the base point
|
|
px, py := curve.bigAffineToField(curve.Gx, curve.Gy)
|
|
pz := new(fieldVal).SetInt(1)
|
|
for i := 0; i < bitSize; i++ {
|
|
doublingPoints[i] = [3]fieldVal{*px, *py, *pz}
|
|
// P = 2*P
|
|
curve.doubleJacobian(px, py, pz, px, py, pz)
|
|
}
|
|
return doublingPoints
|
|
}
|
|
|
|
// SerializedBytePoints returns a serialized byte slice which contains all of
|
|
// the possible points per 8-bit window. This is used to when generating
|
|
// secp256k1.go.
|
|
func (curve *KoblitzCurve) SerializedBytePoints() []byte {
|
|
doublingPoints := curve.getDoublingPoints()
|
|
|
|
// Segregate the bits into byte-sized windows
|
|
serialized := make([]byte, curve.byteSize*256*3*10*4)
|
|
offset := 0
|
|
for byteNum := 0; byteNum < curve.byteSize; byteNum++ {
|
|
// Grab the 8 bits that make up this byte from doublingPoints.
|
|
startingBit := 8 * (curve.byteSize - byteNum - 1)
|
|
computingPoints := doublingPoints[startingBit : startingBit+8]
|
|
|
|
// Compute all points in this window and serialize them.
|
|
for i := 0; i < 256; i++ {
|
|
px, py, pz := new(fieldVal), new(fieldVal), new(fieldVal)
|
|
for j := 0; j < 8; j++ {
|
|
if i>>uint(j)&1 == 1 {
|
|
curve.addJacobian(px, py, pz, &computingPoints[j][0],
|
|
&computingPoints[j][1], &computingPoints[j][2], px, py, pz)
|
|
}
|
|
}
|
|
for i := 0; i < 10; i++ {
|
|
binary.LittleEndian.PutUint32(serialized[offset:], px.n[i])
|
|
offset += 4
|
|
}
|
|
for i := 0; i < 10; i++ {
|
|
binary.LittleEndian.PutUint32(serialized[offset:], py.n[i])
|
|
offset += 4
|
|
}
|
|
for i := 0; i < 10; i++ {
|
|
binary.LittleEndian.PutUint32(serialized[offset:], pz.n[i])
|
|
offset += 4
|
|
}
|
|
}
|
|
}
|
|
|
|
return serialized
|
|
}
|