Commit 288c7b42 authored by George Hotz's avatar George Hotz

bring btcec into minigeth

parent 81bec775
btcec
=====
[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions)
[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
[![GoDoc](https://pkg.go.dev/github.com/btcsuite/btcd/btcec?status.png)](https://pkg.go.dev/github.com/btcsuite/btcd/btcec)
Package btcec implements elliptic curve cryptography needed for working with
Bitcoin (secp256k1 only for now). It is designed so that it may be used with the
standard crypto/ecdsa packages provided with go. A comprehensive suite of test
is provided to ensure proper functionality. Package btcec was originally based
on work from ThePiachu which is licensed under the same terms as Go, but it has
signficantly diverged since then. The btcsuite developers original is licensed
under the liberal ISC license.
Although this package was primarily written for btcd, it has intentionally been
designed so it can be used as a standalone package for any projects needing to
use secp256k1 elliptic curve cryptography.
## Installation and Updating
```bash
$ go get -u github.com/btcsuite/btcd/btcec
```
## Examples
* [Sign Message](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--SignMessage)
Demonstrates signing a message with a secp256k1 private key that is first
parsed form raw bytes and serializing the generated signature.
* [Verify Signature](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--VerifySignature)
Demonstrates verifying a secp256k1 signature against a public key that is
first parsed from raw bytes. The signature is also parsed from raw bytes.
* [Encryption](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--EncryptMessage)
Demonstrates encrypting a message for a public key that is first parsed from
raw bytes, then decrypting it using the corresponding private key.
* [Decryption](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--DecryptMessage)
Demonstrates decrypting a message using a private key that is first parsed
from raw bytes.
## GPG Verification Key
All official release tags are signed by Conformal so users can ensure the code
has not been tampered with and is coming from the btcsuite developers. To
verify the signature perform the following:
- Download the public key from the Conformal website at
https://opensource.conformal.com/GIT-GPG-KEY-conformal.txt
- Import the public key into your GPG keyring:
```bash
gpg --import GIT-GPG-KEY-conformal.txt
```
- Verify the release tag with the following command where `TAG_NAME` is a
placeholder for the specific tag:
```bash
git tag -v TAG_NAME
```
## License
Package btcec is licensed under the [copyfree](http://copyfree.org) ISC License
except for btcec.go and btcec_test.go which is under the same license as Go.
// Copyright 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"encoding/hex"
"testing"
)
// BenchmarkAddJacobian benchmarks the secp256k1 curve addJacobian function with
// Z values of 1 so that the associated optimizations are used.
func BenchmarkAddJacobian(b *testing.B) {
b.StopTimer()
x1 := new(fieldVal).SetHex("34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6")
y1 := new(fieldVal).SetHex("0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232")
z1 := new(fieldVal).SetHex("1")
x2 := new(fieldVal).SetHex("34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6")
y2 := new(fieldVal).SetHex("0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232")
z2 := new(fieldVal).SetHex("1")
x3, y3, z3 := new(fieldVal), new(fieldVal), new(fieldVal)
curve := S256()
b.StartTimer()
for i := 0; i < b.N; i++ {
curve.addJacobian(x1, y1, z1, x2, y2, z2, x3, y3, z3)
}
}
// BenchmarkAddJacobianNotZOne benchmarks the secp256k1 curve addJacobian
// function with Z values other than one so the optimizations associated with
// Z=1 aren't used.
func BenchmarkAddJacobianNotZOne(b *testing.B) {
b.StopTimer()
x1 := new(fieldVal).SetHex("d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718")
y1 := new(fieldVal).SetHex("5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190")
z1 := new(fieldVal).SetHex("2")
x2 := new(fieldVal).SetHex("91abba6a34b7481d922a4bd6a04899d5a686f6cf6da4e66a0cb427fb25c04bd4")
y2 := new(fieldVal).SetHex("03fede65e30b4e7576a2abefc963ddbf9fdccbf791b77c29beadefe49951f7d1")
z2 := new(fieldVal).SetHex("3")
x3, y3, z3 := new(fieldVal), new(fieldVal), new(fieldVal)
curve := S256()
b.StartTimer()
for i := 0; i < b.N; i++ {
curve.addJacobian(x1, y1, z1, x2, y2, z2, x3, y3, z3)
}
}
// BenchmarkScalarBaseMult benchmarks the secp256k1 curve ScalarBaseMult
// function.
func BenchmarkScalarBaseMult(b *testing.B) {
k := fromHex("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
curve := S256()
for i := 0; i < b.N; i++ {
curve.ScalarBaseMult(k.Bytes())
}
}
// BenchmarkScalarBaseMultLarge benchmarks the secp256k1 curve ScalarBaseMult
// function with abnormally large k values.
func BenchmarkScalarBaseMultLarge(b *testing.B) {
k := fromHex("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c005751111111011111110")
curve := S256()
for i := 0; i < b.N; i++ {
curve.ScalarBaseMult(k.Bytes())
}
}
// BenchmarkScalarMult benchmarks the secp256k1 curve ScalarMult function.
func BenchmarkScalarMult(b *testing.B) {
x := fromHex("34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6")
y := fromHex("0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232")
k := fromHex("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
curve := S256()
for i := 0; i < b.N; i++ {
curve.ScalarMult(x, y, k.Bytes())
}
}
// BenchmarkNAF benchmarks the NAF function.
func BenchmarkNAF(b *testing.B) {
k := fromHex("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575")
for i := 0; i < b.N; i++ {
NAF(k.Bytes())
}
}
// BenchmarkSigVerify benchmarks how long it takes the secp256k1 curve to
// verify signatures.
func BenchmarkSigVerify(b *testing.B) {
b.StopTimer()
// Randomly generated keypair.
// Private key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d
pubKey := PublicKey{
Curve: S256(),
X: fromHex("d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab"),
Y: fromHex("ab65528eefbb8057aa85d597258a3fbd481a24633bc9b47a9aa045c91371de52"),
}
// Double sha256 of []byte{0x01, 0x02, 0x03, 0x04}
msgHash := fromHex("8de472e2399610baaa7f84840547cd409434e31f5d3bd71e4d947f283874f9c0")
sig := Signature{
R: fromHex("fef45d2892953aa5bbcdb057b5e98b208f1617a7498af7eb765574e29b5d9c2c"),
S: fromHex("d47563f52aac6b04b55de236b7c515eb9311757db01e02cff079c3ca6efb063f"),
}
if !sig.Verify(msgHash.Bytes(), &pubKey) {
b.Errorf("Signature failed to verify")
return
}
b.StartTimer()
for i := 0; i < b.N; i++ {
sig.Verify(msgHash.Bytes(), &pubKey)
}
}
// BenchmarkFieldNormalize benchmarks how long it takes the internal field
// to perform normalization (which includes modular reduction).
func BenchmarkFieldNormalize(b *testing.B) {
// The normalize function is constant time so default value is fine.
f := new(fieldVal)
for i := 0; i < b.N; i++ {
f.Normalize()
}
}
// BenchmarkParseCompressedPubKey benchmarks how long it takes to decompress and
// validate a compressed public key from a byte array.
func BenchmarkParseCompressedPubKey(b *testing.B) {
rawPk, _ := hex.DecodeString("0234f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6")
var (
pk *PublicKey
err error
)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
pk, err = ParsePubKey(rawPk, S256())
}
_ = pk
_ = err
}
// Copyright 2010 The Go Authors. All rights reserved.
// Copyright 2011 ThePiachu. All rights reserved.
// Copyright 2013-2014 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
// References:
// [SECG]: Recommended Elliptic Curve Domain Parameters
// http://www.secg.org/sec2-v2.pdf
//
// [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone)
// This package operates, internally, on Jacobian coordinates. For a given
// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
// calculation can be performed within the transform (as in ScalarMult and
// ScalarBaseMult). But even for Add and Double, it's faster to apply and
// reverse the transform than to operate in affine coordinates.
import (
"crypto/elliptic"
"math/big"
"sync"
)
var (
// fieldOne is simply the integer 1 in field representation. It is
// used to avoid needing to create it multiple times during the internal
// arithmetic.
fieldOne = new(fieldVal).SetInt(1)
)
// KoblitzCurve supports a koblitz curve implementation that fits the ECC Curve
// interface from crypto/elliptic.
type KoblitzCurve struct {
*elliptic.CurveParams
// q is the value (P+1)/4 used to compute the square root of field
// elements.
q *big.Int
H int // cofactor of the curve.
halfOrder *big.Int // half the order N
// fieldB is the constant B of the curve as a fieldVal.
fieldB *fieldVal
// byteSize is simply the bit size / 8 and is provided for convenience
// since it is calculated repeatedly.
byteSize int
// bytePoints
bytePoints *[32][256][3]fieldVal
// The next 6 values are used specifically for endomorphism
// optimizations in ScalarMult.
// lambda must fulfill lambda^3 = 1 mod N where N is the order of G.
lambda *big.Int
// beta must fulfill beta^3 = 1 mod P where P is the prime field of the
// curve.
beta *fieldVal
// See the EndomorphismVectors in gensecp256k1.go to see how these are
// derived.
a1 *big.Int
b1 *big.Int
a2 *big.Int
b2 *big.Int
}
// Params returns the parameters for the curve.
func (curve *KoblitzCurve) Params() *elliptic.CurveParams {
return curve.CurveParams
}
// bigAffineToField takes an affine point (x, y) as big integers and converts
// it to an affine point as field values.
func (curve *KoblitzCurve) bigAffineToField(x, y *big.Int) (*fieldVal, *fieldVal) {
x3, y3 := new(fieldVal), new(fieldVal)
x3.SetByteSlice(x.Bytes())
y3.SetByteSlice(y.Bytes())
return x3, y3
}
// fieldJacobianToBigAffine takes a Jacobian point (x, y, z) as field values and
// converts it to an affine point as big integers.
func (curve *KoblitzCurve) fieldJacobianToBigAffine(x, y, z *fieldVal) (*big.Int, *big.Int) {
// Inversions are expensive and both point addition and point doubling
// are faster when working with points that have a z value of one. So,
// if the point needs to be converted to affine, go ahead and normalize
// the point itself at the same time as the calculation is the same.
var zInv, tempZ fieldVal
zInv.Set(z).Inverse() // zInv = Z^-1
tempZ.SquareVal(&zInv) // tempZ = Z^-2
x.Mul(&tempZ) // X = X/Z^2 (mag: 1)
y.Mul(tempZ.Mul(&zInv)) // Y = Y/Z^3 (mag: 1)
z.SetInt(1) // Z = 1 (mag: 1)
// Normalize the x and y values.
x.Normalize()
y.Normalize()
// Convert the field values for the now affine point to big.Ints.
x3, y3 := new(big.Int), new(big.Int)
x3.SetBytes(x.Bytes()[:])
y3.SetBytes(y.Bytes()[:])
return x3, y3
}
// IsOnCurve returns boolean if the point (x,y) is on the curve.
// Part of the elliptic.Curve interface. This function differs from the
// crypto/elliptic algorithm since a = 0 not -3.
func (curve *KoblitzCurve) IsOnCurve(x, y *big.Int) bool {
// Convert big ints to field values for faster arithmetic.
fx, fy := curve.bigAffineToField(x, y)
// Elliptic curve equation for secp256k1 is: y^2 = x^3 + 7
y2 := new(fieldVal).SquareVal(fy).Normalize()
result := new(fieldVal).SquareVal(fx).Mul(fx).AddInt(7).Normalize()
return y2.Equals(result)
}
// addZ1AndZ2EqualsOne adds two Jacobian points that are already known to have
// z values of 1 and stores the result in (x3, y3, z3). That is to say
// (x1, y1, 1) + (x2, y2, 1) = (x3, y3, z3). It performs faster addition than
// the generic add routine since less arithmetic is needed due to the ability to
// avoid the z value multiplications.
func (curve *KoblitzCurve) addZ1AndZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3 *fieldVal) {
// To compute the point addition efficiently, this implementation splits
// the equation into intermediate elements which are used to minimize
// the number of field multiplications using the method shown at:
// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl
//
// In particular it performs the calculations using the following:
// H = X2-X1, HH = H^2, I = 4*HH, J = H*I, r = 2*(Y2-Y1), V = X1*I
// X3 = r^2-J-2*V, Y3 = r*(V-X3)-2*Y1*J, Z3 = 2*H
//
// This results in a cost of 4 field multiplications, 2 field squarings,
// 6 field additions, and 5 integer multiplications.
// When the x coordinates are the same for two points on the curve, the
// y coordinates either must be the same, in which case it is point
// doubling, or they are opposite and the result is the point at
// infinity per the group law for elliptic curve cryptography.
x1.Normalize()
y1.Normalize()
x2.Normalize()
y2.Normalize()
if x1.Equals(x2) {
if y1.Equals(y2) {
// Since x1 == x2 and y1 == y2, point doubling must be
// done, otherwise the addition would end up dividing
// by zero.
curve.doubleJacobian(x1, y1, z1, x3, y3, z3)
return
}
// Since x1 == x2 and y1 == -y2, the sum is the point at
// infinity per the group law.
x3.SetInt(0)
y3.SetInt(0)
z3.SetInt(0)
return
}
// Calculate X3, Y3, and Z3 according to the intermediate elements
// breakdown above.
var h, i, j, r, v fieldVal
var negJ, neg2V, negX3 fieldVal
h.Set(x1).Negate(1).Add(x2) // H = X2-X1 (mag: 3)
i.SquareVal(&h).MulInt(4) // I = 4*H^2 (mag: 4)
j.Mul2(&h, &i) // J = H*I (mag: 1)
r.Set(y1).Negate(1).Add(y2).MulInt(2) // r = 2*(Y2-Y1) (mag: 6)
v.Mul2(x1, &i) // V = X1*I (mag: 1)
negJ.Set(&j).Negate(1) // negJ = -J (mag: 2)
neg2V.Set(&v).MulInt(2).Negate(2) // neg2V = -(2*V) (mag: 3)
x3.Set(&r).Square().Add(&negJ).Add(&neg2V) // X3 = r^2-J-2*V (mag: 6)
negX3.Set(x3).Negate(6) // negX3 = -X3 (mag: 7)
j.Mul(y1).MulInt(2).Negate(2) // J = -(2*Y1*J) (mag: 3)
y3.Set(&v).Add(&negX3).Mul(&r).Add(&j) // Y3 = r*(V-X3)-2*Y1*J (mag: 4)
z3.Set(&h).MulInt(2) // Z3 = 2*H (mag: 6)
// Normalize the resulting field values to a magnitude of 1 as needed.
x3.Normalize()
y3.Normalize()
z3.Normalize()
}
// addZ1EqualsZ2 adds two Jacobian points that are already known to have the
// same z value and stores the result in (x3, y3, z3). That is to say
// (x1, y1, z1) + (x2, y2, z1) = (x3, y3, z3). It performs faster addition than
// the generic add routine since less arithmetic is needed due to the known
// equivalence.
func (curve *KoblitzCurve) addZ1EqualsZ2(x1, y1, z1, x2, y2, x3, y3, z3 *fieldVal) {
// To compute the point addition efficiently, this implementation splits
// the equation into intermediate elements which are used to minimize
// the number of field multiplications using a slightly modified version
// of the method shown at:
// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl
//
// In particular it performs the calculations using the following:
// A = X2-X1, B = A^2, C=Y2-Y1, D = C^2, E = X1*B, F = X2*B
// X3 = D-E-F, Y3 = C*(E-X3)-Y1*(F-E), Z3 = Z1*A
//
// This results in a cost of 5 field multiplications, 2 field squarings,
// 9 field additions, and 0 integer multiplications.
// When the x coordinates are the same for two points on the curve, the
// y coordinates either must be the same, in which case it is point
// doubling, or they are opposite and the result is the point at
// infinity per the group law for elliptic curve cryptography.
x1.Normalize()
y1.Normalize()
x2.Normalize()
y2.Normalize()
if x1.Equals(x2) {
if y1.Equals(y2) {
// Since x1 == x2 and y1 == y2, point doubling must be
// done, otherwise the addition would end up dividing
// by zero.
curve.doubleJacobian(x1, y1, z1, x3, y3, z3)
return
}
// Since x1 == x2 and y1 == -y2, the sum is the point at
// infinity per the group law.
x3.SetInt(0)
y3.SetInt(0)
z3.SetInt(0)
return
}
// Calculate X3, Y3, and Z3 according to the intermediate elements
// breakdown above.
var a, b, c, d, e, f fieldVal
var negX1, negY1, negE, negX3 fieldVal
negX1.Set(x1).Negate(1) // negX1 = -X1 (mag: 2)
negY1.Set(y1).Negate(1) // negY1 = -Y1 (mag: 2)
a.Set(&negX1).Add(x2) // A = X2-X1 (mag: 3)
b.SquareVal(&a) // B = A^2 (mag: 1)
c.Set(&negY1).Add(y2) // C = Y2-Y1 (mag: 3)
d.SquareVal(&c) // D = C^2 (mag: 1)
e.Mul2(x1, &b) // E = X1*B (mag: 1)
negE.Set(&e).Negate(1) // negE = -E (mag: 2)
f.Mul2(x2, &b) // F = X2*B (mag: 1)
x3.Add2(&e, &f).Negate(3).Add(&d) // X3 = D-E-F (mag: 5)
negX3.Set(x3).Negate(5).Normalize() // negX3 = -X3 (mag: 1)
y3.Set(y1).Mul(f.Add(&negE)).Negate(3) // Y3 = -(Y1*(F-E)) (mag: 4)
y3.Add(e.Add(&negX3).Mul(&c)) // Y3 = C*(E-X3)+Y3 (mag: 5)
z3.Mul2(z1, &a) // Z3 = Z1*A (mag: 1)
// Normalize the resulting field values to a magnitude of 1 as needed.
x3.Normalize()
y3.Normalize()
}
// addZ2EqualsOne adds two Jacobian points when the second point is already
// known to have a z value of 1 (and the z value for the first point is not 1)
// and stores the result in (x3, y3, z3). That is to say (x1, y1, z1) +
// (x2, y2, 1) = (x3, y3, z3). It performs faster addition than the generic
// add routine since less arithmetic is needed due to the ability to avoid
// multiplications by the second point's z value.
func (curve *KoblitzCurve) addZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3 *fieldVal) {
// To compute the point addition efficiently, this implementation splits
// the equation into intermediate elements which are used to minimize
// the number of field multiplications using the method shown at:
// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
//
// In particular it performs the calculations using the following:
// Z1Z1 = Z1^2, U2 = X2*Z1Z1, S2 = Y2*Z1*Z1Z1, H = U2-X1, HH = H^2,
// I = 4*HH, J = H*I, r = 2*(S2-Y1), V = X1*I
// X3 = r^2-J-2*V, Y3 = r*(V-X3)-2*Y1*J, Z3 = (Z1+H)^2-Z1Z1-HH
//
// This results in a cost of 7 field multiplications, 4 field squarings,
// 9 field additions, and 4 integer multiplications.
// When the x coordinates are the same for two points on the curve, the
// y coordinates either must be the same, in which case it is point
// doubling, or they are opposite and the result is the point at
// infinity per the group law for elliptic curve cryptography. Since
// any number of Jacobian coordinates can represent the same affine
// point, the x and y values need to be converted to like terms. Due to
// the assumption made for this function that the second point has a z
// value of 1 (z2=1), the first point is already "converted".
var z1z1, u2, s2 fieldVal
x1.Normalize()
y1.Normalize()
z1z1.SquareVal(z1) // Z1Z1 = Z1^2 (mag: 1)
u2.Set(x2).Mul(&z1z1).Normalize() // U2 = X2*Z1Z1 (mag: 1)
s2.Set(y2).Mul(&z1z1).Mul(z1).Normalize() // S2 = Y2*Z1*Z1Z1 (mag: 1)
if x1.Equals(&u2) {
if y1.Equals(&s2) {
// Since x1 == x2 and y1 == y2, point doubling must be
// done, otherwise the addition would end up dividing
// by zero.
curve.doubleJacobian(x1, y1, z1, x3, y3, z3)
return
}
// Since x1 == x2 and y1 == -y2, the sum is the point at
// infinity per the group law.
x3.SetInt(0)
y3.SetInt(0)
z3.SetInt(0)
return
}
// Calculate X3, Y3, and Z3 according to the intermediate elements
// breakdown above.
var h, hh, i, j, r, rr, v fieldVal
var negX1, negY1, negX3 fieldVal
negX1.Set(x1).Negate(1) // negX1 = -X1 (mag: 2)
h.Add2(&u2, &negX1) // H = U2-X1 (mag: 3)
hh.SquareVal(&h) // HH = H^2 (mag: 1)
i.Set(&hh).MulInt(4) // I = 4 * HH (mag: 4)
j.Mul2(&h, &i) // J = H*I (mag: 1)
negY1.Set(y1).Negate(1) // negY1 = -Y1 (mag: 2)
r.Set(&s2).Add(&negY1).MulInt(2) // r = 2*(S2-Y1) (mag: 6)
rr.SquareVal(&r) // rr = r^2 (mag: 1)
v.Mul2(x1, &i) // V = X1*I (mag: 1)
x3.Set(&v).MulInt(2).Add(&j).Negate(3) // X3 = -(J+2*V) (mag: 4)
x3.Add(&rr) // X3 = r^2+X3 (mag: 5)
negX3.Set(x3).Negate(5) // negX3 = -X3 (mag: 6)
y3.Set(y1).Mul(&j).MulInt(2).Negate(2) // Y3 = -(2*Y1*J) (mag: 3)
y3.Add(v.Add(&negX3).Mul(&r)) // Y3 = r*(V-X3)+Y3 (mag: 4)
z3.Add2(z1, &h).Square() // Z3 = (Z1+H)^2 (mag: 1)
z3.Add(z1z1.Add(&hh).Negate(2)) // Z3 = Z3-(Z1Z1+HH) (mag: 4)
// Normalize the resulting field values to a magnitude of 1 as needed.
x3.Normalize()
y3.Normalize()
z3.Normalize()
}
// addGeneric adds two Jacobian points (x1, y1, z1) and (x2, y2, z2) without any
// assumptions about the z values of the two points and stores the result in
// (x3, y3, z3). That is to say (x1, y1, z1) + (x2, y2, z2) = (x3, y3, z3). It
// is the slowest of the add routines due to requiring the most arithmetic.
func (curve *KoblitzCurve) addGeneric(x1, y1, z1, x2, y2, z2, x3, y3, z3 *fieldVal) {
// To compute the point addition efficiently, this implementation splits
// the equation into intermediate elements which are used to minimize
// the number of field multiplications using the method shown at:
// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
//
// In particular it performs the calculations using the following:
// Z1Z1 = Z1^2, Z2Z2 = Z2^2, U1 = X1*Z2Z2, U2 = X2*Z1Z1, S1 = Y1*Z2*Z2Z2
// S2 = Y2*Z1*Z1Z1, H = U2-U1, I = (2*H)^2, J = H*I, r = 2*(S2-S1)
// V = U1*I
// X3 = r^2-J-2*V, Y3 = r*(V-X3)-2*S1*J, Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2)*H
//
// This results in a cost of 11 field multiplications, 5 field squarings,
// 9 field additions, and 4 integer multiplications.
// When the x coordinates are the same for two points on the curve, the
// y coordinates either must be the same, in which case it is point
// doubling, or they are opposite and the result is the point at
// infinity. Since any number of Jacobian coordinates can represent the
// same affine point, the x and y values need to be converted to like
// terms.
var z1z1, z2z2, u1, u2, s1, s2 fieldVal
z1z1.SquareVal(z1) // Z1Z1 = Z1^2 (mag: 1)
z2z2.SquareVal(z2) // Z2Z2 = Z2^2 (mag: 1)
u1.Set(x1).Mul(&z2z2).Normalize() // U1 = X1*Z2Z2 (mag: 1)
u2.Set(x2).Mul(&z1z1).Normalize() // U2 = X2*Z1Z1 (mag: 1)
s1.Set(y1).Mul(&z2z2).Mul(z2).Normalize() // S1 = Y1*Z2*Z2Z2 (mag: 1)
s2.Set(y2).Mul(&z1z1).Mul(z1).Normalize() // S2 = Y2*Z1*Z1Z1 (mag: 1)
if u1.Equals(&u2) {
if s1.Equals(&s2) {
// Since x1 == x2 and y1 == y2, point doubling must be
// done, otherwise the addition would end up dividing
// by zero.
curve.doubleJacobian(x1, y1, z1, x3, y3, z3)
return
}
// Since x1 == x2 and y1 == -y2, the sum is the point at
// infinity per the group law.
x3.SetInt(0)
y3.SetInt(0)
z3.SetInt(0)
return
}
// Calculate X3, Y3, and Z3 according to the intermediate elements
// breakdown above.
var h, i, j, r, rr, v fieldVal
var negU1, negS1, negX3 fieldVal
negU1.Set(&u1).Negate(1) // negU1 = -U1 (mag: 2)
h.Add2(&u2, &negU1) // H = U2-U1 (mag: 3)
i.Set(&h).MulInt(2).Square() // I = (2*H)^2 (mag: 2)
j.Mul2(&h, &i) // J = H*I (mag: 1)
negS1.Set(&s1).Negate(1) // negS1 = -S1 (mag: 2)
r.Set(&s2).Add(&negS1).MulInt(2) // r = 2*(S2-S1) (mag: 6)
rr.SquareVal(&r) // rr = r^2 (mag: 1)
v.Mul2(&u1, &i) // V = U1*I (mag: 1)
x3.Set(&v).MulInt(2).Add(&j).Negate(3) // X3 = -(J+2*V) (mag: 4)
x3.Add(&rr) // X3 = r^2+X3 (mag: 5)
negX3.Set(x3).Negate(5) // negX3 = -X3 (mag: 6)
y3.Mul2(&s1, &j).MulInt(2).Negate(2) // Y3 = -(2*S1*J) (mag: 3)
y3.Add(v.Add(&negX3).Mul(&r)) // Y3 = r*(V-X3)+Y3 (mag: 4)
z3.Add2(z1, z2).Square() // Z3 = (Z1+Z2)^2 (mag: 1)
z3.Add(z1z1.Add(&z2z2).Negate(2)) // Z3 = Z3-(Z1Z1+Z2Z2) (mag: 4)
z3.Mul(&h) // Z3 = Z3*H (mag: 1)
// Normalize the resulting field values to a magnitude of 1 as needed.
x3.Normalize()
y3.Normalize()
}
// addJacobian adds the passed Jacobian points (x1, y1, z1) and (x2, y2, z2)
// together and stores the result in (x3, y3, z3).
func (curve *KoblitzCurve) addJacobian(x1, y1, z1, x2, y2, z2, x3, y3, z3 *fieldVal) {
// A point at infinity is the identity according to the group law for
// elliptic curve cryptography. Thus, ∞ + P = P and P + ∞ = P.
if (x1.IsZero() && y1.IsZero()) || z1.IsZero() {
x3.Set(x2)
y3.Set(y2)
z3.Set(z2)
return
}
if (x2.IsZero() && y2.IsZero()) || z2.IsZero() {
x3.Set(x1)
y3.Set(y1)
z3.Set(z1)
return
}
// Faster point addition can be achieved when certain assumptions are
// met. For example, when both points have the same z value, arithmetic
// on the z values can be avoided. This section thus checks for these
// conditions and calls an appropriate add function which is accelerated
// by using those assumptions.
z1.Normalize()
z2.Normalize()
isZ1One := z1.Equals(fieldOne)
isZ2One := z2.Equals(fieldOne)
switch {
case isZ1One && isZ2One:
curve.addZ1AndZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3)
return
case z1.Equals(z2):
curve.addZ1EqualsZ2(x1, y1, z1, x2, y2, x3, y3, z3)
return
case isZ2One:
curve.addZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3)
return
}
// None of the above assumptions are true, so fall back to generic
// point addition.
curve.addGeneric(x1, y1, z1, x2, y2, z2, x3, y3, z3)
}
// Add returns the sum of (x1,y1) and (x2,y2). Part of the elliptic.Curve
// interface.
func (curve *KoblitzCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
// A point at infinity is the identity according to the group law for
// elliptic curve cryptography. Thus, ∞ + P = P and P + ∞ = P.
if x1.Sign() == 0 && y1.Sign() == 0 {
return x2, y2
}
if x2.Sign() == 0 && y2.Sign() == 0 {
return x1, y1
}
// Convert the affine coordinates from big integers to field values
// and do the point addition in Jacobian projective space.
fx1, fy1 := curve.bigAffineToField(x1, y1)
fx2, fy2 := curve.bigAffineToField(x2, y2)
fx3, fy3, fz3 := new(fieldVal), new(fieldVal), new(fieldVal)
fOne := new(fieldVal).SetInt(1)
curve.addJacobian(fx1, fy1, fOne, fx2, fy2, fOne, fx3, fy3, fz3)
// Convert the Jacobian coordinate field values back to affine big
// integers.
return curve.fieldJacobianToBigAffine(fx3, fy3, fz3)
}
// doubleZ1EqualsOne performs point doubling on the passed Jacobian point
// when the point is already known to have a z value of 1 and stores
// the result in (x3, y3, z3). That is to say (x3, y3, z3) = 2*(x1, y1, 1). It
// performs faster point doubling than the generic routine since less arithmetic
// is needed due to the ability to avoid multiplication by the z value.
func (curve *KoblitzCurve) doubleZ1EqualsOne(x1, y1, x3, y3, z3 *fieldVal) {
// This function uses the assumptions that z1 is 1, thus the point
// doubling formulas reduce to:
//
// X3 = (3*X1^2)^2 - 8*X1*Y1^2
// Y3 = (3*X1^2)*(4*X1*Y1^2 - X3) - 8*Y1^4
// Z3 = 2*Y1
//
// To compute the above efficiently, this implementation splits the
// equation into intermediate elements which are used to minimize the
// number of field multiplications in favor of field squarings which
// are roughly 35% faster than field multiplications with the current
// implementation at the time this was written.
//
// This uses a slightly modified version of the method shown at:
// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl
//
// In particular it performs the calculations using the following:
// A = X1^2, B = Y1^2, C = B^2, D = 2*((X1+B)^2-A-C)
// E = 3*A, F = E^2, X3 = F-2*D, Y3 = E*(D-X3)-8*C
// Z3 = 2*Y1
//
// This results in a cost of 1 field multiplication, 5 field squarings,
// 6 field additions, and 5 integer multiplications.
var a, b, c, d, e, f fieldVal
z3.Set(y1).MulInt(2) // Z3 = 2*Y1 (mag: 2)
a.SquareVal(x1) // A = X1^2 (mag: 1)
b.SquareVal(y1) // B = Y1^2 (mag: 1)
c.SquareVal(&b) // C = B^2 (mag: 1)
b.Add(x1).Square() // B = (X1+B)^2 (mag: 1)
d.Set(&a).Add(&c).Negate(2) // D = -(A+C) (mag: 3)
d.Add(&b).MulInt(2) // D = 2*(B+D)(mag: 8)
e.Set(&a).MulInt(3) // E = 3*A (mag: 3)
f.SquareVal(&e) // F = E^2 (mag: 1)
x3.Set(&d).MulInt(2).Negate(16) // X3 = -(2*D) (mag: 17)
x3.Add(&f) // X3 = F+X3 (mag: 18)
f.Set(x3).Negate(18).Add(&d).Normalize() // F = D-X3 (mag: 1)
y3.Set(&c).MulInt(8).Negate(8) // Y3 = -(8*C) (mag: 9)
y3.Add(f.Mul(&e)) // Y3 = E*F+Y3 (mag: 10)
// Normalize the field values back to a magnitude of 1.
x3.Normalize()
y3.Normalize()
z3.Normalize()
}
// doubleGeneric performs point doubling on the passed Jacobian point without
// any assumptions about the z value and stores the result in (x3, y3, z3).
// That is to say (x3, y3, z3) = 2*(x1, y1, z1). It is the slowest of the point
// doubling routines due to requiring the most arithmetic.
func (curve *KoblitzCurve) doubleGeneric(x1, y1, z1, x3, y3, z3 *fieldVal) {
// Point doubling formula for Jacobian coordinates for the secp256k1
// curve:
// X3 = (3*X1^2)^2 - 8*X1*Y1^2
// Y3 = (3*X1^2)*(4*X1*Y1^2 - X3) - 8*Y1^4
// Z3 = 2*Y1*Z1
//
// To compute the above efficiently, this implementation splits the
// equation into intermediate elements which are used to minimize the
// number of field multiplications in favor of field squarings which
// are roughly 35% faster than field multiplications with the current
// implementation at the time this was written.
//
// This uses a slightly modified version of the method shown at:
// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
//
// In particular it performs the calculations using the following:
// A = X1^2, B = Y1^2, C = B^2, D = 2*((X1+B)^2-A-C)
// E = 3*A, F = E^2, X3 = F-2*D, Y3 = E*(D-X3)-8*C
// Z3 = 2*Y1*Z1
//
// This results in a cost of 1 field multiplication, 5 field squarings,
// 6 field additions, and 5 integer multiplications.
var a, b, c, d, e, f fieldVal
z3.Mul2(y1, z1).MulInt(2) // Z3 = 2*Y1*Z1 (mag: 2)
a.SquareVal(x1) // A = X1^2 (mag: 1)
b.SquareVal(y1) // B = Y1^2 (mag: 1)
c.SquareVal(&b) // C = B^2 (mag: 1)
b.Add(x1).Square() // B = (X1+B)^2 (mag: 1)
d.Set(&a).Add(&c).Negate(2) // D = -(A+C) (mag: 3)
d.Add(&b).MulInt(2) // D = 2*(B+D)(mag: 8)
e.Set(&a).MulInt(3) // E = 3*A (mag: 3)
f.SquareVal(&e) // F = E^2 (mag: 1)
x3.Set(&d).MulInt(2).Negate(16) // X3 = -(2*D) (mag: 17)
x3.Add(&f) // X3 = F+X3 (mag: 18)
f.Set(x3).Negate(18).Add(&d).Normalize() // F = D-X3 (mag: 1)
y3.Set(&c).MulInt(8).Negate(8) // Y3 = -(8*C) (mag: 9)
y3.Add(f.Mul(&e)) // Y3 = E*F+Y3 (mag: 10)
// Normalize the field values back to a magnitude of 1.
x3.Normalize()
y3.Normalize()
z3.Normalize()
}
// doubleJacobian doubles the passed Jacobian point (x1, y1, z1) and stores the
// result in (x3, y3, z3).
func (curve *KoblitzCurve) doubleJacobian(x1, y1, z1, x3, y3, z3 *fieldVal) {
// Doubling a point at infinity is still infinity.
if y1.IsZero() || z1.IsZero() {
x3.SetInt(0)
y3.SetInt(0)
z3.SetInt(0)
return
}
// Slightly faster point doubling can be achieved when the z value is 1
// by avoiding the multiplication on the z value. This section calls
// a point doubling function which is accelerated by using that
// assumption when possible.
if z1.Normalize().Equals(fieldOne) {
curve.doubleZ1EqualsOne(x1, y1, x3, y3, z3)
return
}
// Fall back to generic point doubling which works with arbitrary z
// values.
curve.doubleGeneric(x1, y1, z1, x3, y3, z3)
}
// Double returns 2*(x1,y1). Part of the elliptic.Curve interface.
func (curve *KoblitzCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
if y1.Sign() == 0 {
return new(big.Int), new(big.Int)
}
// Convert the affine coordinates from big integers to field values
// and do the point doubling in Jacobian projective space.
fx1, fy1 := curve.bigAffineToField(x1, y1)
fx3, fy3, fz3 := new(fieldVal), new(fieldVal), new(fieldVal)
fOne := new(fieldVal).SetInt(1)
curve.doubleJacobian(fx1, fy1, fOne, fx3, fy3, fz3)
// Convert the Jacobian coordinate field values back to affine big
// integers.
return curve.fieldJacobianToBigAffine(fx3, fy3, fz3)
}
// splitK returns a balanced length-two representation of k and their signs.
// This is algorithm 3.74 from [GECC].
//
// One thing of note about this algorithm is that no matter what c1 and c2 are,
// the final equation of k = k1 + k2 * lambda (mod n) will hold. This is
// provable mathematically due to how a1/b1/a2/b2 are computed.
//
// c1 and c2 are chosen to minimize the max(k1,k2).
func (curve *KoblitzCurve) splitK(k []byte) ([]byte, []byte, int, int) {
// All math here is done with big.Int, which is slow.
// At some point, it might be useful to write something similar to
// fieldVal but for N instead of P as the prime field if this ends up
// being a bottleneck.
bigIntK := new(big.Int)
c1, c2 := new(big.Int), new(big.Int)
tmp1, tmp2 := new(big.Int), new(big.Int)
k1, k2 := new(big.Int), new(big.Int)
bigIntK.SetBytes(k)
// c1 = round(b2 * k / n) from step 4.
// Rounding isn't really necessary and costs too much, hence skipped
c1.Mul(curve.b2, bigIntK)
c1.Div(c1, curve.N)
// c2 = round(b1 * k / n) from step 4 (sign reversed to optimize one step)
// Rounding isn't really necessary and costs too much, hence skipped
c2.Mul(curve.b1, bigIntK)
c2.Div(c2, curve.N)
// k1 = k - c1 * a1 - c2 * a2 from step 5 (note c2's sign is reversed)
tmp1.Mul(c1, curve.a1)
tmp2.Mul(c2, curve.a2)
k1.Sub(bigIntK, tmp1)
k1.Add(k1, tmp2)
// k2 = - c1 * b1 - c2 * b2 from step 5 (note c2's sign is reversed)
tmp1.Mul(c1, curve.b1)
tmp2.Mul(c2, curve.b2)
k2.Sub(tmp2, tmp1)
// Note Bytes() throws out the sign of k1 and k2. This matters
// since k1 and/or k2 can be negative. Hence, we pass that
// back separately.
return k1.Bytes(), k2.Bytes(), k1.Sign(), k2.Sign()
}
// moduloReduce reduces k from more than 32 bytes to 32 bytes and under. This
// is done by doing a simple modulo curve.N. We can do this since G^N = 1 and
// thus any other valid point on the elliptic curve has the same order.
func (curve *KoblitzCurve) moduloReduce(k []byte) []byte {
// Since the order of G is curve.N, we can use a much smaller number
// by doing modulo curve.N
if len(k) > curve.byteSize {
// Reduce k by performing modulo curve.N.
tmpK := new(big.Int).SetBytes(k)
tmpK.Mod(tmpK, curve.N)
return tmpK.Bytes()
}
return k
}
// NAF takes a positive integer k and returns the Non-Adjacent Form (NAF) as two
// byte slices. The first is where 1s will be. The second is where -1s will
// be. NAF is convenient in that on average, only 1/3rd of its values are
// non-zero. This is algorithm 3.30 from [GECC].
//
// Essentially, this makes it possible to minimize the number of operations
// since the resulting ints returned will be at least 50% 0s.
func NAF(k []byte) ([]byte, []byte) {
// The essence of this algorithm is that whenever we have consecutive 1s
// in the binary, we want to put a -1 in the lowest bit and get a bunch
// of 0s up to the highest bit of consecutive 1s. This is due to this
// identity:
// 2^n + 2^(n-1) + 2^(n-2) + ... + 2^(n-k) = 2^(n+1) - 2^(n-k)
//
// The algorithm thus may need to go 1 more bit than the length of the
// bits we actually have, hence bits being 1 bit longer than was
// necessary. Since we need to know whether adding will cause a carry,
// we go from right-to-left in this addition.
var carry, curIsOne, nextIsOne bool
// these default to zero
retPos := make([]byte, len(k)+1)
retNeg := make([]byte, len(k)+1)
for i := len(k) - 1; i >= 0; i-- {
curByte := k[i]
for j := uint(0); j < 8; j++ {
curIsOne = curByte&1 == 1
if j == 7 {
if i == 0 {
nextIsOne = false
} else {
nextIsOne = k[i-1]&1 == 1
}
} else {
nextIsOne = curByte&2 == 2
}
if carry {
if curIsOne {
// This bit is 1, so continue to carry
// and don't need to do anything.
} else {
// We've hit a 0 after some number of
// 1s.
if nextIsOne {
// Start carrying again since
// a new sequence of 1s is
// starting.
retNeg[i+1] += 1 << j
} else {
// Stop carrying since 1s have
// stopped.
carry = false
retPos[i+1] += 1 << j
}
}
} else if curIsOne {
if nextIsOne {
// If this is the start of at least 2
// consecutive 1s, set the current one
// to -1 and start carrying.
retNeg[i+1] += 1 << j
carry = true
} else {
// This is a singleton, not consecutive
// 1s.
retPos[i+1] += 1 << j
}
}
curByte >>= 1
}
}
if carry {
retPos[0] = 1
return retPos, retNeg
}
return retPos[1:], retNeg[1:]
}
// ScalarMult returns k*(Bx, By) where k is a big endian integer.
// Part of the elliptic.Curve interface.
func (curve *KoblitzCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
// Point Q = ∞ (point at infinity).
qx, qy, qz := new(fieldVal), new(fieldVal), new(fieldVal)
// Decompose K into k1 and k2 in order to halve the number of EC ops.
// See Algorithm 3.74 in [GECC].
k1, k2, signK1, signK2 := curve.splitK(curve.moduloReduce(k))
// The main equation here to remember is:
// k * P = k1 * P + k2 * ϕ(P)
//
// P1 below is P in the equation, P2 below is ϕ(P) in the equation
p1x, p1y := curve.bigAffineToField(Bx, By)
p1yNeg := new(fieldVal).NegateVal(p1y, 1)
p1z := new(fieldVal).SetInt(1)
// NOTE: ϕ(x,y) = (βx,y). The Jacobian z coordinate is 1, so this math
// goes through.
p2x := new(fieldVal).Mul2(p1x, curve.beta)
p2y := new(fieldVal).Set(p1y)
p2yNeg := new(fieldVal).NegateVal(p2y, 1)
p2z := new(fieldVal).SetInt(1)
// Flip the positive and negative values of the points as needed
// depending on the signs of k1 and k2. As mentioned in the equation
// above, each of k1 and k2 are multiplied by the respective point.
// Since -k * P is the same thing as k * -P, and the group law for
// elliptic curves states that P(x, y) = -P(x, -y), it's faster and
// simplifies the code to just make the point negative.
if signK1 == -1 {
p1y, p1yNeg = p1yNeg, p1y
}
if signK2 == -1 {
p2y, p2yNeg = p2yNeg, p2y
}
// NAF versions of k1 and k2 should have a lot more zeros.
//
// The Pos version of the bytes contain the +1s and the Neg versions
// contain the -1s.
k1PosNAF, k1NegNAF := NAF(k1)
k2PosNAF, k2NegNAF := NAF(k2)
k1Len := len(k1PosNAF)
k2Len := len(k2PosNAF)
m := k1Len
if m < k2Len {
m = k2Len
}
// Add left-to-right using the NAF optimization. See algorithm 3.77
// from [GECC]. This should be faster overall since there will be a lot
// more instances of 0, hence reducing the number of Jacobian additions
// at the cost of 1 possible extra doubling.
var k1BytePos, k1ByteNeg, k2BytePos, k2ByteNeg byte
for i := 0; i < m; i++ {
// Since we're going left-to-right, pad the front with 0s.
if i < m-k1Len {
k1BytePos = 0
k1ByteNeg = 0
} else {
k1BytePos = k1PosNAF[i-(m-k1Len)]
k1ByteNeg = k1NegNAF[i-(m-k1Len)]
}
if i < m-k2Len {
k2BytePos = 0
k2ByteNeg = 0
} else {
k2BytePos = k2PosNAF[i-(m-k2Len)]
k2ByteNeg = k2NegNAF[i-(m-k2Len)]
}
for j := 7; j >= 0; j-- {
// Q = 2 * Q
curve.doubleJacobian(qx, qy, qz, qx, qy, qz)
if k1BytePos&0x80 == 0x80 {
curve.addJacobian(qx, qy, qz, p1x, p1y, p1z,
qx, qy, qz)
} else if k1ByteNeg&0x80 == 0x80 {
curve.addJacobian(qx, qy, qz, p1x, p1yNeg, p1z,
qx, qy, qz)
}
if k2BytePos&0x80 == 0x80 {
curve.addJacobian(qx, qy, qz, p2x, p2y, p2z,
qx, qy, qz)
} else if k2ByteNeg&0x80 == 0x80 {
curve.addJacobian(qx, qy, qz, p2x, p2yNeg, p2z,
qx, qy, qz)
}
k1BytePos <<= 1
k1ByteNeg <<= 1
k2BytePos <<= 1
k2ByteNeg <<= 1
}
}
// Convert the Jacobian coordinate field values back to affine big.Ints.
return curve.fieldJacobianToBigAffine(qx, qy, qz)
}
// ScalarBaseMult returns k*G where G is the base point of the group and k is a
// big endian integer.
// Part of the elliptic.Curve interface.
func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
newK := curve.moduloReduce(k)
diff := len(curve.bytePoints) - len(newK)
// Point Q = ∞ (point at infinity).
qx, qy, qz := new(fieldVal), new(fieldVal), new(fieldVal)
// curve.bytePoints has all 256 byte points for each 8-bit window. The
// strategy is to add up the byte points. This is best understood by
// expressing k in base-256 which it already sort of is.
// Each "digit" in the 8-bit window can be looked up using bytePoints
// and added together.
for i, byteVal := range newK {
p := curve.bytePoints[diff+i][byteVal]
curve.addJacobian(qx, qy, qz, &p[0], &p[1], &p[2], qx, qy, qz)
}
return curve.fieldJacobianToBigAffine(qx, qy, qz)
}
// QPlus1Div4 returns the (P+1)/4 constant for the curve for use in calculating
// square roots via exponentiation.
//
// DEPRECATED: The actual value returned is (P+1)/4, where as the original
// method name implies that this value is (((P+1)/4)+1)/4. This method is kept
// to maintain backwards compatibility of the API. Use Q() instead.
func (curve *KoblitzCurve) QPlus1Div4() *big.Int {
return curve.q
}
// Q returns the (P+1)/4 constant for the curve for use in calculating square
// roots via exponentiation.
func (curve *KoblitzCurve) Q() *big.Int {
return curve.q
}
var initonce sync.Once
var secp256k1 KoblitzCurve
func initAll() {
initS256()
}
// fromHex converts the passed hex string into a big integer pointer and will
// panic is there is an error. This is only provided for the hard-coded
// constants so errors in the source code can bet detected. It will only (and
// must only) be called for initialization purposes.
func fromHex(s string) *big.Int {
r, ok := new(big.Int).SetString(s, 16)
if !ok {
panic("invalid hex in source file: " + s)
}
return r
}
func initS256() {
// Curve parameters taken from [SECG] section 2.4.1.
secp256k1.CurveParams = new(elliptic.CurveParams)
secp256k1.P = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F")
secp256k1.N = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141")
secp256k1.B = fromHex("0000000000000000000000000000000000000000000000000000000000000007")
secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")
secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")
secp256k1.BitSize = 256
// Curve name taken from https://safecurves.cr.yp.to/.
secp256k1.Name = "secp256k1"
secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P,
big.NewInt(1)), big.NewInt(4))
secp256k1.H = 1
secp256k1.halfOrder = new(big.Int).Rsh(secp256k1.N, 1)
secp256k1.fieldB = new(fieldVal).SetByteSlice(secp256k1.B.Bytes())
// Provided for convenience since this gets computed repeatedly.
secp256k1.byteSize = secp256k1.BitSize / 8
// Deserialize and set the pre-computed table used to accelerate scalar
// base multiplication. This is hard-coded data, so any errors are
// panics because it means something is wrong in the source code.
if err := loadS256BytePoints(); err != nil {
panic(err)
}
// Next 6 constants are from Hal Finney's bitcointalk.org post:
// https://bitcointalk.org/index.php?topic=3238.msg45565#msg45565
// May he rest in peace.
//
// They have also been independently derived from the code in the
// EndomorphismVectors function in gensecp256k1.go.
secp256k1.lambda = fromHex("5363AD4CC05C30E0A5261C028812645A122E22EA20816678DF02967C1B23BD72")
secp256k1.beta = new(fieldVal).SetHex("7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE")
secp256k1.a1 = fromHex("3086D221A7D46BCDE86C90E49284EB15")
secp256k1.b1 = fromHex("-E4437ED6010E88286F547FA90ABFE4C3")
secp256k1.a2 = fromHex("114CA50F7A8E2F3F657C1108D9D44CFD8")
secp256k1.b2 = fromHex("3086D221A7D46BCDE86C90E49284EB15")
// Alternatively, we can use the parameters below, however, they seem
// to be about 8% slower.
// secp256k1.lambda = fromHex("AC9C52B33FA3CF1F5AD9E3FD77ED9BA4A880B9FC8EC739C2E0CFC810B51283CE")
// secp256k1.beta = new(fieldVal).SetHex("851695D49A83F8EF919BB86153CBCB16630FB68AED0A766A3EC693D68E6AFA40")
// secp256k1.a1 = fromHex("E4437ED6010E88286F547FA90ABFE4C3")
// secp256k1.b1 = fromHex("-3086D221A7D46BCDE86C90E49284EB15")
// secp256k1.a2 = fromHex("3086D221A7D46BCDE86C90E49284EB15")
// secp256k1.b2 = fromHex("114CA50F7A8E2F3F657C1108D9D44CFD8")
}
// S256 returns a Curve which implements secp256k1.
func S256() *KoblitzCurve {
initonce.Do(initAll)
return &secp256k1
}
// Copyright 2011 The Go Authors. All rights reserved.
// Copyright 2011 ThePiachu. All rights reserved.
// Copyright 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"crypto/rand"
"fmt"
"math/big"
"testing"
)
// isJacobianOnS256Curve returns boolean if the point (x,y,z) is on the
// secp256k1 curve.
func isJacobianOnS256Curve(x, y, z *fieldVal) bool {
// Elliptic curve equation for secp256k1 is: y^2 = x^3 + 7
// In Jacobian coordinates, Y = y/z^3 and X = x/z^2
// Thus:
// (y/z^3)^2 = (x/z^2)^3 + 7
// y^2/z^6 = x^3/z^6 + 7
// y^2 = x^3 + 7*z^6
var y2, z2, x3, result fieldVal
y2.SquareVal(y).Normalize()
z2.SquareVal(z)
x3.SquareVal(x).Mul(x)
result.SquareVal(&z2).Mul(&z2).MulInt(7).Add(&x3).Normalize()
return y2.Equals(&result)
}
// TestAddJacobian tests addition of points projected in Jacobian coordinates.
func TestAddJacobian(t *testing.T) {
tests := []struct {
x1, y1, z1 string // Coordinates (in hex) of first point to add
x2, y2, z2 string // Coordinates (in hex) of second point to add
x3, y3, z3 string // Coordinates (in hex) of expected point
}{
// Addition with a point at infinity (left hand side).
// ∞ + P = P
{
"0",
"0",
"0",
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
"1",
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
"1",
},
// Addition with a point at infinity (right hand side).
// P + ∞ = P
{
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
"1",
"0",
"0",
"0",
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
"1",
},
// Addition with z1=z2=1 different x values.
{
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"1",
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
"1",
"0cfbc7da1e569b334460788faae0286e68b3af7379d5504efc25e4dba16e46a6",
"e205f79361bbe0346b037b4010985dbf4f9e1e955e7d0d14aca876bfa79aad87",
"44a5646b446e3877a648d6d381370d9ef55a83b666ebce9df1b1d7d65b817b2f",
},
// Addition with z1=z2=1 same x opposite y.
// P(x, y, z) + P(x, -y, z) = infinity
{
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"1",
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"f48e156428cf0276dc092da5856e182288d7569f97934a56fe44be60f0d359fd",
"1",
"0",
"0",
"0",
},
// Addition with z1=z2=1 same point.
// P(x, y, z) + P(x, y, z) = 2P
{
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"1",
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"1",
"ec9f153b13ee7bd915882859635ea9730bf0dc7611b2c7b0e37ee64f87c50c27",
"b082b53702c466dcf6e984a35671756c506c67c2fcb8adb408c44dd0755c8f2a",
"16e3d537ae61fb1247eda4b4f523cfbaee5152c0d0d96b520376833c1e594464",
},
// Addition with z1=z2 (!=1) different x values.
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"5d2fe112c21891d440f65a98473cb626111f8a234d2cd82f22172e369f002147",
"98e3386a0a622a35c4561ffb32308d8e1c6758e10ebb1b4ebd3d04b4eb0ecbe8",
"2",
"cfbc7da1e569b334460788faae0286e68b3af7379d5504efc25e4dba16e46a60",
"817de4d86ef80d1ac0ded00426176fd3e787a5579f43452b2a1db021e6ac3778",
"129591ad11b8e1de99235b4e04dc367bd56a0ed99baf3a77c6c75f5a6e05f08d",
},
// Addition with z1=z2 (!=1) same x opposite y.
// P(x, y, z) + P(x, -y, z) = infinity
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"a470ab21467813b6e0496d2c2b70c11446bab4fcbc9a52b7f225f30e869aea9f",
"2",
"0",
"0",
"0",
},
// Addition with z1=z2 (!=1) same point.
// P(x, y, z) + P(x, y, z) = 2P
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"9f153b13ee7bd915882859635ea9730bf0dc7611b2c7b0e37ee65073c50fabac",
"2b53702c466dcf6e984a35671756c506c67c2fcb8adb408c44dd125dc91cb988",
"6e3d537ae61fb1247eda4b4f523cfbaee5152c0d0d96b520376833c2e5944a11",
},
// Addition with z1!=z2 and z2=1 different x values.
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
"1",
"3ef1f68795a6ccd1181e23eab80a1b9a2cebdcde755413bf097936eb5b91b4f3",
"0bef26c377c068d606f6802130bb7e9f3c3d2abcfa1a295950ed81133561cb04",
"252b235a2371c3bd3246b69c09b86cf7aad41db3375e74ef8d8ebeb4dc0be11a",
},
// Addition with z1!=z2 and z2=1 same x opposite y.
// P(x, y, z) + P(x, -y, z) = infinity
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"f48e156428cf0276dc092da5856e182288d7569f97934a56fe44be60f0d359fd",
"1",
"0",
"0",
"0",
},
// Addition with z1!=z2 and z2=1 same point.
// P(x, y, z) + P(x, y, z) = 2P
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"1",
"9f153b13ee7bd915882859635ea9730bf0dc7611b2c7b0e37ee65073c50fabac",
"2b53702c466dcf6e984a35671756c506c67c2fcb8adb408c44dd125dc91cb988",
"6e3d537ae61fb1247eda4b4f523cfbaee5152c0d0d96b520376833c2e5944a11",
},
// Addition with z1!=z2 and z2!=1 different x values.
// P(x, y, z) + P(x, y, z) = 2P
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"91abba6a34b7481d922a4bd6a04899d5a686f6cf6da4e66a0cb427fb25c04bd4",
"03fede65e30b4e7576a2abefc963ddbf9fdccbf791b77c29beadefe49951f7d1",
"3",
"3f07081927fd3f6dadd4476614c89a09eba7f57c1c6c3b01fa2d64eac1eef31e",
"949166e04ebc7fd95a9d77e5dfd88d1492ecffd189792e3944eb2b765e09e031",
"eb8cba81bcffa4f44d75427506737e1f045f21e6d6f65543ee0e1d163540c931",
}, // Addition with z1!=z2 and z2!=1 same x opposite y.
// P(x, y, z) + P(x, -y, z) = infinity
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"dcc3768780c74a0325e2851edad0dc8a566fa61a9e7fc4a34d13dcb509f99bc7",
"cafc41904dd5428934f7d075129c8ba46eb622d4fc88d72cd1401452664add18",
"3",
"0",
"0",
"0",
},
// Addition with z1!=z2 and z2!=1 same point.
// P(x, y, z) + P(x, y, z) = 2P
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"dcc3768780c74a0325e2851edad0dc8a566fa61a9e7fc4a34d13dcb509f99bc7",
"3503be6fb22abd76cb082f8aed63745b9149dd2b037728d32ebfebac99b51f17",
"3",
"9f153b13ee7bd915882859635ea9730bf0dc7611b2c7b0e37ee65073c50fabac",
"2b53702c466dcf6e984a35671756c506c67c2fcb8adb408c44dd125dc91cb988",
"6e3d537ae61fb1247eda4b4f523cfbaee5152c0d0d96b520376833c2e5944a11",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
// Convert hex to field values.
x1 := new(fieldVal).SetHex(test.x1)
y1 := new(fieldVal).SetHex(test.y1)
z1 := new(fieldVal).SetHex(test.z1)
x2 := new(fieldVal).SetHex(test.x2)
y2 := new(fieldVal).SetHex(test.y2)
z2 := new(fieldVal).SetHex(test.z2)
x3 := new(fieldVal).SetHex(test.x3)
y3 := new(fieldVal).SetHex(test.y3)
z3 := new(fieldVal).SetHex(test.z3)
// Ensure the test data is using points that are actually on
// the curve (or the point at infinity).
if !z1.IsZero() && !isJacobianOnS256Curve(x1, y1, z1) {
t.Errorf("#%d first point is not on the curve -- "+
"invalid test data", i)
continue
}
if !z2.IsZero() && !isJacobianOnS256Curve(x2, y2, z2) {
t.Errorf("#%d second point is not on the curve -- "+
"invalid test data", i)
continue
}
if !z3.IsZero() && !isJacobianOnS256Curve(x3, y3, z3) {
t.Errorf("#%d expected point is not on the curve -- "+
"invalid test data", i)
continue
}
// Add the two points.
rx, ry, rz := new(fieldVal), new(fieldVal), new(fieldVal)
S256().addJacobian(x1, y1, z1, x2, y2, z2, rx, ry, rz)
// Ensure result matches expected.
if !rx.Equals(x3) || !ry.Equals(y3) || !rz.Equals(z3) {
t.Errorf("#%d wrong result\ngot: (%v, %v, %v)\n"+
"want: (%v, %v, %v)", i, rx, ry, rz, x3, y3, z3)
continue
}
}
}
// TestAddAffine tests addition of points in affine coordinates.
func TestAddAffine(t *testing.T) {
tests := []struct {
x1, y1 string // Coordinates (in hex) of first point to add
x2, y2 string // Coordinates (in hex) of second point to add
x3, y3 string // Coordinates (in hex) of expected point
}{
// Addition with a point at infinity (left hand side).
// ∞ + P = P
{
"0",
"0",
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
},
// Addition with a point at infinity (right hand side).
// P + ∞ = P
{
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
"0",
"0",
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
},
// Addition with different x values.
{
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
"131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
"fd5b88c21d3143518d522cd2796f3d726793c88b3e05636bc829448e053fed69",
"21cf4f6a5be5ff6380234c50424a970b1f7e718f5eb58f68198c108d642a137f",
},
// Addition with same x opposite y.
// P(x, y) + P(x, -y) = infinity
{
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"f48e156428cf0276dc092da5856e182288d7569f97934a56fe44be60f0d359fd",
"0",
"0",
},
// Addition with same point.
// P(x, y) + P(x, y) = 2P
{
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"59477d88ae64a104dbb8d31ec4ce2d91b2fe50fa628fb6a064e22582196b365b",
"938dc8c0f13d1e75c987cb1a220501bd614b0d3dd9eb5c639847e1240216e3b6",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
// Convert hex to field values.
x1, y1 := fromHex(test.x1), fromHex(test.y1)
x2, y2 := fromHex(test.x2), fromHex(test.y2)
x3, y3 := fromHex(test.x3), fromHex(test.y3)
// Ensure the test data is using points that are actually on
// the curve (or the point at infinity).
if !(x1.Sign() == 0 && y1.Sign() == 0) && !S256().IsOnCurve(x1, y1) {
t.Errorf("#%d first point is not on the curve -- "+
"invalid test data", i)
continue
}
if !(x2.Sign() == 0 && y2.Sign() == 0) && !S256().IsOnCurve(x2, y2) {
t.Errorf("#%d second point is not on the curve -- "+
"invalid test data", i)
continue
}
if !(x3.Sign() == 0 && y3.Sign() == 0) && !S256().IsOnCurve(x3, y3) {
t.Errorf("#%d expected point is not on the curve -- "+
"invalid test data", i)
continue
}
// Add the two points.
rx, ry := S256().Add(x1, y1, x2, y2)
// Ensure result matches expected.
if rx.Cmp(x3) != 00 || ry.Cmp(y3) != 0 {
t.Errorf("#%d wrong result\ngot: (%x, %x)\n"+
"want: (%x, %x)", i, rx, ry, x3, y3)
continue
}
}
}
// TestDoubleJacobian tests doubling of points projected in Jacobian
// coordinates.
func TestDoubleJacobian(t *testing.T) {
tests := []struct {
x1, y1, z1 string // Coordinates (in hex) of point to double
x3, y3, z3 string // Coordinates (in hex) of expected point
}{
// Doubling a point at infinity is still infinity.
{
"0",
"0",
"0",
"0",
"0",
"0",
},
// Doubling with z1=1.
{
"34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
"0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
"1",
"ec9f153b13ee7bd915882859635ea9730bf0dc7611b2c7b0e37ee64f87c50c27",
"b082b53702c466dcf6e984a35671756c506c67c2fcb8adb408c44dd0755c8f2a",
"16e3d537ae61fb1247eda4b4f523cfbaee5152c0d0d96b520376833c1e594464",
},
// Doubling with z1!=1.
{
"d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718",
"5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190",
"2",
"9f153b13ee7bd915882859635ea9730bf0dc7611b2c7b0e37ee65073c50fabac",
"2b53702c466dcf6e984a35671756c506c67c2fcb8adb408c44dd125dc91cb988",
"6e3d537ae61fb1247eda4b4f523cfbaee5152c0d0d96b520376833c2e5944a11",
},
// From btcd issue #709.
{
"201e3f75715136d2f93c4f4598f91826f94ca01f4233a5bd35de9708859ca50d",
"bdf18566445e7562c6ada68aef02d498d7301503de5b18c6aef6e2b1722412e1",
"0000000000000000000000000000000000000000000000000000000000000001",
"4a5e0559863ebb4e9ed85f5c4fa76003d05d9a7626616e614a1f738621e3c220",
"00000000000000000000000000000000000000000000000000000001b1388778",
"7be30acc88bceac58d5b4d15de05a931ae602a07bcb6318d5dedc563e4482993",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
// Convert hex to field values.
x1 := new(fieldVal).SetHex(test.x1)
y1 := new(fieldVal).SetHex(test.y1)
z1 := new(fieldVal).SetHex(test.z1)
x3 := new(fieldVal).SetHex(test.x3)
y3 := new(fieldVal).SetHex(test.y3)
z3 := new(fieldVal).SetHex(test.z3)
// Ensure the test data is using points that are actually on
// the curve (or the point at infinity).
if !z1.IsZero() && !isJacobianOnS256Curve(x1, y1, z1) {
t.Errorf("#%d first point is not on the curve -- "+
"invalid test data", i)
continue
}
if !z3.IsZero() && !isJacobianOnS256Curve(x3, y3, z3) {
t.Errorf("#%d expected point is not on the curve -- "+
"invalid test data", i)
continue
}
// Double the point.
rx, ry, rz := new(fieldVal), new(fieldVal), new(fieldVal)
S256().doubleJacobian(x1, y1, z1, rx, ry, rz)
// Ensure result matches expected.
if !rx.Equals(x3) || !ry.Equals(y3) || !rz.Equals(z3) {
t.Errorf("#%d wrong result\ngot: (%v, %v, %v)\n"+
"want: (%v, %v, %v)", i, rx, ry, rz, x3, y3, z3)
continue
}
}
}
// TestDoubleAffine tests doubling of points in affine coordinates.
func TestDoubleAffine(t *testing.T) {
tests := []struct {
x1, y1 string // Coordinates (in hex) of point to double
x3, y3 string // Coordinates (in hex) of expected point
}{
// Doubling a point at infinity is still infinity.
// 2*∞ = ∞ (point at infinity)
{
"0",
"0",
"0",
"0",
},
// Random points.
{
"e41387ffd8baaeeb43c2faa44e141b19790e8ac1f7ff43d480dc132230536f86",
"1b88191d430f559896149c86cbcb703193105e3cf3213c0c3556399836a2b899",
"88da47a089d333371bd798c548ef7caae76e737c1980b452d367b3cfe3082c19",
"3b6f659b09a362821dfcfefdbfbc2e59b935ba081b6c249eb147b3c2100b1bc1",
},
{
"b3589b5d984f03ef7c80aeae444f919374799edf18d375cab10489a3009cff0c",
"c26cf343875b3630e15bccc61202815b5d8f1fd11308934a584a5babe69db36a",
"e193860172998751e527bb12563855602a227fc1f612523394da53b746bb2fb1",
"2bfcf13d2f5ab8bb5c611fab5ebbed3dc2f057062b39a335224c22f090c04789",
},
{
"2b31a40fbebe3440d43ac28dba23eee71c62762c3fe3dbd88b4ab82dc6a82340",
"9ba7deb02f5c010e217607fd49d58db78ec273371ea828b49891ce2fd74959a1",
"2c8d5ef0d343b1a1a48aa336078eadda8481cb048d9305dc4fdf7ee5f65973a2",
"bb4914ac729e26d3cd8f8dc8f702f3f4bb7e0e9c5ae43335f6e94c2de6c3dc95",
},
{
"61c64b760b51981fab54716d5078ab7dffc93730b1d1823477e27c51f6904c7a",
"ef6eb16ea1a36af69d7f66524c75a3a5e84c13be8fbc2e811e0563c5405e49bd",
"5f0dcdd2595f5ad83318a0f9da481039e36f135005420393e72dfca985b482f4",
"a01c849b0837065c1cb481b0932c441f49d1cab1b4b9f355c35173d93f110ae0",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
// Convert hex to field values.
x1, y1 := fromHex(test.x1), fromHex(test.y1)
x3, y3 := fromHex(test.x3), fromHex(test.y3)
// Ensure the test data is using points that are actually on
// the curve (or the point at infinity).
if !(x1.Sign() == 0 && y1.Sign() == 0) && !S256().IsOnCurve(x1, y1) {
t.Errorf("#%d first point is not on the curve -- "+
"invalid test data", i)
continue
}
if !(x3.Sign() == 0 && y3.Sign() == 0) && !S256().IsOnCurve(x3, y3) {
t.Errorf("#%d expected point is not on the curve -- "+
"invalid test data", i)
continue
}
// Double the point.
rx, ry := S256().Double(x1, y1)
// Ensure result matches expected.
if rx.Cmp(x3) != 00 || ry.Cmp(y3) != 0 {
t.Errorf("#%d wrong result\ngot: (%x, %x)\n"+
"want: (%x, %x)", i, rx, ry, x3, y3)
continue
}
}
}
func TestOnCurve(t *testing.T) {
s256 := S256()
if !s256.IsOnCurve(s256.Params().Gx, s256.Params().Gy) {
t.Errorf("FAIL S256")
}
}
type baseMultTest struct {
k string
x, y string
}
//TODO: add more test vectors
var s256BaseMultTests = []baseMultTest{
{
"AA5E28D6A97A2479A65527F7290311A3624D4CC0FA1578598EE3C2613BF99522",
"34F9460F0E4F08393D192B3C5133A6BA099AA0AD9FD54EBCCFACDFA239FF49C6",
"B71EA9BD730FD8923F6D25A7A91E7DD7728A960686CB5A901BB419E0F2CA232",
},
{
"7E2B897B8CEBC6361663AD410835639826D590F393D90A9538881735256DFAE3",
"D74BF844B0862475103D96A611CF2D898447E288D34B360BC885CB8CE7C00575",
"131C670D414C4546B88AC3FF664611B1C38CEB1C21D76369D7A7A0969D61D97D",
},
{
"6461E6DF0FE7DFD05329F41BF771B86578143D4DD1F7866FB4CA7E97C5FA945D",
"E8AECC370AEDD953483719A116711963CE201AC3EB21D3F3257BB48668C6A72F",
"C25CAF2F0EBA1DDB2F0F3F47866299EF907867B7D27E95B3873BF98397B24EE1",
},
{
"376A3A2CDCD12581EFFF13EE4AD44C4044B8A0524C42422A7E1E181E4DEECCEC",
"14890E61FCD4B0BD92E5B36C81372CA6FED471EF3AA60A3E415EE4FE987DABA1",
"297B858D9F752AB42D3BCA67EE0EB6DCD1C2B7B0DBE23397E66ADC272263F982",
},
{
"1B22644A7BE026548810C378D0B2994EEFA6D2B9881803CB02CEFF865287D1B9",
"F73C65EAD01C5126F28F442D087689BFA08E12763E0CEC1D35B01751FD735ED3",
"F449A8376906482A84ED01479BD18882B919C140D638307F0C0934BA12590BDE",
},
}
//TODO: test different curves as well?
func TestBaseMult(t *testing.T) {
s256 := S256()
for i, e := range s256BaseMultTests {
k, ok := new(big.Int).SetString(e.k, 16)
if !ok {
t.Errorf("%d: bad value for k: %s", i, e.k)
}
x, y := s256.ScalarBaseMult(k.Bytes())
if fmt.Sprintf("%X", x) != e.x || fmt.Sprintf("%X", y) != e.y {
t.Errorf("%d: bad output for k=%s: got (%X, %X), want (%s, %s)", i, e.k, x, y, e.x, e.y)
}
if testing.Short() && i > 5 {
break
}
}
}
func TestBaseMultVerify(t *testing.T) {
s256 := S256()
for bytes := 1; bytes < 40; bytes++ {
for i := 0; i < 30; i++ {
data := make([]byte, bytes)
_, err := rand.Read(data)
if err != nil {
t.Errorf("failed to read random data for %d", i)
continue
}
x, y := s256.ScalarBaseMult(data)
xWant, yWant := s256.ScalarMult(s256.Gx, s256.Gy, data)
if x.Cmp(xWant) != 0 || y.Cmp(yWant) != 0 {
t.Errorf("%d: bad output for %X: got (%X, %X), want (%X, %X)", i, data, x, y, xWant, yWant)
}
if testing.Short() && i > 2 {
break
}
}
}
}
func TestScalarMult(t *testing.T) {
tests := []struct {
x string
y string
k string
rx string
ry string
}{
// base mult, essentially.
{
"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
"18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725",
"50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352",
"2cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6",
},
// From btcd issue #709.
{
"000000000000000000000000000000000000000000000000000000000000002c",
"420e7a99bba18a9d3952597510fd2b6728cfeafc21a4e73951091d4d8ddbe94e",
"a2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba219b51835b55cc30ebfe2f6599bc56f58",
"a2112dcdfbcd10ae1133a358de7b82db68e0a3eb4b492cc8268d1e7118c98788",
"27fc7463b7bb3c5f98ecf2c84a6272bb1681ed553d92c69f2dfe25a9f9fd3836",
},
}
s256 := S256()
for i, test := range tests {
x, _ := new(big.Int).SetString(test.x, 16)
y, _ := new(big.Int).SetString(test.y, 16)
k, _ := new(big.Int).SetString(test.k, 16)
xWant, _ := new(big.Int).SetString(test.rx, 16)
yWant, _ := new(big.Int).SetString(test.ry, 16)
xGot, yGot := s256.ScalarMult(x, y, k.Bytes())
if xGot.Cmp(xWant) != 0 || yGot.Cmp(yWant) != 0 {
t.Fatalf("%d: bad output: got (%X, %X), want (%X, %X)", i, xGot, yGot, xWant, yWant)
}
}
}
func TestScalarMultRand(t *testing.T) {
// Strategy for this test:
// Get a random exponent from the generator point at first
// This creates a new point which is used in the next iteration
// Use another random exponent on the new point.
// We use BaseMult to verify by multiplying the previous exponent
// and the new random exponent together (mod N)
s256 := S256()
x, y := s256.Gx, s256.Gy
exponent := big.NewInt(1)
for i := 0; i < 1024; i++ {
data := make([]byte, 32)
_, err := rand.Read(data)
if err != nil {
t.Fatalf("failed to read random data at %d", i)
break
}
x, y = s256.ScalarMult(x, y, data)
exponent.Mul(exponent, new(big.Int).SetBytes(data))
xWant, yWant := s256.ScalarBaseMult(exponent.Bytes())
if x.Cmp(xWant) != 0 || y.Cmp(yWant) != 0 {
t.Fatalf("%d: bad output for %X: got (%X, %X), want (%X, %X)", i, data, x, y, xWant, yWant)
break
}
}
}
func TestSplitK(t *testing.T) {
tests := []struct {
k string
k1, k2 string
s1, s2 int
}{
{
"6df2b5d30854069ccdec40ae022f5c948936324a4e9ebed8eb82cfd5a6b6d766",
"00000000000000000000000000000000b776e53fb55f6b006a270d42d64ec2b1",
"00000000000000000000000000000000d6cc32c857f1174b604eefc544f0c7f7",
-1, -1,
},
{
"6ca00a8f10632170accc1b3baf2a118fa5725f41473f8959f34b8f860c47d88d",
"0000000000000000000000000000000007b21976c1795723c1bfbfa511e95b84",
"00000000000000000000000000000000d8d2d5f9d20fc64fd2cf9bda09a5bf90",
1, -1,
},
{
"b2eda8ab31b259032d39cbc2a234af17fcee89c863a8917b2740b67568166289",
"00000000000000000000000000000000507d930fecda7414fc4a523b95ef3c8c",
"00000000000000000000000000000000f65ffb179df189675338c6185cb839be",
-1, -1,
},
{
"f6f00e44f179936f2befc7442721b0633f6bafdf7161c167ffc6f7751980e3a0",
"0000000000000000000000000000000008d0264f10bcdcd97da3faa38f85308d",
"0000000000000000000000000000000065fed1506eb6605a899a54e155665f79",
-1, -1,
},
{
"8679085ab081dc92cdd23091ce3ee998f6b320e419c3475fae6b5b7d3081996e",
"0000000000000000000000000000000089fbf24fbaa5c3c137b4f1cedc51d975",
"00000000000000000000000000000000d38aa615bd6754d6f4d51ccdaf529fea",
-1, -1,
},
{
"6b1247bb7931dfcae5b5603c8b5ae22ce94d670138c51872225beae6bba8cdb3",
"000000000000000000000000000000008acc2a521b21b17cfb002c83be62f55d",
"0000000000000000000000000000000035f0eff4d7430950ecb2d94193dedc79",
-1, -1,
},
{
"a2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba219b51835b55cc30ebfe2f6599bc56f58",
"0000000000000000000000000000000045c53aa1bb56fcd68c011e2dad6758e4",
"00000000000000000000000000000000a2e79d200f27f2360fba57619936159b",
-1, -1,
},
}
s256 := S256()
for i, test := range tests {
k, ok := new(big.Int).SetString(test.k, 16)
if !ok {
t.Errorf("%d: bad value for k: %s", i, test.k)
}
k1, k2, k1Sign, k2Sign := s256.splitK(k.Bytes())
k1str := fmt.Sprintf("%064x", k1)
if test.k1 != k1str {
t.Errorf("%d: bad k1: got %v, want %v", i, k1str, test.k1)
}
k2str := fmt.Sprintf("%064x", k2)
if test.k2 != k2str {
t.Errorf("%d: bad k2: got %v, want %v", i, k2str, test.k2)
}
if test.s1 != k1Sign {
t.Errorf("%d: bad k1 sign: got %d, want %d", i, k1Sign, test.s1)
}
if test.s2 != k2Sign {
t.Errorf("%d: bad k2 sign: got %d, want %d", i, k2Sign, test.s2)
}
k1Int := new(big.Int).SetBytes(k1)
k1SignInt := new(big.Int).SetInt64(int64(k1Sign))
k1Int.Mul(k1Int, k1SignInt)
k2Int := new(big.Int).SetBytes(k2)
k2SignInt := new(big.Int).SetInt64(int64(k2Sign))
k2Int.Mul(k2Int, k2SignInt)
gotK := new(big.Int).Mul(k2Int, s256.lambda)
gotK.Add(k1Int, gotK)
gotK.Mod(gotK, s256.N)
if k.Cmp(gotK) != 0 {
t.Errorf("%d: bad k: got %X, want %X", i, gotK.Bytes(), k.Bytes())
}
}
}
func TestSplitKRand(t *testing.T) {
s256 := S256()
for i := 0; i < 1024; i++ {
bytesK := make([]byte, 32)
_, err := rand.Read(bytesK)
if err != nil {
t.Fatalf("failed to read random data at %d", i)
break
}
k := new(big.Int).SetBytes(bytesK)
k1, k2, k1Sign, k2Sign := s256.splitK(bytesK)
k1Int := new(big.Int).SetBytes(k1)
k1SignInt := new(big.Int).SetInt64(int64(k1Sign))
k1Int.Mul(k1Int, k1SignInt)
k2Int := new(big.Int).SetBytes(k2)
k2SignInt := new(big.Int).SetInt64(int64(k2Sign))
k2Int.Mul(k2Int, k2SignInt)
gotK := new(big.Int).Mul(k2Int, s256.lambda)
gotK.Add(k1Int, gotK)
gotK.Mod(gotK, s256.N)
if k.Cmp(gotK) != 0 {
t.Errorf("%d: bad k: got %X, want %X", i, gotK.Bytes(), k.Bytes())
}
}
}
// Test this curve's usage with the ecdsa package.
func testKeyGeneration(t *testing.T, c *KoblitzCurve, tag string) {
priv, err := NewPrivateKey(c)
if err != nil {
t.Errorf("%s: error: %s", tag, err)
return
}
if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) {
t.Errorf("%s: public key invalid: %s", tag, err)
}
}
func TestKeyGeneration(t *testing.T) {
testKeyGeneration(t, S256(), "S256")
}
func testSignAndVerify(t *testing.T, c *KoblitzCurve, tag string) {
priv, _ := NewPrivateKey(c)
pub := priv.PubKey()
hashed := []byte("testing")
sig, err := priv.Sign(hashed)
if err != nil {
t.Errorf("%s: error signing: %s", tag, err)
return
}
if !sig.Verify(hashed, pub) {
t.Errorf("%s: Verify failed", tag)
}
hashed[0] ^= 0xff
if sig.Verify(hashed, pub) {
t.Errorf("%s: Verify always works!", tag)
}
}
func TestSignAndVerify(t *testing.T) {
testSignAndVerify(t, S256(), "S256")
}
func TestNAF(t *testing.T) {
tests := []string{
"6df2b5d30854069ccdec40ae022f5c948936324a4e9ebed8eb82cfd5a6b6d766",
"b776e53fb55f6b006a270d42d64ec2b1",
"d6cc32c857f1174b604eefc544f0c7f7",
"45c53aa1bb56fcd68c011e2dad6758e4",
"a2e79d200f27f2360fba57619936159b",
}
negOne := big.NewInt(-1)
one := big.NewInt(1)
two := big.NewInt(2)
for i, test := range tests {
want, _ := new(big.Int).SetString(test, 16)
nafPos, nafNeg := NAF(want.Bytes())
got := big.NewInt(0)
// Check that the NAF representation comes up with the right number
for i := 0; i < len(nafPos); i++ {
bytePos := nafPos[i]
byteNeg := nafNeg[i]
for j := 7; j >= 0; j-- {
got.Mul(got, two)
if bytePos&0x80 == 0x80 {
got.Add(got, one)
} else if byteNeg&0x80 == 0x80 {
got.Add(got, negOne)
}
bytePos <<= 1
byteNeg <<= 1
}
}
if got.Cmp(want) != 0 {
t.Errorf("%d: Failed NAF got %X want %X", i, got, want)
}
}
}
func TestNAFRand(t *testing.T) {
negOne := big.NewInt(-1)
one := big.NewInt(1)
two := big.NewInt(2)
for i := 0; i < 1024; i++ {
data := make([]byte, 32)
_, err := rand.Read(data)
if err != nil {
t.Fatalf("failed to read random data at %d", i)
break
}
nafPos, nafNeg := NAF(data)
want := new(big.Int).SetBytes(data)
got := big.NewInt(0)
// Check that the NAF representation comes up with the right number
for i := 0; i < len(nafPos); i++ {
bytePos := nafPos[i]
byteNeg := nafNeg[i]
for j := 7; j >= 0; j-- {
got.Mul(got, two)
if bytePos&0x80 == 0x80 {
got.Add(got, one)
} else if byteNeg&0x80 == 0x80 {
got.Add(got, negOne)
}
bytePos <<= 1
byteNeg <<= 1
}
}
if got.Cmp(want) != 0 {
t.Errorf("%d: Failed NAF got %X want %X", i, got, want)
}
}
}
// Copyright (c) 2015-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"errors"
"io"
)
var (
// ErrInvalidMAC occurs when Message Authentication Check (MAC) fails
// during decryption. This happens because of either invalid private key or
// corrupt ciphertext.
ErrInvalidMAC = errors.New("invalid mac hash")
// errInputTooShort occurs when the input ciphertext to the Decrypt
// function is less than 134 bytes long.
errInputTooShort = errors.New("ciphertext too short")
// errUnsupportedCurve occurs when the first two bytes of the encrypted
// text aren't 0x02CA (= 712 = secp256k1, from OpenSSL).
errUnsupportedCurve = errors.New("unsupported curve")
errInvalidXLength = errors.New("invalid X length, must be 32")
errInvalidYLength = errors.New("invalid Y length, must be 32")
errInvalidPadding = errors.New("invalid PKCS#7 padding")
// 0x02CA = 714
ciphCurveBytes = [2]byte{0x02, 0xCA}
// 0x20 = 32
ciphCoordLength = [2]byte{0x00, 0x20}
)
// GenerateSharedSecret generates a shared secret based on a private key and a
// public key using Diffie-Hellman key exchange (ECDH) (RFC 4753).
// RFC5903 Section 9 states we should only return x.
func GenerateSharedSecret(privkey *PrivateKey, pubkey *PublicKey) []byte {
x, _ := pubkey.Curve.ScalarMult(pubkey.X, pubkey.Y, privkey.D.Bytes())
return x.Bytes()
}
// Encrypt encrypts data for the target public key using AES-256-CBC. It also
// generates a private key (the pubkey of which is also in the output). The only
// supported curve is secp256k1. The `structure' that it encodes everything into
// is:
//
// struct {
// // Initialization Vector used for AES-256-CBC
// IV [16]byte
// // Public Key: curve(2) + len_of_pubkeyX(2) + pubkeyX +
// // len_of_pubkeyY(2) + pubkeyY (curve = 714)
// PublicKey [70]byte
// // Cipher text
// Data []byte
// // HMAC-SHA-256 Message Authentication Code
// HMAC [32]byte
// }
//
// The primary aim is to ensure byte compatibility with Pyelliptic. Also, refer
// to section 5.8.1 of ANSI X9.63 for rationale on this format.
func Encrypt(pubkey *PublicKey, in []byte) ([]byte, error) {
ephemeral, err := NewPrivateKey(S256())
if err != nil {
return nil, err
}
ecdhKey := GenerateSharedSecret(ephemeral, pubkey)
derivedKey := sha512.Sum512(ecdhKey)
keyE := derivedKey[:32]
keyM := derivedKey[32:]
paddedIn := addPKCSPadding(in)
// IV + Curve params/X/Y + padded plaintext/ciphertext + HMAC-256
out := make([]byte, aes.BlockSize+70+len(paddedIn)+sha256.Size)
iv := out[:aes.BlockSize]
if _, err = io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
// start writing public key
pb := ephemeral.PubKey().SerializeUncompressed()
offset := aes.BlockSize
// curve and X length
copy(out[offset:offset+4], append(ciphCurveBytes[:], ciphCoordLength[:]...))
offset += 4
// X
copy(out[offset:offset+32], pb[1:33])
offset += 32
// Y length
copy(out[offset:offset+2], ciphCoordLength[:])
offset += 2
// Y
copy(out[offset:offset+32], pb[33:])
offset += 32
// start encryption
block, err := aes.NewCipher(keyE)
if err != nil {
return nil, err
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(out[offset:len(out)-sha256.Size], paddedIn)
// start HMAC-SHA-256
hm := hmac.New(sha256.New, keyM)
hm.Write(out[:len(out)-sha256.Size]) // everything is hashed
copy(out[len(out)-sha256.Size:], hm.Sum(nil)) // write checksum
return out, nil
}
// Decrypt decrypts data that was encrypted using the Encrypt function.
func Decrypt(priv *PrivateKey, in []byte) ([]byte, error) {
// IV + Curve params/X/Y + 1 block + HMAC-256
if len(in) < aes.BlockSize+70+aes.BlockSize+sha256.Size {
return nil, errInputTooShort
}
// read iv
iv := in[:aes.BlockSize]
offset := aes.BlockSize
// start reading pubkey
if !bytes.Equal(in[offset:offset+2], ciphCurveBytes[:]) {
return nil, errUnsupportedCurve
}
offset += 2
if !bytes.Equal(in[offset:offset+2], ciphCoordLength[:]) {
return nil, errInvalidXLength
}
offset += 2
xBytes := in[offset : offset+32]
offset += 32
if !bytes.Equal(in[offset:offset+2], ciphCoordLength[:]) {
return nil, errInvalidYLength
}
offset += 2
yBytes := in[offset : offset+32]
offset += 32
pb := make([]byte, 65)
pb[0] = byte(0x04) // uncompressed
copy(pb[1:33], xBytes)
copy(pb[33:], yBytes)
// check if (X, Y) lies on the curve and create a Pubkey if it does
pubkey, err := ParsePubKey(pb, S256())
if err != nil {
return nil, err
}
// check for cipher text length
if (len(in)-aes.BlockSize-offset-sha256.Size)%aes.BlockSize != 0 {
return nil, errInvalidPadding // not padded to 16 bytes
}
// read hmac
messageMAC := in[len(in)-sha256.Size:]
// generate shared secret
ecdhKey := GenerateSharedSecret(priv, pubkey)
derivedKey := sha512.Sum512(ecdhKey)
keyE := derivedKey[:32]
keyM := derivedKey[32:]
// verify mac
hm := hmac.New(sha256.New, keyM)
hm.Write(in[:len(in)-sha256.Size]) // everything is hashed
expectedMAC := hm.Sum(nil)
if !hmac.Equal(messageMAC, expectedMAC) {
return nil, ErrInvalidMAC
}
// start decryption
block, err := aes.NewCipher(keyE)
if err != nil {
return nil, err
}
mode := cipher.NewCBCDecrypter(block, iv)
// same length as ciphertext
plaintext := make([]byte, len(in)-offset-sha256.Size)
mode.CryptBlocks(plaintext, in[offset:len(in)-sha256.Size])
return removePKCSPadding(plaintext)
}
// Implement PKCS#7 padding with block size of 16 (AES block size).
// addPKCSPadding adds padding to a block of data
func addPKCSPadding(src []byte) []byte {
padding := aes.BlockSize - len(src)%aes.BlockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
// removePKCSPadding removes padding from data that was added with addPKCSPadding
func removePKCSPadding(src []byte) ([]byte, error) {
length := len(src)
padLength := int(src[length-1])
if padLength > aes.BlockSize || length < aes.BlockSize {
return nil, errInvalidPadding
}
return src[:length-padLength], nil
}
// Copyright (c) 2015-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"bytes"
"encoding/hex"
"testing"
)
func TestGenerateSharedSecret(t *testing.T) {
privKey1, err := NewPrivateKey(S256())
if err != nil {
t.Errorf("private key generation error: %s", err)
return
}
privKey2, err := NewPrivateKey(S256())
if err != nil {
t.Errorf("private key generation error: %s", err)
return
}
secret1 := GenerateSharedSecret(privKey1, privKey2.PubKey())
secret2 := GenerateSharedSecret(privKey2, privKey1.PubKey())
if !bytes.Equal(secret1, secret2) {
t.Errorf("ECDH failed, secrets mismatch - first: %x, second: %x",
secret1, secret2)
}
}
// Test 1: Encryption and decryption
func TestCipheringBasic(t *testing.T) {
privkey, err := NewPrivateKey(S256())
if err != nil {
t.Fatal("failed to generate private key")
}
in := []byte("Hey there dude. How are you doing? This is a test.")
out, err := Encrypt(privkey.PubKey(), in)
if err != nil {
t.Fatal("failed to encrypt:", err)
}
dec, err := Decrypt(privkey, out)
if err != nil {
t.Fatal("failed to decrypt:", err)
}
if !bytes.Equal(in, dec) {
t.Error("decrypted data doesn't match original")
}
}
// Test 2: Byte compatibility with Pyelliptic
func TestCiphering(t *testing.T) {
pb, _ := hex.DecodeString("fe38240982f313ae5afb3e904fb8215fb11af1200592b" +
"fca26c96c4738e4bf8f")
privkey, _ := PrivKeyFromBytes(S256(), pb)
in := []byte("This is just a test.")
out, _ := hex.DecodeString("b0d66e5adaa5ed4e2f0ca68e17b8f2fc02ca002009e3" +
"3487e7fa4ab505cf34d98f131be7bd258391588ca7804acb30251e71a04e0020ecf" +
"df0f84608f8add82d7353af780fbb28868c713b7813eb4d4e61f7b75d7534dd9856" +
"9b0ba77cf14348fcff80fee10e11981f1b4be372d93923e9178972f69937ec850ed" +
"6c3f11ff572ddd5b2bedf9f9c0b327c54da02a28fcdce1f8369ffec")
dec, err := Decrypt(privkey, out)
if err != nil {
t.Fatal("failed to decrypt:", err)
}
if !bytes.Equal(in, dec) {
t.Error("decrypted data doesn't match original")
}
}
func TestCipheringErrors(t *testing.T) {
privkey, err := NewPrivateKey(S256())
if err != nil {
t.Fatal("failed to generate private key")
}
tests1 := []struct {
ciphertext []byte // input ciphertext
}{
{bytes.Repeat([]byte{0x00}, 133)}, // errInputTooShort
{bytes.Repeat([]byte{0x00}, 134)}, // errUnsupportedCurve
{bytes.Repeat([]byte{0x02, 0xCA}, 134)}, // errInvalidXLength
{bytes.Repeat([]byte{0x02, 0xCA, 0x00, 0x20}, 134)}, // errInvalidYLength
{[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0xCA, 0x00, 0x20, // curve and X length
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // X
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x20, // Y length
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Y
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ciphertext
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MAC
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}}, // invalid pubkey
{[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0xCA, 0x00, 0x20, // curve and X length
0x11, 0x5C, 0x42, 0xE7, 0x57, 0xB2, 0xEF, 0xB7, // X
0x67, 0x1C, 0x57, 0x85, 0x30, 0xEC, 0x19, 0x1A,
0x13, 0x59, 0x38, 0x1E, 0x6A, 0x71, 0x12, 0x7A,
0x9D, 0x37, 0xC4, 0x86, 0xFD, 0x30, 0xDA, 0xE5,
0x00, 0x20, // Y length
0x7E, 0x76, 0xDC, 0x58, 0xF6, 0x93, 0xBD, 0x7E, // Y
0x70, 0x10, 0x35, 0x8C, 0xE6, 0xB1, 0x65, 0xE4,
0x83, 0xA2, 0x92, 0x10, 0x10, 0xDB, 0x67, 0xAC,
0x11, 0xB1, 0xB5, 0x1B, 0x65, 0x19, 0x53, 0xD2,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ciphertext
// padding not aligned to 16 bytes
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MAC
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}}, // errInvalidPadding
{[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0xCA, 0x00, 0x20, // curve and X length
0x11, 0x5C, 0x42, 0xE7, 0x57, 0xB2, 0xEF, 0xB7, // X
0x67, 0x1C, 0x57, 0x85, 0x30, 0xEC, 0x19, 0x1A,
0x13, 0x59, 0x38, 0x1E, 0x6A, 0x71, 0x12, 0x7A,
0x9D, 0x37, 0xC4, 0x86, 0xFD, 0x30, 0xDA, 0xE5,
0x00, 0x20, // Y length
0x7E, 0x76, 0xDC, 0x58, 0xF6, 0x93, 0xBD, 0x7E, // Y
0x70, 0x10, 0x35, 0x8C, 0xE6, 0xB1, 0x65, 0xE4,
0x83, 0xA2, 0x92, 0x10, 0x10, 0xDB, 0x67, 0xAC,
0x11, 0xB1, 0xB5, 0x1B, 0x65, 0x19, 0x53, 0xD2,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ciphertext
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MAC
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}}, // ErrInvalidMAC
}
for i, test := range tests1 {
_, err = Decrypt(privkey, test.ciphertext)
if err == nil {
t.Errorf("Decrypt #%d did not get error", i)
}
}
// test error from removePKCSPadding
tests2 := []struct {
in []byte // input data
}{
{bytes.Repeat([]byte{0x11}, 17)},
{bytes.Repeat([]byte{0x07}, 15)},
}
for i, test := range tests2 {
_, err = removePKCSPadding(test.in)
if err == nil {
t.Errorf("removePKCSPadding #%d did not get error", i)
}
}
}
// Copyright (c) 2013-2014 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
/*
Package btcec implements support for the elliptic curves needed for bitcoin.
Bitcoin uses elliptic curve cryptography using koblitz curves
(specifically secp256k1) for cryptographic functions. See
http://www.secg.org/collateral/sec2_final.pdf for details on the
standard.
This package provides the data structures and functions implementing the
crypto/elliptic Curve interface in order to permit using these curves
with the standard crypto/ecdsa package provided with go. Helper
functionality is provided to parse signatures and public keys from
standard formats. It was designed for use with btcd, but should be
general enough for other uses of elliptic curve crypto. It was originally based
on some initial work by ThePiachu, but has significantly diverged since then.
*/
package btcec
// Copyright (c) 2014 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec_test
import (
"encoding/hex"
"fmt"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg/chainhash"
)
// This example demonstrates signing a message with a secp256k1 private key that
// is first parsed form raw bytes and serializing the generated signature.
func Example_signMessage() {
// Decode a hex-encoded private key.
pkBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2d4f87" +
"20ee63e502ee2869afab7de234b80c")
if err != nil {
fmt.Println(err)
return
}
privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes)
// Sign a message using the private key.
message := "test message"
messageHash := chainhash.DoubleHashB([]byte(message))
signature, err := privKey.Sign(messageHash)
if err != nil {
fmt.Println(err)
return
}
// Serialize and display the signature.
fmt.Printf("Serialized Signature: %x\n", signature.Serialize())
// Verify the signature for the message using the public key.
verified := signature.Verify(messageHash, pubKey)
fmt.Printf("Signature Verified? %v\n", verified)
// Output:
// Serialized Signature: 304402201008e236fa8cd0f25df4482dddbb622e8a8b26ef0ba731719458de3ccd93805b022032f8ebe514ba5f672466eba334639282616bb3c2f0ab09998037513d1f9e3d6d
// Signature Verified? true
}
// This example demonstrates verifying a secp256k1 signature against a public
// key that is first parsed from raw bytes. The signature is also parsed from
// raw bytes.
func Example_verifySignature() {
// Decode hex-encoded serialized public key.
pubKeyBytes, err := hex.DecodeString("02a673638cb9587cb68ea08dbef685c" +
"6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5")
if err != nil {
fmt.Println(err)
return
}
pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256())
if err != nil {
fmt.Println(err)
return
}
// Decode hex-encoded serialized signature.
sigBytes, err := hex.DecodeString("30450220090ebfb3690a0ff115bb1b38b" +
"8b323a667b7653454f1bccb06d4bbdca42c2079022100ec95778b51e707" +
"1cb1205f8bde9af6592fc978b0452dafe599481c46d6b2e479")
if err != nil {
fmt.Println(err)
return
}
signature, err := btcec.ParseSignature(sigBytes, btcec.S256())
if err != nil {
fmt.Println(err)
return
}
// Verify the signature for the message using the public key.
message := "test message"
messageHash := chainhash.DoubleHashB([]byte(message))
verified := signature.Verify(messageHash, pubKey)
fmt.Println("Signature Verified?", verified)
// Output:
// Signature Verified? true
}
// This example demonstrates encrypting a message for a public key that is first
// parsed from raw bytes, then decrypting it using the corresponding private key.
func Example_encryptMessage() {
// Decode the hex-encoded pubkey of the recipient.
pubKeyBytes, err := hex.DecodeString("04115c42e757b2efb7671c578530ec191a1" +
"359381e6a71127a9d37c486fd30dae57e76dc58f693bd7e7010358ce6b165e483a29" +
"21010db67ac11b1b51b651953d2") // uncompressed pubkey
if err != nil {
fmt.Println(err)
return
}
pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256())
if err != nil {
fmt.Println(err)
return
}
// Encrypt a message decryptable by the private key corresponding to pubKey
message := "test message"
ciphertext, err := btcec.Encrypt(pubKey, []byte(message))
if err != nil {
fmt.Println(err)
return
}
// Decode the hex-encoded private key.
pkBytes, err := hex.DecodeString("a11b0a4e1a132305652ee7a8eb7848f6ad" +
"5ea381e3ce20a2c086a2e388230811")
if err != nil {
fmt.Println(err)
return
}
// note that we already have corresponding pubKey
privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes)
// Try decrypting and verify if it's the same message.
plaintext, err := btcec.Decrypt(privKey, ciphertext)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(plaintext))
// Output:
// test message
}
// This example demonstrates decrypting a message using a private key that is
// first parsed from raw bytes.
func Example_decryptMessage() {
// Decode the hex-encoded private key.
pkBytes, err := hex.DecodeString("a11b0a4e1a132305652ee7a8eb7848f6ad" +
"5ea381e3ce20a2c086a2e388230811")
if err != nil {
fmt.Println(err)
return
}
privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes)
ciphertext, err := hex.DecodeString("35f644fbfb208bc71e57684c3c8b437402ca" +
"002047a2f1b38aa1a8f1d5121778378414f708fe13ebf7b4a7bb74407288c1958969" +
"00207cf4ac6057406e40f79961c973309a892732ae7a74ee96cd89823913b8b8d650" +
"a44166dc61ea1c419d47077b748a9c06b8d57af72deb2819d98a9d503efc59fc8307" +
"d14174f8b83354fac3ff56075162")
// Try decrypting the message.
plaintext, err := btcec.Decrypt(privKey, ciphertext)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(plaintext))
// Output:
// test message
}
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2013-2016 Dave Collins
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
// References:
// [HAC]: Handbook of Applied Cryptography Menezes, van Oorschot, Vanstone.
// http://cacr.uwaterloo.ca/hac/
// All elliptic curve operations for secp256k1 are done in a finite field
// characterized by a 256-bit prime. Given this precision is larger than the
// biggest available native type, obviously some form of bignum math is needed.
// This package implements specialized fixed-precision field arithmetic rather
// than relying on an arbitrary-precision arithmetic package such as math/big
// for dealing with the field math since the size is known. As a result, rather
// large performance gains are achieved by taking advantage of many
// optimizations not available to arbitrary-precision arithmetic and generic
// modular arithmetic algorithms.
//
// There are various ways to internally represent each finite field element.
// For example, the most obvious representation would be to use an array of 4
// uint64s (64 bits * 4 = 256 bits). However, that representation suffers from
// a couple of issues. First, there is no native Go type large enough to handle
// the intermediate results while adding or multiplying two 64-bit numbers, and
// second there is no space left for overflows when performing the intermediate
// arithmetic between each array element which would lead to expensive carry
// propagation.
//
// Given the above, this implementation represents the the field elements as
// 10 uint32s with each word (array entry) treated as base 2^26. This was
// chosen for the following reasons:
// 1) Most systems at the current time are 64-bit (or at least have 64-bit
// registers available for specialized purposes such as MMX) so the
// intermediate results can typically be done using a native register (and
// using uint64s to avoid the need for additional half-word arithmetic)
// 2) In order to allow addition of the internal words without having to
// propagate the the carry, the max normalized value for each register must
// be less than the number of bits available in the register
// 3) Since we're dealing with 32-bit values, 64-bits of overflow is a
// reasonable choice for #2
// 4) Given the need for 256-bits of precision and the properties stated in #1,
// #2, and #3, the representation which best accommodates this is 10 uint32s
// with base 2^26 (26 bits * 10 = 260 bits, so the final word only needs 22
// bits) which leaves the desired 64 bits (32 * 10 = 320, 320 - 256 = 64) for
// overflow
//
// Since it is so important that the field arithmetic is extremely fast for
// high performance crypto, this package does not perform any validation where
// it ordinarily would. For example, some functions only give the correct
// result is the field is normalized and there is no checking to ensure it is.
// While I typically prefer to ensure all state and input is valid for most
// packages, this code is really only used internally and every extra check
// counts.
import (
"encoding/hex"
)
// Constants used to make the code more readable.
const (
twoBitsMask = 0x3
fourBitsMask = 0xf
sixBitsMask = 0x3f
eightBitsMask = 0xff
)
// Constants related to the field representation.
const (
// fieldWords is the number of words used to internally represent the
// 256-bit value.
fieldWords = 10
// fieldBase is the exponent used to form the numeric base of each word.
// 2^(fieldBase*i) where i is the word position.
fieldBase = 26
// fieldOverflowBits is the minimum number of "overflow" bits for each
// word in the field value.
fieldOverflowBits = 32 - fieldBase
// fieldBaseMask is the mask for the bits in each word needed to
// represent the numeric base of each word (except the most significant
// word).
fieldBaseMask = (1 << fieldBase) - 1
// fieldMSBBits is the number of bits in the most significant word used
// to represent the value.
fieldMSBBits = 256 - (fieldBase * (fieldWords - 1))
// fieldMSBMask is the mask for the bits in the most significant word
// needed to represent the value.
fieldMSBMask = (1 << fieldMSBBits) - 1
// fieldPrimeWordZero is word zero of the secp256k1 prime in the
// internal field representation. It is used during negation.
fieldPrimeWordZero = 0x3fffc2f
// fieldPrimeWordOne is word one of the secp256k1 prime in the
// internal field representation. It is used during negation.
fieldPrimeWordOne = 0x3ffffbf
)
var (
// fieldQBytes is the value Q = (P+1)/4 for the secp256k1 prime P. This
// value is used to efficiently compute the square root of values in the
// field via exponentiation. The value of Q in hex is:
//
// Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c
fieldQBytes = []byte{
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x0c,
}
)
// fieldVal implements optimized fixed-precision arithmetic over the
// secp256k1 finite field. This means all arithmetic is performed modulo
// 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f. It
// represents each 256-bit value as 10 32-bit integers in base 2^26. This
// provides 6 bits of overflow in each word (10 bits in the most significant
// word) for a total of 64 bits of overflow (9*6 + 10 = 64). It only implements
// the arithmetic needed for elliptic curve operations.
//
// The following depicts the internal representation:
// -----------------------------------------------------------------
// | n[9] | n[8] | ... | n[0] |
// | 32 bits available | 32 bits available | ... | 32 bits available |
// | 22 bits for value | 26 bits for value | ... | 26 bits for value |
// | 10 bits overflow | 6 bits overflow | ... | 6 bits overflow |
// | Mult: 2^(26*9) | Mult: 2^(26*8) | ... | Mult: 2^(26*0) |
// -----------------------------------------------------------------
//
// For example, consider the number 2^49 + 1. It would be represented as:
// n[0] = 1
// n[1] = 2^23
// n[2..9] = 0
//
// The full 256-bit value is then calculated by looping i from 9..0 and
// doing sum(n[i] * 2^(26i)) like so:
// n[9] * 2^(26*9) = 0 * 2^234 = 0
// n[8] * 2^(26*8) = 0 * 2^208 = 0
// ...
// n[1] * 2^(26*1) = 2^23 * 2^26 = 2^49
// n[0] * 2^(26*0) = 1 * 2^0 = 1
// Sum: 0 + 0 + ... + 2^49 + 1 = 2^49 + 1
type fieldVal struct {
n [10]uint32
}
// String returns the field value as a human-readable hex string.
func (f fieldVal) String() string {
t := new(fieldVal).Set(&f).Normalize()
return hex.EncodeToString(t.Bytes()[:])
}
// Zero sets the field value to zero. A newly created field value is already
// set to zero. This function can be useful to clear an existing field value
// for reuse.
func (f *fieldVal) Zero() {
f.n[0] = 0
f.n[1] = 0
f.n[2] = 0
f.n[3] = 0
f.n[4] = 0
f.n[5] = 0
f.n[6] = 0
f.n[7] = 0
f.n[8] = 0
f.n[9] = 0
}
// Set sets the field value equal to the passed value.
//
// The field value is returned to support chaining. This enables syntax like:
// f := new(fieldVal).Set(f2).Add(1) so that f = f2 + 1 where f2 is not
// modified.
func (f *fieldVal) Set(val *fieldVal) *fieldVal {
*f = *val
return f
}
// SetInt sets the field value to the passed integer. This is a convenience
// function since it is fairly common to perform some arithemetic with small
// native integers.
//
// The field value is returned to support chaining. This enables syntax such
// as f := new(fieldVal).SetInt(2).Mul(f2) so that f = 2 * f2.
func (f *fieldVal) SetInt(ui uint) *fieldVal {
f.Zero()
f.n[0] = uint32(ui)
return f
}
// SetBytes packs the passed 32-byte big-endian value into the internal field
// value representation.
//
// The field value is returned to support chaining. This enables syntax like:
// f := new(fieldVal).SetBytes(byteArray).Mul(f2) so that f = ba * f2.
func (f *fieldVal) SetBytes(b *[32]byte) *fieldVal {
// Pack the 256 total bits across the 10 uint32 words with a max of
// 26-bits per word. This could be done with a couple of for loops,
// but this unrolled version is significantly faster. Benchmarks show
// this is about 34 times faster than the variant which uses loops.
f.n[0] = uint32(b[31]) | uint32(b[30])<<8 | uint32(b[29])<<16 |
(uint32(b[28])&twoBitsMask)<<24
f.n[1] = uint32(b[28])>>2 | uint32(b[27])<<6 | uint32(b[26])<<14 |
(uint32(b[25])&fourBitsMask)<<22
f.n[2] = uint32(b[25])>>4 | uint32(b[24])<<4 | uint32(b[23])<<12 |
(uint32(b[22])&sixBitsMask)<<20
f.n[3] = uint32(b[22])>>6 | uint32(b[21])<<2 | uint32(b[20])<<10 |
uint32(b[19])<<18
f.n[4] = uint32(b[18]) | uint32(b[17])<<8 | uint32(b[16])<<16 |
(uint32(b[15])&twoBitsMask)<<24
f.n[5] = uint32(b[15])>>2 | uint32(b[14])<<6 | uint32(b[13])<<14 |
(uint32(b[12])&fourBitsMask)<<22
f.n[6] = uint32(b[12])>>4 | uint32(b[11])<<4 | uint32(b[10])<<12 |
(uint32(b[9])&sixBitsMask)<<20
f.n[7] = uint32(b[9])>>6 | uint32(b[8])<<2 | uint32(b[7])<<10 |
uint32(b[6])<<18
f.n[8] = uint32(b[5]) | uint32(b[4])<<8 | uint32(b[3])<<16 |
(uint32(b[2])&twoBitsMask)<<24
f.n[9] = uint32(b[2])>>2 | uint32(b[1])<<6 | uint32(b[0])<<14
return f
}
// SetByteSlice interprets the provided slice as a 256-bit big-endian unsigned
// integer (meaning it is truncated to the first 32 bytes), packs it into the
// internal field value representation, and returns the updated field value.
//
// Note that since passing a slice with more than 32 bytes is truncated, it is
// possible that the truncated value is less than the field prime. It is up to
// the caller to decide whether it needs to provide numbers of the appropriate
// size or if it is acceptable to use this function with the described
// truncation behavior.
//
// The field value is returned to support chaining. This enables syntax like:
// f := new(fieldVal).SetByteSlice(byteSlice)
func (f *fieldVal) SetByteSlice(b []byte) *fieldVal {
var b32 [32]byte
if len(b) > 32 {
b = b[:32]
}
copy(b32[32-len(b):], b)
return f.SetBytes(&b32)
}
// SetHex decodes the passed big-endian hex string into the internal field value
// representation. Only the first 32-bytes are used.
//
// The field value is returned to support chaining. This enables syntax like:
// f := new(fieldVal).SetHex("0abc").Add(1) so that f = 0x0abc + 1
func (f *fieldVal) SetHex(hexString string) *fieldVal {
if len(hexString)%2 != 0 {
hexString = "0" + hexString
}
bytes, _ := hex.DecodeString(hexString)
return f.SetByteSlice(bytes)
}
// Normalize normalizes the internal field words into the desired range and
// performs fast modular reduction over the secp256k1 prime by making use of the
// special form of the prime.
func (f *fieldVal) Normalize() *fieldVal {
// The field representation leaves 6 bits of overflow in each word so
// intermediate calculations can be performed without needing to
// propagate the carry to each higher word during the calculations. In
// order to normalize, we need to "compact" the full 256-bit value to
// the right while propagating any carries through to the high order
// word.
//
// Since this field is doing arithmetic modulo the secp256k1 prime, we
// also need to perform modular reduction over the prime.
//
// Per [HAC] section 14.3.4: Reduction method of moduli of special form,
// when the modulus is of the special form m = b^t - c, highly efficient
// reduction can be achieved.
//
// The secp256k1 prime is equivalent to 2^256 - 4294968273, so it fits
// this criteria.
//
// 4294968273 in field representation (base 2^26) is:
// n[0] = 977
// n[1] = 64
// That is to say (2^26 * 64) + 977 = 4294968273
//
// The algorithm presented in the referenced section typically repeats
// until the quotient is zero. However, due to our field representation
// we already know to within one reduction how many times we would need
// to repeat as it's the uppermost bits of the high order word. Thus we
// can simply multiply the magnitude by the field representation of the
// prime and do a single iteration. After this step there might be an
// additional carry to bit 256 (bit 22 of the high order word).
t9 := f.n[9]
m := t9 >> fieldMSBBits
t9 = t9 & fieldMSBMask
t0 := f.n[0] + m*977
t1 := (t0 >> fieldBase) + f.n[1] + (m << 6)
t0 = t0 & fieldBaseMask
t2 := (t1 >> fieldBase) + f.n[2]
t1 = t1 & fieldBaseMask
t3 := (t2 >> fieldBase) + f.n[3]
t2 = t2 & fieldBaseMask
t4 := (t3 >> fieldBase) + f.n[4]
t3 = t3 & fieldBaseMask
t5 := (t4 >> fieldBase) + f.n[5]
t4 = t4 & fieldBaseMask
t6 := (t5 >> fieldBase) + f.n[6]
t5 = t5 & fieldBaseMask
t7 := (t6 >> fieldBase) + f.n[7]
t6 = t6 & fieldBaseMask
t8 := (t7 >> fieldBase) + f.n[8]
t7 = t7 & fieldBaseMask
t9 = (t8 >> fieldBase) + t9
t8 = t8 & fieldBaseMask
// At this point, the magnitude is guaranteed to be one, however, the
// value could still be greater than the prime if there was either a
// carry through to bit 256 (bit 22 of the higher order word) or the
// value is greater than or equal to the field characteristic. The
// following determines if either or these conditions are true and does
// the final reduction in constant time.
//
// Note that the if/else statements here intentionally do the bitwise
// operators even when it won't change the value to ensure constant time
// between the branches. Also note that 'm' will be zero when neither
// of the aforementioned conditions are true and the value will not be
// changed when 'm' is zero.
m = 1
if t9 == fieldMSBMask {
m &= 1
} else {
m &= 0
}
if t2&t3&t4&t5&t6&t7&t8 == fieldBaseMask {
m &= 1
} else {
m &= 0
}
if ((t0+977)>>fieldBase + t1 + 64) > fieldBaseMask {
m &= 1
} else {
m &= 0
}
if t9>>fieldMSBBits != 0 {
m |= 1
} else {
m |= 0
}
t0 = t0 + m*977
t1 = (t0 >> fieldBase) + t1 + (m << 6)
t0 = t0 & fieldBaseMask
t2 = (t1 >> fieldBase) + t2
t1 = t1 & fieldBaseMask
t3 = (t2 >> fieldBase) + t3
t2 = t2 & fieldBaseMask
t4 = (t3 >> fieldBase) + t4
t3 = t3 & fieldBaseMask
t5 = (t4 >> fieldBase) + t5
t4 = t4 & fieldBaseMask
t6 = (t5 >> fieldBase) + t6
t5 = t5 & fieldBaseMask
t7 = (t6 >> fieldBase) + t7
t6 = t6 & fieldBaseMask
t8 = (t7 >> fieldBase) + t8
t7 = t7 & fieldBaseMask
t9 = (t8 >> fieldBase) + t9
t8 = t8 & fieldBaseMask
t9 = t9 & fieldMSBMask // Remove potential multiple of 2^256.
// Finally, set the normalized and reduced words.
f.n[0] = t0
f.n[1] = t1
f.n[2] = t2
f.n[3] = t3
f.n[4] = t4
f.n[5] = t5
f.n[6] = t6
f.n[7] = t7
f.n[8] = t8
f.n[9] = t9
return f
}
// PutBytes unpacks the field value to a 32-byte big-endian value using the
// passed byte array. There is a similar function, Bytes, which unpacks the
// field value into a new array and returns that. This version is provided
// since it can be useful to cut down on the number of allocations by allowing
// the caller to reuse a buffer.
//
// The field value must be normalized for this function to return the correct
// result.
func (f *fieldVal) PutBytes(b *[32]byte) {
// Unpack the 256 total bits from the 10 uint32 words with a max of
// 26-bits per word. This could be done with a couple of for loops,
// but this unrolled version is a bit faster. Benchmarks show this is
// about 10 times faster than the variant which uses loops.
b[31] = byte(f.n[0] & eightBitsMask)
b[30] = byte((f.n[0] >> 8) & eightBitsMask)
b[29] = byte((f.n[0] >> 16) & eightBitsMask)
b[28] = byte((f.n[0]>>24)&twoBitsMask | (f.n[1]&sixBitsMask)<<2)
b[27] = byte((f.n[1] >> 6) & eightBitsMask)
b[26] = byte((f.n[1] >> 14) & eightBitsMask)
b[25] = byte((f.n[1]>>22)&fourBitsMask | (f.n[2]&fourBitsMask)<<4)
b[24] = byte((f.n[2] >> 4) & eightBitsMask)
b[23] = byte((f.n[2] >> 12) & eightBitsMask)
b[22] = byte((f.n[2]>>20)&sixBitsMask | (f.n[3]&twoBitsMask)<<6)
b[21] = byte((f.n[3] >> 2) & eightBitsMask)
b[20] = byte((f.n[3] >> 10) & eightBitsMask)
b[19] = byte((f.n[3] >> 18) & eightBitsMask)
b[18] = byte(f.n[4] & eightBitsMask)
b[17] = byte((f.n[4] >> 8) & eightBitsMask)
b[16] = byte((f.n[4] >> 16) & eightBitsMask)
b[15] = byte((f.n[4]>>24)&twoBitsMask | (f.n[5]&sixBitsMask)<<2)
b[14] = byte((f.n[5] >> 6) & eightBitsMask)
b[13] = byte((f.n[5] >> 14) & eightBitsMask)
b[12] = byte((f.n[5]>>22)&fourBitsMask | (f.n[6]&fourBitsMask)<<4)
b[11] = byte((f.n[6] >> 4) & eightBitsMask)
b[10] = byte((f.n[6] >> 12) & eightBitsMask)
b[9] = byte((f.n[6]>>20)&sixBitsMask | (f.n[7]&twoBitsMask)<<6)
b[8] = byte((f.n[7] >> 2) & eightBitsMask)
b[7] = byte((f.n[7] >> 10) & eightBitsMask)
b[6] = byte((f.n[7] >> 18) & eightBitsMask)
b[5] = byte(f.n[8] & eightBitsMask)
b[4] = byte((f.n[8] >> 8) & eightBitsMask)
b[3] = byte((f.n[8] >> 16) & eightBitsMask)
b[2] = byte((f.n[8]>>24)&twoBitsMask | (f.n[9]&sixBitsMask)<<2)
b[1] = byte((f.n[9] >> 6) & eightBitsMask)
b[0] = byte((f.n[9] >> 14) & eightBitsMask)
}
// Bytes unpacks the field value to a 32-byte big-endian value. See PutBytes
// for a variant that allows the a buffer to be passed which can be useful to
// to cut down on the number of allocations by allowing the caller to reuse a
// buffer.
//
// The field value must be normalized for this function to return correct
// result.
func (f *fieldVal) Bytes() *[32]byte {
b := new([32]byte)
f.PutBytes(b)
return b
}
// IsZero returns whether or not the field value is equal to zero.
func (f *fieldVal) IsZero() bool {
// The value can only be zero if no bits are set in any of the words.
// This is a constant time implementation.
bits := f.n[0] | f.n[1] | f.n[2] | f.n[3] | f.n[4] |
f.n[5] | f.n[6] | f.n[7] | f.n[8] | f.n[9]
return bits == 0
}
// IsOdd returns whether or not the field value is an odd number.
//
// The field value must be normalized for this function to return correct
// result.
func (f *fieldVal) IsOdd() bool {
// Only odd numbers have the bottom bit set.
return f.n[0]&1 == 1
}
// Equals returns whether or not the two field values are the same. Both
// field values being compared must be normalized for this function to return
// the correct result.
func (f *fieldVal) Equals(val *fieldVal) bool {
// Xor only sets bits when they are different, so the two field values
// can only be the same if no bits are set after xoring each word.
// This is a constant time implementation.
bits := (f.n[0] ^ val.n[0]) | (f.n[1] ^ val.n[1]) | (f.n[2] ^ val.n[2]) |
(f.n[3] ^ val.n[3]) | (f.n[4] ^ val.n[4]) | (f.n[5] ^ val.n[5]) |
(f.n[6] ^ val.n[6]) | (f.n[7] ^ val.n[7]) | (f.n[8] ^ val.n[8]) |
(f.n[9] ^ val.n[9])
return bits == 0
}
// NegateVal negates the passed value and stores the result in f. The caller
// must provide the magnitude of the passed value for a correct result.
//
// The field value is returned to support chaining. This enables syntax like:
// f.NegateVal(f2).AddInt(1) so that f = -f2 + 1.
func (f *fieldVal) NegateVal(val *fieldVal, magnitude uint32) *fieldVal {
// Negation in the field is just the prime minus the value. However,
// in order to allow negation against a field value without having to
// normalize/reduce it first, multiply by the magnitude (that is how
// "far" away it is from the normalized value) to adjust. Also, since
// negating a value pushes it one more order of magnitude away from the
// normalized range, add 1 to compensate.
//
// For some intuition here, imagine you're performing mod 12 arithmetic
// (picture a clock) and you are negating the number 7. So you start at
// 12 (which is of course 0 under mod 12) and count backwards (left on
// the clock) 7 times to arrive at 5. Notice this is just 12-7 = 5.
// Now, assume you're starting with 19, which is a number that is
// already larger than the modulus and congruent to 7 (mod 12). When a
// value is already in the desired range, its magnitude is 1. Since 19
// is an additional "step", its magnitude (mod 12) is 2. Since any
// multiple of the modulus is conguent to zero (mod m), the answer can
// be shortcut by simply mulplying the magnitude by the modulus and
// subtracting. Keeping with the example, this would be (2*12)-19 = 5.
f.n[0] = (magnitude+1)*fieldPrimeWordZero - val.n[0]
f.n[1] = (magnitude+1)*fieldPrimeWordOne - val.n[1]
f.n[2] = (magnitude+1)*fieldBaseMask - val.n[2]
f.n[3] = (magnitude+1)*fieldBaseMask - val.n[3]
f.n[4] = (magnitude+1)*fieldBaseMask - val.n[4]
f.n[5] = (magnitude+1)*fieldBaseMask - val.n[5]
f.n[6] = (magnitude+1)*fieldBaseMask - val.n[6]
f.n[7] = (magnitude+1)*fieldBaseMask - val.n[7]
f.n[8] = (magnitude+1)*fieldBaseMask - val.n[8]
f.n[9] = (magnitude+1)*fieldMSBMask - val.n[9]
return f
}
// Negate negates the field value. The existing field value is modified. The
// caller must provide the magnitude of the field value for a correct result.
//
// The field value is returned to support chaining. This enables syntax like:
// f.Negate().AddInt(1) so that f = -f + 1.
func (f *fieldVal) Negate(magnitude uint32) *fieldVal {
return f.NegateVal(f, magnitude)
}
// AddInt adds the passed integer to the existing field value and stores the
// result in f. This is a convenience function since it is fairly common to
// perform some arithemetic with small native integers.
//
// The field value is returned to support chaining. This enables syntax like:
// f.AddInt(1).Add(f2) so that f = f + 1 + f2.
func (f *fieldVal) AddInt(ui uint) *fieldVal {
// Since the field representation intentionally provides overflow bits,
// it's ok to use carryless addition as the carry bit is safely part of
// the word and will be normalized out.
f.n[0] += uint32(ui)
return f
}
// Add adds the passed value to the existing field value and stores the result
// in f.
//
// The field value is returned to support chaining. This enables syntax like:
// f.Add(f2).AddInt(1) so that f = f + f2 + 1.
func (f *fieldVal) Add(val *fieldVal) *fieldVal {
// Since the field representation intentionally provides overflow bits,
// it's ok to use carryless addition as the carry bit is safely part of
// each word and will be normalized out. This could obviously be done
// in a loop, but the unrolled version is faster.
f.n[0] += val.n[0]
f.n[1] += val.n[1]
f.n[2] += val.n[2]
f.n[3] += val.n[3]
f.n[4] += val.n[4]
f.n[5] += val.n[5]
f.n[6] += val.n[6]
f.n[7] += val.n[7]
f.n[8] += val.n[8]
f.n[9] += val.n[9]
return f
}
// Add2 adds the passed two field values together and stores the result in f.
//
// The field value is returned to support chaining. This enables syntax like:
// f3.Add2(f, f2).AddInt(1) so that f3 = f + f2 + 1.
func (f *fieldVal) Add2(val *fieldVal, val2 *fieldVal) *fieldVal {
// Since the field representation intentionally provides overflow bits,
// it's ok to use carryless addition as the carry bit is safely part of
// each word and will be normalized out. This could obviously be done
// in a loop, but the unrolled version is faster.
f.n[0] = val.n[0] + val2.n[0]
f.n[1] = val.n[1] + val2.n[1]
f.n[2] = val.n[2] + val2.n[2]
f.n[3] = val.n[3] + val2.n[3]
f.n[4] = val.n[4] + val2.n[4]
f.n[5] = val.n[5] + val2.n[5]
f.n[6] = val.n[6] + val2.n[6]
f.n[7] = val.n[7] + val2.n[7]
f.n[8] = val.n[8] + val2.n[8]
f.n[9] = val.n[9] + val2.n[9]
return f
}
// MulInt multiplies the field value by the passed int and stores the result in
// f. Note that this function can overflow if multiplying the value by any of
// the individual words exceeds a max uint32. Therefore it is important that
// the caller ensures no overflows will occur before using this function.
//
// The field value is returned to support chaining. This enables syntax like:
// f.MulInt(2).Add(f2) so that f = 2 * f + f2.
func (f *fieldVal) MulInt(val uint) *fieldVal {
// Since each word of the field representation can hold up to
// fieldOverflowBits extra bits which will be normalized out, it's safe
// to multiply each word without using a larger type or carry
// propagation so long as the values won't overflow a uint32. This
// could obviously be done in a loop, but the unrolled version is
// faster.
ui := uint32(val)
f.n[0] *= ui
f.n[1] *= ui
f.n[2] *= ui
f.n[3] *= ui
f.n[4] *= ui
f.n[5] *= ui
f.n[6] *= ui
f.n[7] *= ui
f.n[8] *= ui
f.n[9] *= ui
return f
}
// Mul multiplies the passed value to the existing field value and stores the
// result in f. Note that this function can overflow if multiplying any
// of the individual words exceeds a max uint32. In practice, this means the
// magnitude of either value involved in the multiplication must be a max of
// 8.
//
// The field value is returned to support chaining. This enables syntax like:
// f.Mul(f2).AddInt(1) so that f = (f * f2) + 1.
func (f *fieldVal) Mul(val *fieldVal) *fieldVal {
return f.Mul2(f, val)
}
// Mul2 multiplies the passed two field values together and stores the result
// result in f. Note that this function can overflow if multiplying any of
// the individual words exceeds a max uint32. In practice, this means the
// magnitude of either value involved in the multiplication must be a max of
// 8.
//
// The field value is returned to support chaining. This enables syntax like:
// f3.Mul2(f, f2).AddInt(1) so that f3 = (f * f2) + 1.
func (f *fieldVal) Mul2(val *fieldVal, val2 *fieldVal) *fieldVal {
// This could be done with a couple of for loops and an array to store
// the intermediate terms, but this unrolled version is significantly
// faster.
// Terms for 2^(fieldBase*0).
m := uint64(val.n[0]) * uint64(val2.n[0])
t0 := m & fieldBaseMask
// Terms for 2^(fieldBase*1).
m = (m >> fieldBase) +
uint64(val.n[0])*uint64(val2.n[1]) +
uint64(val.n[1])*uint64(val2.n[0])
t1 := m & fieldBaseMask
// Terms for 2^(fieldBase*2).
m = (m >> fieldBase) +
uint64(val.n[0])*uint64(val2.n[2]) +
uint64(val.n[1])*uint64(val2.n[1]) +
uint64(val.n[2])*uint64(val2.n[0])
t2 := m & fieldBaseMask
// Terms for 2^(fieldBase*3).
m = (m >> fieldBase) +
uint64(val.n[0])*uint64(val2.n[3]) +
uint64(val.n[1])*uint64(val2.n[2]) +
uint64(val.n[2])*uint64(val2.n[1]) +
uint64(val.n[3])*uint64(val2.n[0])
t3 := m & fieldBaseMask
// Terms for 2^(fieldBase*4).
m = (m >> fieldBase) +
uint64(val.n[0])*uint64(val2.n[4]) +
uint64(val.n[1])*uint64(val2.n[3]) +
uint64(val.n[2])*uint64(val2.n[2]) +
uint64(val.n[3])*uint64(val2.n[1]) +
uint64(val.n[4])*uint64(val2.n[0])
t4 := m & fieldBaseMask
// Terms for 2^(fieldBase*5).
m = (m >> fieldBase) +
uint64(val.n[0])*uint64(val2.n[5]) +
uint64(val.n[1])*uint64(val2.n[4]) +
uint64(val.n[2])*uint64(val2.n[3]) +
uint64(val.n[3])*uint64(val2.n[2]) +
uint64(val.n[4])*uint64(val2.n[1]) +
uint64(val.n[5])*uint64(val2.n[0])
t5 := m & fieldBaseMask
// Terms for 2^(fieldBase*6).
m = (m >> fieldBase) +
uint64(val.n[0])*uint64(val2.n[6]) +
uint64(val.n[1])*uint64(val2.n[5]) +
uint64(val.n[2])*uint64(val2.n[4]) +
uint64(val.n[3])*uint64(val2.n[3]) +
uint64(val.n[4])*uint64(val2.n[2]) +
uint64(val.n[5])*uint64(val2.n[1]) +
uint64(val.n[6])*uint64(val2.n[0])
t6 := m & fieldBaseMask
// Terms for 2^(fieldBase*7).
m = (m >> fieldBase) +
uint64(val.n[0])*uint64(val2.n[7]) +
uint64(val.n[1])*uint64(val2.n[6]) +
uint64(val.n[2])*uint64(val2.n[5]) +
uint64(val.n[3])*uint64(val2.n[4]) +
uint64(val.n[4])*uint64(val2.n[3]) +
uint64(val.n[5])*uint64(val2.n[2]) +
uint64(val.n[6])*uint64(val2.n[1]) +
uint64(val.n[7])*uint64(val2.n[0])
t7 := m & fieldBaseMask
// Terms for 2^(fieldBase*8).
m = (m >> fieldBase) +
uint64(val.n[0])*uint64(val2.n[8]) +
uint64(val.n[1])*uint64(val2.n[7]) +
uint64(val.n[2])*uint64(val2.n[6]) +
uint64(val.n[3])*uint64(val2.n[5]) +
uint64(val.n[4])*uint64(val2.n[4]) +
uint64(val.n[5])*uint64(val2.n[3]) +
uint64(val.n[6])*uint64(val2.n[2]) +
uint64(val.n[7])*uint64(val2.n[1]) +
uint64(val.n[8])*uint64(val2.n[0])
t8 := m & fieldBaseMask
// Terms for 2^(fieldBase*9).
m = (m >> fieldBase) +
uint64(val.n[0])*uint64(val2.n[9]) +
uint64(val.n[1])*uint64(val2.n[8]) +
uint64(val.n[2])*uint64(val2.n[7]) +
uint64(val.n[3])*uint64(val2.n[6]) +
uint64(val.n[4])*uint64(val2.n[5]) +
uint64(val.n[5])*uint64(val2.n[4]) +
uint64(val.n[6])*uint64(val2.n[3]) +
uint64(val.n[7])*uint64(val2.n[2]) +
uint64(val.n[8])*uint64(val2.n[1]) +
uint64(val.n[9])*uint64(val2.n[0])
t9 := m & fieldBaseMask
// Terms for 2^(fieldBase*10).
m = (m >> fieldBase) +
uint64(val.n[1])*uint64(val2.n[9]) +
uint64(val.n[2])*uint64(val2.n[8]) +
uint64(val.n[3])*uint64(val2.n[7]) +
uint64(val.n[4])*uint64(val2.n[6]) +
uint64(val.n[5])*uint64(val2.n[5]) +
uint64(val.n[6])*uint64(val2.n[4]) +
uint64(val.n[7])*uint64(val2.n[3]) +
uint64(val.n[8])*uint64(val2.n[2]) +
uint64(val.n[9])*uint64(val2.n[1])
t10 := m & fieldBaseMask
// Terms for 2^(fieldBase*11).
m = (m >> fieldBase) +
uint64(val.n[2])*uint64(val2.n[9]) +
uint64(val.n[3])*uint64(val2.n[8]) +
uint64(val.n[4])*uint64(val2.n[7]) +
uint64(val.n[5])*uint64(val2.n[6]) +
uint64(val.n[6])*uint64(val2.n[5]) +
uint64(val.n[7])*uint64(val2.n[4]) +
uint64(val.n[8])*uint64(val2.n[3]) +
uint64(val.n[9])*uint64(val2.n[2])
t11 := m & fieldBaseMask
// Terms for 2^(fieldBase*12).
m = (m >> fieldBase) +
uint64(val.n[3])*uint64(val2.n[9]) +
uint64(val.n[4])*uint64(val2.n[8]) +
uint64(val.n[5])*uint64(val2.n[7]) +
uint64(val.n[6])*uint64(val2.n[6]) +
uint64(val.n[7])*uint64(val2.n[5]) +
uint64(val.n[8])*uint64(val2.n[4]) +
uint64(val.n[9])*uint64(val2.n[3])
t12 := m & fieldBaseMask
// Terms for 2^(fieldBase*13).
m = (m >> fieldBase) +
uint64(val.n[4])*uint64(val2.n[9]) +
uint64(val.n[5])*uint64(val2.n[8]) +
uint64(val.n[6])*uint64(val2.n[7]) +
uint64(val.n[7])*uint64(val2.n[6]) +
uint64(val.n[8])*uint64(val2.n[5]) +
uint64(val.n[9])*uint64(val2.n[4])
t13 := m & fieldBaseMask
// Terms for 2^(fieldBase*14).
m = (m >> fieldBase) +
uint64(val.n[5])*uint64(val2.n[9]) +
uint64(val.n[6])*uint64(val2.n[8]) +
uint64(val.n[7])*uint64(val2.n[7]) +
uint64(val.n[8])*uint64(val2.n[6]) +
uint64(val.n[9])*uint64(val2.n[5])
t14 := m & fieldBaseMask
// Terms for 2^(fieldBase*15).
m = (m >> fieldBase) +
uint64(val.n[6])*uint64(val2.n[9]) +
uint64(val.n[7])*uint64(val2.n[8]) +
uint64(val.n[8])*uint64(val2.n[7]) +
uint64(val.n[9])*uint64(val2.n[6])
t15 := m & fieldBaseMask
// Terms for 2^(fieldBase*16).
m = (m >> fieldBase) +
uint64(val.n[7])*uint64(val2.n[9]) +
uint64(val.n[8])*uint64(val2.n[8]) +
uint64(val.n[9])*uint64(val2.n[7])
t16 := m & fieldBaseMask
// Terms for 2^(fieldBase*17).
m = (m >> fieldBase) +
uint64(val.n[8])*uint64(val2.n[9]) +
uint64(val.n[9])*uint64(val2.n[8])
t17 := m & fieldBaseMask
// Terms for 2^(fieldBase*18).
m = (m >> fieldBase) + uint64(val.n[9])*uint64(val2.n[9])
t18 := m & fieldBaseMask
// What's left is for 2^(fieldBase*19).
t19 := m >> fieldBase
// At this point, all of the terms are grouped into their respective
// base.
//
// Per [HAC] section 14.3.4: Reduction method of moduli of special form,
// when the modulus is of the special form m = b^t - c, highly efficient
// reduction can be achieved per the provided algorithm.
//
// The secp256k1 prime is equivalent to 2^256 - 4294968273, so it fits
// this criteria.
//
// 4294968273 in field representation (base 2^26) is:
// n[0] = 977
// n[1] = 64
// That is to say (2^26 * 64) + 977 = 4294968273
//
// Since each word is in base 26, the upper terms (t10 and up) start
// at 260 bits (versus the final desired range of 256 bits), so the
// field representation of 'c' from above needs to be adjusted for the
// extra 4 bits by multiplying it by 2^4 = 16. 4294968273 * 16 =
// 68719492368. Thus, the adjusted field representation of 'c' is:
// n[0] = 977 * 16 = 15632
// n[1] = 64 * 16 = 1024
// That is to say (2^26 * 1024) + 15632 = 68719492368
//
// To reduce the final term, t19, the entire 'c' value is needed instead
// of only n[0] because there are no more terms left to handle n[1].
// This means there might be some magnitude left in the upper bits that
// is handled below.
m = t0 + t10*15632
t0 = m & fieldBaseMask
m = (m >> fieldBase) + t1 + t10*1024 + t11*15632
t1 = m & fieldBaseMask
m = (m >> fieldBase) + t2 + t11*1024 + t12*15632
t2 = m & fieldBaseMask
m = (m >> fieldBase) + t3 + t12*1024 + t13*15632
t3 = m & fieldBaseMask
m = (m >> fieldBase) + t4 + t13*1024 + t14*15632
t4 = m & fieldBaseMask
m = (m >> fieldBase) + t5 + t14*1024 + t15*15632
t5 = m & fieldBaseMask
m = (m >> fieldBase) + t6 + t15*1024 + t16*15632
t6 = m & fieldBaseMask
m = (m >> fieldBase) + t7 + t16*1024 + t17*15632
t7 = m & fieldBaseMask
m = (m >> fieldBase) + t8 + t17*1024 + t18*15632
t8 = m & fieldBaseMask
m = (m >> fieldBase) + t9 + t18*1024 + t19*68719492368
t9 = m & fieldMSBMask
m = m >> fieldMSBBits
// At this point, if the magnitude is greater than 0, the overall value
// is greater than the max possible 256-bit value. In particular, it is
// "how many times larger" than the max value it is.
//
// The algorithm presented in [HAC] section 14.3.4 repeats until the
// quotient is zero. However, due to the above, we already know at
// least how many times we would need to repeat as it's the value
// currently in m. Thus we can simply multiply the magnitude by the
// field representation of the prime and do a single iteration. Notice
// that nothing will be changed when the magnitude is zero, so we could
// skip this in that case, however always running regardless allows it
// to run in constant time. The final result will be in the range
// 0 <= result <= prime + (2^64 - c), so it is guaranteed to have a
// magnitude of 1, but it is denormalized.
d := t0 + m*977
f.n[0] = uint32(d & fieldBaseMask)
d = (d >> fieldBase) + t1 + m*64
f.n[1] = uint32(d & fieldBaseMask)
f.n[2] = uint32((d >> fieldBase) + t2)
f.n[3] = uint32(t3)
f.n[4] = uint32(t4)
f.n[5] = uint32(t5)
f.n[6] = uint32(t6)
f.n[7] = uint32(t7)
f.n[8] = uint32(t8)
f.n[9] = uint32(t9)
return f
}
// Square squares the field value. The existing field value is modified. Note
// that this function can overflow if multiplying any of the individual words
// exceeds a max uint32. In practice, this means the magnitude of the field
// must be a max of 8 to prevent overflow.
//
// The field value is returned to support chaining. This enables syntax like:
// f.Square().Mul(f2) so that f = f^2 * f2.
func (f *fieldVal) Square() *fieldVal {
return f.SquareVal(f)
}
// SquareVal squares the passed value and stores the result in f. Note that
// this function can overflow if multiplying any of the individual words
// exceeds a max uint32. In practice, this means the magnitude of the field
// being squred must be a max of 8 to prevent overflow.
//
// The field value is returned to support chaining. This enables syntax like:
// f3.SquareVal(f).Mul(f) so that f3 = f^2 * f = f^3.
func (f *fieldVal) SquareVal(val *fieldVal) *fieldVal {
// This could be done with a couple of for loops and an array to store
// the intermediate terms, but this unrolled version is significantly
// faster.
// Terms for 2^(fieldBase*0).
m := uint64(val.n[0]) * uint64(val.n[0])
t0 := m & fieldBaseMask
// Terms for 2^(fieldBase*1).
m = (m >> fieldBase) + 2*uint64(val.n[0])*uint64(val.n[1])
t1 := m & fieldBaseMask
// Terms for 2^(fieldBase*2).
m = (m >> fieldBase) +
2*uint64(val.n[0])*uint64(val.n[2]) +
uint64(val.n[1])*uint64(val.n[1])
t2 := m & fieldBaseMask
// Terms for 2^(fieldBase*3).
m = (m >> fieldBase) +
2*uint64(val.n[0])*uint64(val.n[3]) +
2*uint64(val.n[1])*uint64(val.n[2])
t3 := m & fieldBaseMask
// Terms for 2^(fieldBase*4).
m = (m >> fieldBase) +
2*uint64(val.n[0])*uint64(val.n[4]) +
2*uint64(val.n[1])*uint64(val.n[3]) +
uint64(val.n[2])*uint64(val.n[2])
t4 := m & fieldBaseMask
// Terms for 2^(fieldBase*5).
m = (m >> fieldBase) +
2*uint64(val.n[0])*uint64(val.n[5]) +
2*uint64(val.n[1])*uint64(val.n[4]) +
2*uint64(val.n[2])*uint64(val.n[3])
t5 := m & fieldBaseMask
// Terms for 2^(fieldBase*6).
m = (m >> fieldBase) +
2*uint64(val.n[0])*uint64(val.n[6]) +
2*uint64(val.n[1])*uint64(val.n[5]) +
2*uint64(val.n[2])*uint64(val.n[4]) +
uint64(val.n[3])*uint64(val.n[3])
t6 := m & fieldBaseMask
// Terms for 2^(fieldBase*7).
m = (m >> fieldBase) +
2*uint64(val.n[0])*uint64(val.n[7]) +
2*uint64(val.n[1])*uint64(val.n[6]) +
2*uint64(val.n[2])*uint64(val.n[5]) +
2*uint64(val.n[3])*uint64(val.n[4])
t7 := m & fieldBaseMask
// Terms for 2^(fieldBase*8).
m = (m >> fieldBase) +
2*uint64(val.n[0])*uint64(val.n[8]) +
2*uint64(val.n[1])*uint64(val.n[7]) +
2*uint64(val.n[2])*uint64(val.n[6]) +
2*uint64(val.n[3])*uint64(val.n[5]) +
uint64(val.n[4])*uint64(val.n[4])
t8 := m & fieldBaseMask
// Terms for 2^(fieldBase*9).
m = (m >> fieldBase) +
2*uint64(val.n[0])*uint64(val.n[9]) +
2*uint64(val.n[1])*uint64(val.n[8]) +
2*uint64(val.n[2])*uint64(val.n[7]) +
2*uint64(val.n[3])*uint64(val.n[6]) +
2*uint64(val.n[4])*uint64(val.n[5])
t9 := m & fieldBaseMask
// Terms for 2^(fieldBase*10).
m = (m >> fieldBase) +
2*uint64(val.n[1])*uint64(val.n[9]) +
2*uint64(val.n[2])*uint64(val.n[8]) +
2*uint64(val.n[3])*uint64(val.n[7]) +
2*uint64(val.n[4])*uint64(val.n[6]) +
uint64(val.n[5])*uint64(val.n[5])
t10 := m & fieldBaseMask
// Terms for 2^(fieldBase*11).
m = (m >> fieldBase) +
2*uint64(val.n[2])*uint64(val.n[9]) +
2*uint64(val.n[3])*uint64(val.n[8]) +
2*uint64(val.n[4])*uint64(val.n[7]) +
2*uint64(val.n[5])*uint64(val.n[6])
t11 := m & fieldBaseMask
// Terms for 2^(fieldBase*12).
m = (m >> fieldBase) +
2*uint64(val.n[3])*uint64(val.n[9]) +
2*uint64(val.n[4])*uint64(val.n[8]) +
2*uint64(val.n[5])*uint64(val.n[7]) +
uint64(val.n[6])*uint64(val.n[6])
t12 := m & fieldBaseMask
// Terms for 2^(fieldBase*13).
m = (m >> fieldBase) +
2*uint64(val.n[4])*uint64(val.n[9]) +
2*uint64(val.n[5])*uint64(val.n[8]) +
2*uint64(val.n[6])*uint64(val.n[7])
t13 := m & fieldBaseMask
// Terms for 2^(fieldBase*14).
m = (m >> fieldBase) +
2*uint64(val.n[5])*uint64(val.n[9]) +
2*uint64(val.n[6])*uint64(val.n[8]) +
uint64(val.n[7])*uint64(val.n[7])
t14 := m & fieldBaseMask
// Terms for 2^(fieldBase*15).
m = (m >> fieldBase) +
2*uint64(val.n[6])*uint64(val.n[9]) +
2*uint64(val.n[7])*uint64(val.n[8])
t15 := m & fieldBaseMask
// Terms for 2^(fieldBase*16).
m = (m >> fieldBase) +
2*uint64(val.n[7])*uint64(val.n[9]) +
uint64(val.n[8])*uint64(val.n[8])
t16 := m & fieldBaseMask
// Terms for 2^(fieldBase*17).
m = (m >> fieldBase) + 2*uint64(val.n[8])*uint64(val.n[9])
t17 := m & fieldBaseMask
// Terms for 2^(fieldBase*18).
m = (m >> fieldBase) + uint64(val.n[9])*uint64(val.n[9])
t18 := m & fieldBaseMask
// What's left is for 2^(fieldBase*19).
t19 := m >> fieldBase
// At this point, all of the terms are grouped into their respective
// base.
//
// Per [HAC] section 14.3.4: Reduction method of moduli of special form,
// when the modulus is of the special form m = b^t - c, highly efficient
// reduction can be achieved per the provided algorithm.
//
// The secp256k1 prime is equivalent to 2^256 - 4294968273, so it fits
// this criteria.
//
// 4294968273 in field representation (base 2^26) is:
// n[0] = 977
// n[1] = 64
// That is to say (2^26 * 64) + 977 = 4294968273
//
// Since each word is in base 26, the upper terms (t10 and up) start
// at 260 bits (versus the final desired range of 256 bits), so the
// field representation of 'c' from above needs to be adjusted for the
// extra 4 bits by multiplying it by 2^4 = 16. 4294968273 * 16 =
// 68719492368. Thus, the adjusted field representation of 'c' is:
// n[0] = 977 * 16 = 15632
// n[1] = 64 * 16 = 1024
// That is to say (2^26 * 1024) + 15632 = 68719492368
//
// To reduce the final term, t19, the entire 'c' value is needed instead
// of only n[0] because there are no more terms left to handle n[1].
// This means there might be some magnitude left in the upper bits that
// is handled below.
m = t0 + t10*15632
t0 = m & fieldBaseMask
m = (m >> fieldBase) + t1 + t10*1024 + t11*15632
t1 = m & fieldBaseMask
m = (m >> fieldBase) + t2 + t11*1024 + t12*15632
t2 = m & fieldBaseMask
m = (m >> fieldBase) + t3 + t12*1024 + t13*15632
t3 = m & fieldBaseMask
m = (m >> fieldBase) + t4 + t13*1024 + t14*15632
t4 = m & fieldBaseMask
m = (m >> fieldBase) + t5 + t14*1024 + t15*15632
t5 = m & fieldBaseMask
m = (m >> fieldBase) + t6 + t15*1024 + t16*15632
t6 = m & fieldBaseMask
m = (m >> fieldBase) + t7 + t16*1024 + t17*15632
t7 = m & fieldBaseMask
m = (m >> fieldBase) + t8 + t17*1024 + t18*15632
t8 = m & fieldBaseMask
m = (m >> fieldBase) + t9 + t18*1024 + t19*68719492368
t9 = m & fieldMSBMask
m = m >> fieldMSBBits
// At this point, if the magnitude is greater than 0, the overall value
// is greater than the max possible 256-bit value. In particular, it is
// "how many times larger" than the max value it is.
//
// The algorithm presented in [HAC] section 14.3.4 repeats until the
// quotient is zero. However, due to the above, we already know at
// least how many times we would need to repeat as it's the value
// currently in m. Thus we can simply multiply the magnitude by the
// field representation of the prime and do a single iteration. Notice
// that nothing will be changed when the magnitude is zero, so we could
// skip this in that case, however always running regardless allows it
// to run in constant time. The final result will be in the range
// 0 <= result <= prime + (2^64 - c), so it is guaranteed to have a
// magnitude of 1, but it is denormalized.
n := t0 + m*977
f.n[0] = uint32(n & fieldBaseMask)
n = (n >> fieldBase) + t1 + m*64
f.n[1] = uint32(n & fieldBaseMask)
f.n[2] = uint32((n >> fieldBase) + t2)
f.n[3] = uint32(t3)
f.n[4] = uint32(t4)
f.n[5] = uint32(t5)
f.n[6] = uint32(t6)
f.n[7] = uint32(t7)
f.n[8] = uint32(t8)
f.n[9] = uint32(t9)
return f
}
// Inverse finds the modular multiplicative inverse of the field value. The
// existing field value is modified.
//
// The field value is returned to support chaining. This enables syntax like:
// f.Inverse().Mul(f2) so that f = f^-1 * f2.
func (f *fieldVal) Inverse() *fieldVal {
// Fermat's little theorem states that for a nonzero number a and prime
// prime p, a^(p-1) = 1 (mod p). Since the multipliciative inverse is
// a*b = 1 (mod p), it follows that b = a*a^(p-2) = a^(p-1) = 1 (mod p).
// Thus, a^(p-2) is the multiplicative inverse.
//
// In order to efficiently compute a^(p-2), p-2 needs to be split into
// a sequence of squares and multipications that minimizes the number of
// multiplications needed (since they are more costly than squarings).
// Intermediate results are saved and reused as well.
//
// The secp256k1 prime - 2 is 2^256 - 4294968275.
//
// This has a cost of 258 field squarings and 33 field multiplications.
var a2, a3, a4, a10, a11, a21, a42, a45, a63, a1019, a1023 fieldVal
a2.SquareVal(f)
a3.Mul2(&a2, f)
a4.SquareVal(&a2)
a10.SquareVal(&a4).Mul(&a2)
a11.Mul2(&a10, f)
a21.Mul2(&a10, &a11)
a42.SquareVal(&a21)
a45.Mul2(&a42, &a3)
a63.Mul2(&a42, &a21)
a1019.SquareVal(&a63).Square().Square().Square().Mul(&a11)
a1023.Mul2(&a1019, &a4)
f.Set(&a63) // f = a^(2^6 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^11 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^16 - 1024)
f.Mul(&a1023) // f = a^(2^16 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^21 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^26 - 1024)
f.Mul(&a1023) // f = a^(2^26 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^31 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^36 - 1024)
f.Mul(&a1023) // f = a^(2^36 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^41 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^46 - 1024)
f.Mul(&a1023) // f = a^(2^46 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^51 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^56 - 1024)
f.Mul(&a1023) // f = a^(2^56 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^61 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^66 - 1024)
f.Mul(&a1023) // f = a^(2^66 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^71 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^76 - 1024)
f.Mul(&a1023) // f = a^(2^76 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^81 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^86 - 1024)
f.Mul(&a1023) // f = a^(2^86 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^91 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^96 - 1024)
f.Mul(&a1023) // f = a^(2^96 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^101 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^106 - 1024)
f.Mul(&a1023) // f = a^(2^106 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^111 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^116 - 1024)
f.Mul(&a1023) // f = a^(2^116 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^121 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^126 - 1024)
f.Mul(&a1023) // f = a^(2^126 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^131 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^136 - 1024)
f.Mul(&a1023) // f = a^(2^136 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^141 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^146 - 1024)
f.Mul(&a1023) // f = a^(2^146 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^151 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^156 - 1024)
f.Mul(&a1023) // f = a^(2^156 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^161 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^166 - 1024)
f.Mul(&a1023) // f = a^(2^166 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^171 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^176 - 1024)
f.Mul(&a1023) // f = a^(2^176 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^181 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^186 - 1024)
f.Mul(&a1023) // f = a^(2^186 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^191 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^196 - 1024)
f.Mul(&a1023) // f = a^(2^196 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^201 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^206 - 1024)
f.Mul(&a1023) // f = a^(2^206 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^211 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^216 - 1024)
f.Mul(&a1023) // f = a^(2^216 - 1)
f.Square().Square().Square().Square().Square() // f = a^(2^221 - 32)
f.Square().Square().Square().Square().Square() // f = a^(2^226 - 1024)
f.Mul(&a1019) // f = a^(2^226 - 5)
f.Square().Square().Square().Square().Square() // f = a^(2^231 - 160)
f.Square().Square().Square().Square().Square() // f = a^(2^236 - 5120)
f.Mul(&a1023) // f = a^(2^236 - 4097)
f.Square().Square().Square().Square().Square() // f = a^(2^241 - 131104)
f.Square().Square().Square().Square().Square() // f = a^(2^246 - 4195328)
f.Mul(&a1023) // f = a^(2^246 - 4194305)
f.Square().Square().Square().Square().Square() // f = a^(2^251 - 134217760)
f.Square().Square().Square().Square().Square() // f = a^(2^256 - 4294968320)
return f.Mul(&a45) // f = a^(2^256 - 4294968275) = a^(p-2)
}
// SqrtVal computes the square root of x modulo the curve's prime, and stores
// the result in f. The square root is computed via exponentiation of x by the
// value Q = (P+1)/4 using the curve's precomputed big-endian representation of
// the Q. This method uses a modified version of square-and-multiply
// exponentiation over secp256k1 fieldVals to operate on bytes instead of bits,
// which offers better performance over both big.Int exponentiation and bit-wise
// square-and-multiply.
//
// NOTE: This method only works when P is intended to be the secp256k1 prime and
// is not constant time. The returned value is of magnitude 1, but is
// denormalized.
func (f *fieldVal) SqrtVal(x *fieldVal) *fieldVal {
// The following computation iteratively computes x^((P+1)/4) = x^Q
// using the recursive, piece-wise definition:
//
// x^n = (x^2)^(n/2) mod P if n is even
// x^n = x(x^2)^(n-1/2) mod P if n is odd
//
// Given n in its big-endian representation b_k, ..., b_0, x^n can be
// computed by defining the sequence r_k+1, ..., r_0, where:
//
// r_k+1 = 1
// r_i = (r_i+1)^2 * x^b_i for i = k, ..., 0
//
// The final value r_0 = x^n.
//
// See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more
// details.
//
// This can be further optimized, by observing that the value of Q in
// secp256k1 has the value:
//
// Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c
//
// We can unroll the typical bit-wise interpretation of the
// exponentiation algorithm above to instead operate on bytes.
// This reduces the number of comparisons by an order of magnitude,
// reducing the overhead of failed branch predictions and additional
// comparisons in this method.
//
// Since there there are only 4 unique bytes of Q, this keeps the jump
// table small without the need to handle all possible 8-bit values.
// Further, we observe that 29 of the 32 bytes are 0xff; making the
// first case handle 0xff therefore optimizes the hot path.
f.SetInt(1)
for _, b := range fieldQBytes {
switch b {
// Most common case, where all 8 bits are set.
case 0xff:
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
// First byte of Q (0x3f), where all but the top two bits are
// set. Note that this case only applies six operations, since
// the highest bit of Q resides in bit six of the first byte. We
// ignore the first two bits, since squaring for these bits will
// result in an invalid result. We forgo squaring f before the
// first multiply, since 1^2 = 1.
case 0x3f:
f.Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
// Byte 28 of Q (0xbf), where only bit 7 is unset.
case 0xbf:
f.Square().Mul(x)
f.Square()
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
// Byte 31 of Q (0x0c), where only bits 3 and 4 are set.
default:
f.Square()
f.Square()
f.Square()
f.Square()
f.Square().Mul(x)
f.Square().Mul(x)
f.Square()
f.Square()
}
}
return f
}
// Sqrt computes the square root of f modulo the curve's prime, and stores the
// result in f. The square root is computed via exponentiation of x by the value
// Q = (P+1)/4 using the curve's precomputed big-endian representation of the Q.
// This method uses a modified version of square-and-multiply exponentiation
// over secp256k1 fieldVals to operate on bytes instead of bits, which offers
// better performance over both big.Int exponentiation and bit-wise
// square-and-multiply.
//
// NOTE: This method only works when P is intended to be the secp256k1 prime and
// is not constant time. The returned value is of magnitude 1, but is
// denormalized.
func (f *fieldVal) Sqrt() *fieldVal {
return f.SqrtVal(f)
}
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2013-2016 Dave Collins
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"crypto/rand"
"encoding/hex"
"fmt"
"reflect"
"testing"
)
// TestSetInt ensures that setting a field value to various native integers
// works as expected.
func TestSetInt(t *testing.T) {
tests := []struct {
in uint
raw [10]uint32
}{
{5, [10]uint32{5, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
// 2^26
{67108864, [10]uint32{67108864, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
// 2^26 + 1
{67108865, [10]uint32{67108865, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
// 2^32 - 1
{4294967295, [10]uint32{4294967295, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetInt(test.in)
if !reflect.DeepEqual(f.n, test.raw) {
t.Errorf("fieldVal.Set #%d wrong result\ngot: %v\n"+
"want: %v", i, f.n, test.raw)
continue
}
}
}
// TestZero ensures that zeroing a field value zero works as expected.
func TestZero(t *testing.T) {
f := new(fieldVal).SetInt(2)
f.Zero()
for idx, rawInt := range f.n {
if rawInt != 0 {
t.Errorf("internal field integer at index #%d is not "+
"zero - got %d", idx, rawInt)
}
}
}
// TestIsZero ensures that checking if a field IsZero works as expected.
func TestIsZero(t *testing.T) {
f := new(fieldVal)
if !f.IsZero() {
t.Errorf("new field value is not zero - got %v (rawints %x)", f,
f.n)
}
f.SetInt(1)
if f.IsZero() {
t.Errorf("field claims it's zero when it's not - got %v "+
"(raw rawints %x)", f, f.n)
}
f.Zero()
if !f.IsZero() {
t.Errorf("field claims it's not zero when it is - got %v "+
"(raw rawints %x)", f, f.n)
}
}
// TestStringer ensures the stringer returns the appropriate hex string.
func TestStringer(t *testing.T) {
tests := []struct {
in string
expected string
}{
{"0", "0000000000000000000000000000000000000000000000000000000000000000"},
{"1", "0000000000000000000000000000000000000000000000000000000000000001"},
{"a", "000000000000000000000000000000000000000000000000000000000000000a"},
{"b", "000000000000000000000000000000000000000000000000000000000000000b"},
{"c", "000000000000000000000000000000000000000000000000000000000000000c"},
{"d", "000000000000000000000000000000000000000000000000000000000000000d"},
{"e", "000000000000000000000000000000000000000000000000000000000000000e"},
{"f", "000000000000000000000000000000000000000000000000000000000000000f"},
{"f0", "00000000000000000000000000000000000000000000000000000000000000f0"},
// 2^26-1
{
"3ffffff",
"0000000000000000000000000000000000000000000000000000000003ffffff",
},
// 2^32-1
{
"ffffffff",
"00000000000000000000000000000000000000000000000000000000ffffffff",
},
// 2^64-1
{
"ffffffffffffffff",
"000000000000000000000000000000000000000000000000ffffffffffffffff",
},
// 2^96-1
{
"ffffffffffffffffffffffff",
"0000000000000000000000000000000000000000ffffffffffffffffffffffff",
},
// 2^128-1
{
"ffffffffffffffffffffffffffffffff",
"00000000000000000000000000000000ffffffffffffffffffffffffffffffff",
},
// 2^160-1
{
"ffffffffffffffffffffffffffffffffffffffff",
"000000000000000000000000ffffffffffffffffffffffffffffffffffffffff",
},
// 2^192-1
{
"ffffffffffffffffffffffffffffffffffffffffffffffff",
"0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff",
},
// 2^224-1
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
},
// 2^256-4294968273 (the btcec prime, so should result in 0)
{
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
"0000000000000000000000000000000000000000000000000000000000000000",
},
// 2^256-4294968274 (the secp256k1 prime+1, so should result in 1)
{
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30",
"0000000000000000000000000000000000000000000000000000000000000001",
},
// Invalid hex
{"g", "0000000000000000000000000000000000000000000000000000000000000000"},
{"1h", "0000000000000000000000000000000000000000000000000000000000000000"},
{"i1", "0000000000000000000000000000000000000000000000000000000000000000"},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in)
result := f.String()
if result != test.expected {
t.Errorf("fieldVal.String #%d wrong result\ngot: %v\n"+
"want: %v", i, result, test.expected)
continue
}
}
}
// TestNormalize ensures that normalizing the internal field words works as
// expected.
func TestNormalize(t *testing.T) {
tests := []struct {
raw [10]uint32 // Intentionally denormalized value
normalized [10]uint32 // Normalized form of the raw value
}{
{
[10]uint32{0x00000005, 0, 0, 0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x00000005, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
// 2^26
{
[10]uint32{0x04000000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x00000000, 0x1, 0, 0, 0, 0, 0, 0, 0, 0},
},
// 2^26 + 1
{
[10]uint32{0x04000001, 0x0, 0, 0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x00000001, 0x1, 0, 0, 0, 0, 0, 0, 0, 0},
},
// 2^32 - 1
{
[10]uint32{0xffffffff, 0x00, 0, 0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x03ffffff, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0},
},
// 2^32
{
[10]uint32{0x04000000, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x00000000, 0x40, 0, 0, 0, 0, 0, 0, 0, 0},
},
// 2^32 + 1
{
[10]uint32{0x04000001, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x00000001, 0x40, 0, 0, 0, 0, 0, 0, 0, 0},
},
// 2^64 - 1
{
[10]uint32{0xffffffff, 0xffffffc0, 0xfc0, 0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x03ffffff, 0x03ffffff, 0xfff, 0, 0, 0, 0, 0, 0, 0},
},
// 2^64
{
[10]uint32{0x04000000, 0x03ffffff, 0x0fff, 0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x00000000, 0x00000000, 0x1000, 0, 0, 0, 0, 0, 0, 0},
},
// 2^64 + 1
{
[10]uint32{0x04000001, 0x03ffffff, 0x0fff, 0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x00000001, 0x00000000, 0x1000, 0, 0, 0, 0, 0, 0, 0},
},
// 2^96 - 1
{
[10]uint32{0xffffffff, 0xffffffc0, 0xffffffc0, 0x3ffc0, 0, 0, 0, 0, 0, 0},
[10]uint32{0x03ffffff, 0x03ffffff, 0x03ffffff, 0x3ffff, 0, 0, 0, 0, 0, 0},
},
// 2^96
{
[10]uint32{0x04000000, 0x03ffffff, 0x03ffffff, 0x3ffff, 0, 0, 0, 0, 0, 0},
[10]uint32{0x00000000, 0x00000000, 0x00000000, 0x40000, 0, 0, 0, 0, 0, 0},
},
// 2^128 - 1
{
[10]uint32{0xffffffff, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffc0, 0, 0, 0, 0, 0},
[10]uint32{0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0xffffff, 0, 0, 0, 0, 0},
},
// 2^128
{
[10]uint32{0x04000000, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x0ffffff, 0, 0, 0, 0, 0},
[10]uint32{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1000000, 0, 0, 0, 0, 0},
},
// 2^256 - 4294968273 (secp256k1 prime)
{
[10]uint32{0xfffffc2f, 0xffffff80, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0},
[10]uint32{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000},
},
// Prime larger than P where both first and second words are larger
// than P's first and second words
{
[10]uint32{0xfffffc30, 0xffffff86, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0},
[10]uint32{0x00000001, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000},
},
// Prime larger than P where only the second word is larger
// than P's second words.
{
[10]uint32{0xfffffc2a, 0xffffff87, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0},
[10]uint32{0x03fffffb, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000},
},
// 2^256 - 1
{
[10]uint32{0xffffffff, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0xffffffc0, 0x3fffc0},
[10]uint32{0x000003d0, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000},
},
// Prime with field representation such that the initial
// reduction does not result in a carry to bit 256.
//
// 2^256 - 4294968273 (secp256k1 prime)
{
[10]uint32{0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff},
[10]uint32{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
},
// Prime larger than P that reduces to a value which is still
// larger than P when it has a magnitude of 1 due to its first
// word and does not result in a carry to bit 256.
//
// 2^256 - 4294968272 (secp256k1 prime + 1)
{
[10]uint32{0x03fffc30, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff},
[10]uint32{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
},
// Prime larger than P that reduces to a value which is still
// larger than P when it has a magnitude of 1 due to its second
// word and does not result in a carry to bit 256.
//
// 2^256 - 4227859409 (secp256k1 prime + 0x4000000)
{
[10]uint32{0x03fffc2f, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff},
[10]uint32{0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
},
// Prime larger than P that reduces to a value which is still
// larger than P when it has a magnitude of 1 due to a carry to
// bit 256, but would not be without the carry. These values
// come from the fact that P is 2^256 - 4294968273 and 977 is
// the low order word in the internal field representation.
//
// 2^256 * 5 - ((4294968273 - (977+1)) * 4)
{
[10]uint32{0x03ffffff, 0x03fffeff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x0013fffff},
[10]uint32{0x00001314, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000000},
},
// Prime larger than P that reduces to a value which is still
// larger than P when it has a magnitude of 1 due to both a
// carry to bit 256 and the first word.
{
[10]uint32{0x03fffc30, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x07ffffff, 0x003fffff},
[10]uint32{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001},
},
// Prime larger than P that reduces to a value which is still
// larger than P when it has a magnitude of 1 due to both a
// carry to bit 256 and the second word.
//
{
[10]uint32{0x03fffc2f, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x3ffffff, 0x07ffffff, 0x003fffff},
[10]uint32{0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000, 0x00000000, 0x00000001},
},
// Prime larger than P that reduces to a value which is still
// larger than P when it has a magnitude of 1 due to a carry to
// bit 256 and the first and second words.
//
{
[10]uint32{0x03fffc30, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x07ffffff, 0x003fffff},
[10]uint32{0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001},
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal)
f.n = test.raw
f.Normalize()
if !reflect.DeepEqual(f.n, test.normalized) {
t.Errorf("fieldVal.Normalize #%d wrong result\n"+
"got: %x\nwant: %x", i, f.n, test.normalized)
continue
}
}
}
// TestIsOdd ensures that checking if a field value IsOdd works as expected.
func TestIsOdd(t *testing.T) {
tests := []struct {
in string // hex encoded value
expected bool // expected oddness
}{
{"0", false},
{"1", true},
{"2", false},
// 2^32 - 1
{"ffffffff", true},
// 2^64 - 2
{"fffffffffffffffe", false},
// secp256k1 prime
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", true},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in)
result := f.IsOdd()
if result != test.expected {
t.Errorf("fieldVal.IsOdd #%d wrong result\n"+
"got: %v\nwant: %v", i, result, test.expected)
continue
}
}
}
// TestEquals ensures that checking two field values for equality via Equals
// works as expected.
func TestEquals(t *testing.T) {
tests := []struct {
in1 string // hex encoded value
in2 string // hex encoded value
expected bool // expected equality
}{
{"0", "0", true},
{"0", "1", false},
{"1", "0", false},
// 2^32 - 1 == 2^32 - 1?
{"ffffffff", "ffffffff", true},
// 2^64 - 1 == 2^64 - 2?
{"ffffffffffffffff", "fffffffffffffffe", false},
// 0 == prime (mod prime)?
{"0", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", true},
// 1 == prime+1 (mod prime)?
{"1", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", true},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in1).Normalize()
f2 := new(fieldVal).SetHex(test.in2).Normalize()
result := f.Equals(f2)
if result != test.expected {
t.Errorf("fieldVal.Equals #%d wrong result\n"+
"got: %v\nwant: %v", i, result, test.expected)
continue
}
}
}
// TestNegate ensures that negating field values via Negate works as expected.
func TestNegate(t *testing.T) {
tests := []struct {
in string // hex encoded value
expected string // expected hex encoded value
}{
// secp256k1 prime (aka 0)
{"0", "0"},
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "0"},
{"0", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"},
// secp256k1 prime-1
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1"},
{"1", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e"},
// secp256k1 prime-2
{"2", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d"},
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", "2"},
// Random sampling
{
"b3d9aac9c5e43910b4385b53c7e78c21d4cd5f8e683c633aed04c233efc2e120",
"4c2655363a1bc6ef4bc7a4ac381873de2b32a07197c39cc512fb3dcb103d1b0f",
},
{
"f8a85984fee5a12a7c8dd08830d83423c937d77c379e4a958e447a25f407733f",
"757a67b011a5ed583722f77cf27cbdc36c82883c861b56a71bb85d90bf888f0",
},
{
"45ee6142a7fda884211e93352ed6cb2807800e419533be723a9548823ece8312",
"ba119ebd5802577bdee16ccad12934d7f87ff1be6acc418dc56ab77cc131791d",
},
{
"53c2a668f07e411a2e473e1c3b6dcb495dec1227af27673761d44afe5b43d22b",
"ac3d59970f81bee5d1b8c1e3c49234b6a213edd850d898c89e2bb500a4bc2a04",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in).Normalize()
expected := new(fieldVal).SetHex(test.expected).Normalize()
result := f.Negate(1).Normalize()
if !result.Equals(expected) {
t.Errorf("fieldVal.Negate #%d wrong result\n"+
"got: %v\nwant: %v", i, result, expected)
continue
}
}
}
// TestAddInt ensures that adding an integer to field values via AddInt works as
// expected.
func TestAddInt(t *testing.T) {
tests := []struct {
in1 string // hex encoded value
in2 uint // unsigned integer to add to the value above
expected string // expected hex encoded value
}{
{"0", 1, "1"},
{"1", 0, "1"},
{"1", 1, "2"},
// secp256k1 prime-1 + 1
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", 1, "0"},
// secp256k1 prime + 1
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 1, "1"},
// Random samples.
{
"ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d6c1",
0x10f,
"ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d7d0",
},
{
"44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41deea9cecf",
0x2cf11d41,
"44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41e1b9aec10",
},
{
"88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f7105122c9c",
0x4829aa2d,
"88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f714d3bd6c9",
},
{
"8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee09a015e2a6",
0xa21265a5,
"8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee0a4228484b",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in1).Normalize()
expected := new(fieldVal).SetHex(test.expected).Normalize()
result := f.AddInt(test.in2).Normalize()
if !result.Equals(expected) {
t.Errorf("fieldVal.AddInt #%d wrong result\n"+
"got: %v\nwant: %v", i, result, expected)
continue
}
}
}
// TestAdd ensures that adding two field values together via Add works as
// expected.
func TestAdd(t *testing.T) {
tests := []struct {
in1 string // first hex encoded value
in2 string // second hex encoded value to add
expected string // expected hex encoded value
}{
{"0", "1", "1"},
{"1", "0", "1"},
{"1", "1", "2"},
// secp256k1 prime-1 + 1
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1", "0"},
// secp256k1 prime + 1
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "1", "1"},
// Random samples.
{
"2b2012f975404e5065b4292fb8bed0a5d315eacf24c74d8b27e73bcc5430edcc",
"2c3cefa4e4753e8aeec6ac4c12d99da4d78accefda3b7885d4c6bab46c86db92",
"575d029e59b58cdb547ad57bcb986e4aaaa0b7beff02c610fcadf680c0b7c95e",
},
{
"8131e8722fe59bb189692b96c9f38de92885730f1dd39ab025daffb94c97f79c",
"ff5454b765f0aab5f0977dcc629becc84cabeb9def48e79c6aadb2622c490fa9",
"80863d2995d646677a00a9632c8f7ab175315ead0d1c824c9088b21c78e10b16",
},
{
"c7c95e93d0892b2b2cdd77e80eb646ea61be7a30ac7e097e9f843af73fad5c22",
"3afe6f91a74dfc1c7f15c34907ee981656c37236d946767dd53ccad9190e437c",
"02c7ce2577d72747abf33b3116a4df00b881ec6785c47ffc74c105d158bba36f",
},
{
"fd1c26f6a23381e5d785ba889494ec059369b888ad8431cd67d8c934b580dbe1",
"a475aa5a31dcca90ef5b53c097d9133d6b7117474b41e7877bb199590fc0489c",
"a191d150d4104c76c6e10e492c6dff42fedacfcff8c61954e38a628ec541284e",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in1).Normalize()
f2 := new(fieldVal).SetHex(test.in2).Normalize()
expected := new(fieldVal).SetHex(test.expected).Normalize()
result := f.Add(f2).Normalize()
if !result.Equals(expected) {
t.Errorf("fieldVal.Add #%d wrong result\n"+
"got: %v\nwant: %v", i, result, expected)
continue
}
}
}
// TestAdd2 ensures that adding two field values together via Add2 works as
// expected.
func TestAdd2(t *testing.T) {
tests := []struct {
in1 string // first hex encoded value
in2 string // second hex encoded value to add
expected string // expected hex encoded value
}{
{"0", "1", "1"},
{"1", "0", "1"},
{"1", "1", "2"},
// secp256k1 prime-1 + 1
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1", "0"},
// secp256k1 prime + 1
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "1", "1"},
// close but over the secp256k1 prime
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000", "f1ffff000", "1ffff3d1"},
// Random samples.
{
"ad82b8d1cc136e23e9fd77fe2c7db1fe5a2ecbfcbde59ab3529758334f862d28",
"4d6a4e95d6d61f4f46b528bebe152d408fd741157a28f415639347a84f6f574b",
"faed0767a2e98d7330b2a0bcea92df3eea060d12380e8ec8b62a9fdb9ef58473",
},
{
"f3f43a2540054a86e1df98547ec1c0e157b193e5350fb4a3c3ea214b228ac5e7",
"25706572592690ea3ddc951a1b48b504a4c83dc253756e1b96d56fdfb3199522",
"19649f97992bdb711fbc2d6e9a0a75e5fc79d1a7888522bf5abf912bd5a45eda",
},
{
"6915bb94eef13ff1bb9b2633d997e13b9b1157c713363cc0e891416d6734f5b8",
"11f90d6ac6fe1c4e8900b1c85fb575c251ec31b9bc34b35ada0aea1c21eded22",
"7b0ec8ffb5ef5c40449bd7fc394d56fdecfd8980cf6af01bc29c2b898922e2da",
},
{
"48b0c9eae622eed9335b747968544eb3e75cb2dc8128388f948aa30f88cabde4",
"0989882b52f85f9d524a3a3061a0e01f46d597839d2ba637320f4b9510c8d2d5",
"523a5216391b4e7685a5aea9c9f52ed32e324a601e53dec6c699eea4999390b9",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in1).Normalize()
f2 := new(fieldVal).SetHex(test.in2).Normalize()
expected := new(fieldVal).SetHex(test.expected).Normalize()
result := f.Add2(f, f2).Normalize()
if !result.Equals(expected) {
t.Errorf("fieldVal.Add2 #%d wrong result\n"+
"got: %v\nwant: %v", i, result, expected)
continue
}
}
}
// TestMulInt ensures that adding an integer to field values via MulInt works as
// expected.
func TestMulInt(t *testing.T) {
tests := []struct {
in1 string // hex encoded value
in2 uint // unsigned integer to multiply with value above
expected string // expected hex encoded value
}{
{"0", 0, "0"},
{"1", 0, "0"},
{"0", 1, "0"},
{"1", 1, "1"},
// secp256k1 prime-1 * 2
{
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e",
2,
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d",
},
// secp256k1 prime * 3
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 3, "0"},
// secp256k1 prime-1 * 8
{
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e",
8,
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27",
},
// Random samples for first value. The second value is limited
// to 8 since that is the maximum int used in the elliptic curve
// calculations.
{
"b75674dc9180d306c692163ac5e089f7cef166af99645c0c23568ab6d967288a",
6,
"4c06bd2b6904f228a76c8560a3433bced9a8681d985a2848d407404d186b0280",
},
{
"54873298ac2b5ba8591c125ae54931f5ea72040aee07b208d6135476fb5b9c0e",
3,
"fd9597ca048212f90b543710afdb95e1bf560c20ca17161a8239fd64f212d42a",
},
{
"7c30fbd363a74c17e1198f56b090b59bbb6c8755a74927a6cba7a54843506401",
5,
"6cf4eb20f2447c77657fccb172d38c0aa91ea4ac446dc641fa463a6b5091fba7",
},
{
"fb4529be3e027a3d1587d8a500b72f2d312e3577340ef5175f96d113be4c2ceb",
8,
"da294df1f013d1e8ac3ec52805b979698971abb9a077a8bafcb688a4f261820f",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in1).Normalize()
expected := new(fieldVal).SetHex(test.expected).Normalize()
result := f.MulInt(test.in2).Normalize()
if !result.Equals(expected) {
t.Errorf("fieldVal.MulInt #%d wrong result\n"+
"got: %v\nwant: %v", i, result, expected)
continue
}
}
}
// TestMul ensures that multiplying two field valuess via Mul works as expected.
func TestMul(t *testing.T) {
tests := []struct {
in1 string // first hex encoded value
in2 string // second hex encoded value to multiply with
expected string // expected hex encoded value
}{
{"0", "0", "0"},
{"1", "0", "0"},
{"0", "1", "0"},
{"1", "1", "1"},
// slightly over prime
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1ffff",
"1000",
"1ffff3d1",
},
// secp256k1 prime-1 * 2
{
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e",
"2",
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d",
},
// secp256k1 prime * 3
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "3", "0"},
// secp256k1 prime-1 * 8
{
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e",
"8",
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27",
},
// Random samples.
{
"cfb81753d5ef499a98ecc04c62cb7768c2e4f1740032946db1c12e405248137e",
"58f355ad27b4d75fb7db0442452e732c436c1f7c5a7c4e214fa9cc031426a7d3",
"1018cd2d7c2535235b71e18db9cd98027386328d2fa6a14b36ec663c4c87282b",
},
{
"26e9d61d1cdf3920e9928e85fa3df3e7556ef9ab1d14ec56d8b4fc8ed37235bf",
"2dfc4bbe537afee979c644f8c97b31e58be5296d6dbc460091eae630c98511cf",
"da85f48da2dc371e223a1ae63bd30b7e7ee45ae9b189ac43ff357e9ef8cf107a",
},
{
"5db64ed5afb71646c8b231585d5b2bf7e628590154e0854c4c29920b999ff351",
"279cfae5eea5d09ade8e6a7409182f9de40981bc31c84c3d3dfe1d933f152e9a",
"2c78fbae91792dd0b157abe3054920049b1879a7cc9d98cfda927d83be411b37",
},
{
"b66dfc1f96820b07d2bdbd559c19319a3a73c97ceb7b3d662f4fe75ecb6819e6",
"bf774aba43e3e49eb63a6e18037d1118152568f1a3ac4ec8b89aeb6ff8008ae1",
"c4f016558ca8e950c21c3f7fc15f640293a979c7b01754ee7f8b3340d4902ebb",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in1).Normalize()
f2 := new(fieldVal).SetHex(test.in2).Normalize()
expected := new(fieldVal).SetHex(test.expected).Normalize()
result := f.Mul(f2).Normalize()
if !result.Equals(expected) {
t.Errorf("fieldVal.Mul #%d wrong result\n"+
"got: %v\nwant: %v", i, result, expected)
continue
}
}
}
// TestSquare ensures that squaring field values via Square works as expected.
func TestSquare(t *testing.T) {
tests := []struct {
in string // hex encoded value
expected string // expected hex encoded value
}{
// secp256k1 prime (aka 0)
{"0", "0"},
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "0"},
{"0", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"},
// secp256k1 prime-1
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1"},
// secp256k1 prime-2
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", "4"},
// Random sampling
{
"b0ba920360ea8436a216128047aab9766d8faf468895eb5090fc8241ec758896",
"133896b0b69fda8ce9f648b9a3af38f345290c9eea3cbd35bafcadf7c34653d3",
},
{
"c55d0d730b1d0285a1599995938b042a756e6e8857d390165ffab480af61cbd5",
"cd81758b3f5877cbe7e5b0a10cebfa73bcbf0957ca6453e63ee8954ab7780bee",
},
{
"e89c1f9a70d93651a1ba4bca5b78658f00de65a66014a25544d3365b0ab82324",
"39ffc7a43e5dbef78fd5d0354fb82c6d34f5a08735e34df29da14665b43aa1f",
},
{
"7dc26186079d22bcbe1614aa20ae627e62d72f9be7ad1e99cac0feb438956f05",
"bf86bcfc4edb3d81f916853adfda80c07c57745b008b60f560b1912f95bce8ae",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in).Normalize()
expected := new(fieldVal).SetHex(test.expected).Normalize()
result := f.Square().Normalize()
if !result.Equals(expected) {
t.Errorf("fieldVal.Square #%d wrong result\n"+
"got: %v\nwant: %v", i, result, expected)
continue
}
}
}
// TestInverse ensures that finding the multiplicative inverse via Inverse works
// as expected.
func TestInverse(t *testing.T) {
tests := []struct {
in string // hex encoded value
expected string // expected hex encoded value
}{
// secp256k1 prime (aka 0)
{"0", "0"},
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "0"},
{"0", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"},
// secp256k1 prime-1
{
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e",
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e",
},
// secp256k1 prime-2
{
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d",
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffe17",
},
// Random sampling
{
"16fb970147a9acc73654d4be233cc48b875ce20a2122d24f073d29bd28805aca",
"987aeb257b063df0c6d1334051c47092b6d8766c4bf10c463786d93f5bc54354",
},
{
"69d1323ce9f1f7b3bd3c7320b0d6311408e30281e273e39a0d8c7ee1c8257919",
"49340981fa9b8d3dad72de470b34f547ed9179c3953797d0943af67806f4bb6",
},
{
"e0debf988ae098ecda07d0b57713e97c6d213db19753e8c95aa12a2fc1cc5272",
"64f58077b68af5b656b413ea366863f7b2819f8d27375d9c4d9804135ca220c2",
},
{
"dcd394f91f74c2ba16aad74a22bb0ed47fe857774b8f2d6c09e28bfb14642878",
"fb848ec64d0be572a63c38fe83df5e7f3d032f60bf8c969ef67d36bf4ada22a9",
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
f := new(fieldVal).SetHex(test.in).Normalize()
expected := new(fieldVal).SetHex(test.expected).Normalize()
result := f.Inverse().Normalize()
if !result.Equals(expected) {
t.Errorf("fieldVal.Inverse #%d wrong result\n"+
"got: %v\nwant: %v", i, result, expected)
continue
}
}
}
// randFieldVal returns a random, normalized element in the field.
func randFieldVal(t *testing.T) fieldVal {
var b [32]byte
if _, err := rand.Read(b[:]); err != nil {
t.Fatalf("unable to create random element: %v", err)
}
var x fieldVal
return *x.SetBytes(&b).Normalize()
}
type sqrtTest struct {
name string
in string
expected string
}
// TestSqrt asserts that a fieldVal properly computes the square root modulo the
// sep256k1 prime.
func TestSqrt(t *testing.T) {
var tests []sqrtTest
// No valid root exists for the negative of a square.
for i := uint(9); i > 0; i-- {
var (
x fieldVal
s fieldVal // x^2 mod p
n fieldVal // -x^2 mod p
)
x.SetInt(i)
s.SquareVal(&x).Normalize()
n.NegateVal(&s, 1).Normalize()
tests = append(tests, sqrtTest{
name: fmt.Sprintf("-%d", i),
in: fmt.Sprintf("%x", *n.Bytes()),
})
}
// A root should exist for true squares.
for i := uint(0); i < 10; i++ {
var (
x fieldVal
s fieldVal // x^2 mod p
)
x.SetInt(i)
s.SquareVal(&x).Normalize()
tests = append(tests, sqrtTest{
name: fmt.Sprintf("%d", i),
in: fmt.Sprintf("%x", *s.Bytes()),
expected: fmt.Sprintf("%x", *x.Bytes()),
})
}
// Compute a non-square element, by negating if it has a root.
ns := randFieldVal(t)
if new(fieldVal).SqrtVal(&ns).Square().Equals(&ns) {
ns.Negate(1).Normalize()
}
// For large random field values, test that:
// 1) its square has a valid root.
// 2) the negative of its square has no root.
// 3) the product of its square with a non-square has no root.
for i := 0; i < 10; i++ {
var (
x fieldVal
s fieldVal // x^2 mod p
n fieldVal // -x^2 mod p
m fieldVal // ns*x^2 mod p
)
x = randFieldVal(t)
s.SquareVal(&x).Normalize()
n.NegateVal(&s, 1).Normalize()
m.Mul2(&s, &ns).Normalize()
// A root should exist for true squares.
tests = append(tests, sqrtTest{
name: fmt.Sprintf("%x", *s.Bytes()),
in: fmt.Sprintf("%x", *s.Bytes()),
expected: fmt.Sprintf("%x", *x.Bytes()),
})
// No valid root exists for the negative of a square.
tests = append(tests, sqrtTest{
name: fmt.Sprintf("-%x", *s.Bytes()),
in: fmt.Sprintf("%x", *n.Bytes()),
})
// No root should be computed for product of a square and
// non-square.
tests = append(tests, sqrtTest{
name: fmt.Sprintf("ns*%x", *s.Bytes()),
in: fmt.Sprintf("%x", *m.Bytes()),
})
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
testSqrt(t, test)
})
}
}
func testSqrt(t *testing.T, test sqrtTest) {
var (
f fieldVal
root fieldVal
rootNeg fieldVal
)
f.SetHex(test.in).Normalize()
// Compute sqrt(f) and its negative.
root.SqrtVal(&f).Normalize()
rootNeg.NegateVal(&root, 1).Normalize()
switch {
// If we expect a square root, verify that either the computed square
// root is +/- the expected value.
case len(test.expected) > 0:
var expected fieldVal
expected.SetHex(test.expected).Normalize()
if !root.Equals(&expected) && !rootNeg.Equals(&expected) {
t.Fatalf("fieldVal.Sqrt incorrect root\n"+
"got: %v\ngot_neg: %v\nwant: %v",
root, rootNeg, expected)
}
// Otherwise, we expect this input not to have a square root.
default:
if root.Square().Equals(&f) || rootNeg.Square().Equals(&f) {
t.Fatalf("fieldVal.Sqrt root should not exist\n"+
"got: %v\ngot_neg: %v", root, rootNeg)
}
}
}
// TestFieldSetBytes ensures that setting a field value to a 256-bit big-endian
// unsigned integer via both the slice and array methods works as expected for
// edge cases. Random cases are tested via the various other tests.
func TestFieldSetBytes(t *testing.T) {
tests := []struct {
name string // test description
in string // hex encoded test value
expected [10]uint32 // expected raw ints
}{{
name: "zero",
in: "00",
expected: [10]uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
}, {
name: "field prime",
in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
expected: [10]uint32{
0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff,
},
}, {
name: "field prime - 1",
in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e",
expected: [10]uint32{
0x03fffc2e, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff,
},
}, {
name: "field prime + 1 (overflow in word zero)",
in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30",
expected: [10]uint32{
0x03fffc30, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff,
},
}, {
name: "field prime first 32 bits",
in: "fffffc2f",
expected: [10]uint32{
0x03fffc2f, 0x00000003f, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
},
}, {
name: "field prime word zero",
in: "03fffc2f",
expected: [10]uint32{
0x03fffc2f, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
},
}, {
name: "field prime first 64 bits",
in: "fffffffefffffc2f",
expected: [10]uint32{
0x03fffc2f, 0x03ffffbf, 0x00000fff, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
},
}, {
name: "field prime word zero and one",
in: "0ffffefffffc2f",
expected: [10]uint32{
0x03fffc2f, 0x03ffffbf, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
},
}, {
name: "field prime first 96 bits",
in: "fffffffffffffffefffffc2f",
expected: [10]uint32{
0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x0003ffff, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
},
}, {
name: "field prime word zero, one, and two",
in: "3ffffffffffefffffc2f",
expected: [10]uint32{
0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
},
}, {
name: "overflow in word one (prime + 1<<26)",
in: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff03fffc2f",
expected: [10]uint32{
0x03fffc2f, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff,
},
}, {
name: "(field prime - 1) * 2 NOT mod P, truncated >32 bytes",
in: "01fffffffffffffffffffffffffffffffffffffffffffffffffffffffdfffff85c",
expected: [10]uint32{
0x01fffff8, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x00007fff,
},
}, {
name: "2^256 - 1",
in: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
expected: [10]uint32{
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff,
},
}, {
name: "alternating bits",
in: "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5",
expected: [10]uint32{
0x01a5a5a5, 0x01696969, 0x025a5a5a, 0x02969696, 0x01a5a5a5,
0x01696969, 0x025a5a5a, 0x02969696, 0x01a5a5a5, 0x00296969,
},
}, {
name: "alternating bits 2",
in: "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a",
expected: [10]uint32{
0x025a5a5a, 0x02969696, 0x01a5a5a5, 0x01696969, 0x025a5a5a,
0x02969696, 0x01a5a5a5, 0x01696969, 0x025a5a5a, 0x00169696,
},
}}
for _, test := range tests {
inBytes := hexToBytes(test.in)
// Ensure setting the bytes via the slice method works as expected.
var f fieldVal
f.SetByteSlice(inBytes)
if !reflect.DeepEqual(f.n, test.expected) {
t.Errorf("%s: unexpected result\ngot: %x\nwant: %x", test.name, f.n,
test.expected)
continue
}
// Ensure setting the bytes via the array method works as expected.
var f2 fieldVal
var b32 [32]byte
truncatedInBytes := inBytes
if len(truncatedInBytes) > 32 {
truncatedInBytes = truncatedInBytes[:32]
}
copy(b32[32-len(truncatedInBytes):], truncatedInBytes)
f2.SetBytes(&b32)
if !reflect.DeepEqual(f2.n, test.expected) {
t.Errorf("%s: unexpected result\ngot: %x\nwant: %x", test.name,
f2.n, test.expected)
continue
}
}
}
// hexToBytes converts the passed hex string into bytes and will panic if there
// is an error. This is only provided for the hard-coded constants so errors in
// the source code can be detected. It will only (and must only) be called with
// hard-coded values.
func hexToBytes(s string) []byte {
b, err := hex.DecodeString(s)
if err != nil {
panic("invalid hex in source file: " + s)
}
return b
}
// Copyright 2015 The btcsuite developers
// 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.
// It is called by go generate and used to automatically generate pre-computed
// tables used to accelerate operations.
//go:build ignore
// +build ignore
package main
import (
"bytes"
"compress/zlib"
"encoding/base64"
"fmt"
"log"
"os"
"github.com/ethereum/go-ethereum/crypto/btcec"
)
func main() {
fi, err := os.Create("secp256k1.go")
if err != nil {
log.Fatal(err)
}
defer fi.Close()
// Compress the serialized byte points.
serialized := btcec.S256().SerializedBytePoints()
var compressed bytes.Buffer
w := zlib.NewWriter(&compressed)
if _, err := w.Write(serialized); err != nil {
fmt.Println(err)
os.Exit(1)
}
w.Close()
// Encode the compressed byte points with base64.
encoded := make([]byte, base64.StdEncoding.EncodedLen(compressed.Len()))
base64.StdEncoding.Encode(encoded, compressed.Bytes())
fmt.Fprintln(fi, "// Copyright (c) 2015 The btcsuite developers")
fmt.Fprintln(fi, "// Use of this source code is governed by an ISC")
fmt.Fprintln(fi, "// license that can be found in the LICENSE file.")
fmt.Fprintln(fi)
fmt.Fprintln(fi, "package btcec")
fmt.Fprintln(fi)
fmt.Fprintln(fi, "// Auto-generated file (see genprecomps.go)")
fmt.Fprintln(fi, "// DO NOT EDIT")
fmt.Fprintln(fi)
fmt.Fprintf(fi, "var secp256k1BytePoints = %q\n", string(encoded))
a1, b1, a2, b2 := btcec.S256().EndomorphismVectors()
fmt.Println("The following values are the computed linearly " +
"independent vectors needed to make use of the secp256k1 " +
"endomorphism:")
fmt.Printf("a1: %x\n", a1)
fmt.Printf("b1: %x\n", b1)
fmt.Printf("a2: %x\n", a2)
fmt.Printf("b2: %x\n", b2)
}
// Copyright (c) 2014-2015 The btcsuite developers
// 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
// References:
// [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone)
import (
"encoding/binary"
"math/big"
)
// secp256k1BytePoints are dummy points used so the code which generates the
// real values can compile.
var secp256k1BytePoints = ""
// 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 < curve.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
}
// sqrt returns the square root of the provided big integer using Newton's
// method. It's only compiled and used during generation of pre-computed
// values, so speed is not a huge concern.
func sqrt(n *big.Int) *big.Int {
// Initial guess = 2^(log_2(n)/2)
guess := big.NewInt(2)
guess.Exp(guess, big.NewInt(int64(n.BitLen()/2)), nil)
// Now refine using Newton's method.
big2 := big.NewInt(2)
prevGuess := big.NewInt(0)
for {
prevGuess.Set(guess)
guess.Add(guess, new(big.Int).Div(n, guess))
guess.Div(guess, big2)
if guess.Cmp(prevGuess) == 0 {
break
}
}
return guess
}
// EndomorphismVectors runs the first 3 steps of algorithm 3.74 from [GECC] to
// generate the linearly independent vectors needed to generate a balanced
// length-two representation of a multiplier such that k = k1 + k2λ (mod N) and
// returns them. Since the values will always be the same given the fact that N
// and λ are fixed, the final results can be accelerated by storing the
// precomputed values with the curve.
func (curve *KoblitzCurve) EndomorphismVectors() (a1, b1, a2, b2 *big.Int) {
bigMinus1 := big.NewInt(-1)
// This section uses an extended Euclidean algorithm to generate a
// sequence of equations:
// s[i] * N + t[i] * λ = r[i]
nSqrt := sqrt(curve.N)
u, v := new(big.Int).Set(curve.N), new(big.Int).Set(curve.lambda)
x1, y1 := big.NewInt(1), big.NewInt(0)
x2, y2 := big.NewInt(0), big.NewInt(1)
q, r := new(big.Int), new(big.Int)
qu, qx1, qy1 := new(big.Int), new(big.Int), new(big.Int)
s, t := new(big.Int), new(big.Int)
ri, ti := new(big.Int), new(big.Int)
a1, b1, a2, b2 = new(big.Int), new(big.Int), new(big.Int), new(big.Int)
found, oneMore := false, false
for u.Sign() != 0 {
// q = v/u
q.Div(v, u)
// r = v - q*u
qu.Mul(q, u)
r.Sub(v, qu)
// s = x2 - q*x1
qx1.Mul(q, x1)
s.Sub(x2, qx1)
// t = y2 - q*y1
qy1.Mul(q, y1)
t.Sub(y2, qy1)
// v = u, u = r, x2 = x1, x1 = s, y2 = y1, y1 = t
v.Set(u)
u.Set(r)
x2.Set(x1)
x1.Set(s)
y2.Set(y1)
y1.Set(t)
// As soon as the remainder is less than the sqrt of n, the
// values of a1 and b1 are known.
if !found && r.Cmp(nSqrt) < 0 {
// When this condition executes ri and ti represent the
// r[i] and t[i] values such that i is the greatest
// index for which r >= sqrt(n). Meanwhile, the current
// r and t values are r[i+1] and t[i+1], respectively.
// a1 = r[i+1], b1 = -t[i+1]
a1.Set(r)
b1.Mul(t, bigMinus1)
found = true
oneMore = true
// Skip to the next iteration so ri and ti are not
// modified.
continue
} else if oneMore {
// When this condition executes ri and ti still
// represent the r[i] and t[i] values while the current
// r and t are r[i+2] and t[i+2], respectively.
// sum1 = r[i]^2 + t[i]^2
rSquared := new(big.Int).Mul(ri, ri)
tSquared := new(big.Int).Mul(ti, ti)
sum1 := new(big.Int).Add(rSquared, tSquared)
// sum2 = r[i+2]^2 + t[i+2]^2
r2Squared := new(big.Int).Mul(r, r)
t2Squared := new(big.Int).Mul(t, t)
sum2 := new(big.Int).Add(r2Squared, t2Squared)
// if (r[i]^2 + t[i]^2) <= (r[i+2]^2 + t[i+2]^2)
if sum1.Cmp(sum2) <= 0 {
// a2 = r[i], b2 = -t[i]
a2.Set(ri)
b2.Mul(ti, bigMinus1)
} else {
// a2 = r[i+2], b2 = -t[i+2]
a2.Set(r)
b2.Mul(t, bigMinus1)
}
// All done.
break
}
ri.Set(r)
ti.Set(t)
}
return a1, b1, a2, b2
}
// Copyright 2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"compress/zlib"
"encoding/base64"
"encoding/binary"
"io/ioutil"
"strings"
)
//go:generate go run -tags gensecp256k1 genprecomps.go
// loadS256BytePoints decompresses and deserializes the pre-computed byte points
// used to accelerate scalar base multiplication for the secp256k1 curve. This
// approach is used since it allows the compile to use significantly less ram
// and be performed much faster than it is with hard-coding the final in-memory
// data structure. At the same time, it is quite fast to generate the in-memory
// data structure at init time with this approach versus computing the table.
func loadS256BytePoints() error {
// There will be no byte points to load when generating them.
bp := secp256k1BytePoints
if len(bp) == 0 {
return nil
}
// Decompress the pre-computed table used to accelerate scalar base
// multiplication.
decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(bp))
r, err := zlib.NewReader(decoder)
if err != nil {
return err
}
serialized, err := ioutil.ReadAll(r)
if err != nil {
return err
}
// Deserialize the precomputed byte points and set the curve to them.
offset := 0
var bytePoints [32][256][3]fieldVal
for byteNum := 0; byteNum < 32; byteNum++ {
// All points in this window.
for i := 0; i < 256; i++ {
px := &bytePoints[byteNum][i][0]
py := &bytePoints[byteNum][i][1]
pz := &bytePoints[byteNum][i][2]
for i := 0; i < 10; i++ {
px.n[i] = binary.LittleEndian.Uint32(serialized[offset:])
offset += 4
}
for i := 0; i < 10; i++ {
py.n[i] = binary.LittleEndian.Uint32(serialized[offset:])
offset += 4
}
for i := 0; i < 10; i++ {
pz.n[i] = binary.LittleEndian.Uint32(serialized[offset:])
offset += 4
}
}
}
secp256k1.bytePoints = &bytePoints
return nil
}
// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"math/big"
)
// PrivateKey wraps an ecdsa.PrivateKey as a convenience mainly for signing
// things with the the private key without having to directly import the ecdsa
// package.
type PrivateKey ecdsa.PrivateKey
// PrivKeyFromBytes returns a private and public key for `curve' based on the
// private key passed as an argument as a byte slice.
func PrivKeyFromBytes(curve elliptic.Curve, pk []byte) (*PrivateKey,
*PublicKey) {
x, y := curve.ScalarBaseMult(pk)
priv := &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: curve,
X: x,
Y: y,
},
D: new(big.Int).SetBytes(pk),
}
return (*PrivateKey)(priv), (*PublicKey)(&priv.PublicKey)
}
// NewPrivateKey is a wrapper for ecdsa.GenerateKey that returns a PrivateKey
// instead of the normal ecdsa.PrivateKey.
func NewPrivateKey(curve elliptic.Curve) (*PrivateKey, error) {
key, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return nil, err
}
return (*PrivateKey)(key), nil
}
// PubKey returns the PublicKey corresponding to this private key.
func (p *PrivateKey) PubKey() *PublicKey {
return (*PublicKey)(&p.PublicKey)
}
// ToECDSA returns the private key as a *ecdsa.PrivateKey.
func (p *PrivateKey) ToECDSA() *ecdsa.PrivateKey {
return (*ecdsa.PrivateKey)(p)
}
// Sign generates an ECDSA signature for the provided hash (which should be the result
// of hashing a larger message) using the private key. Produced signature
// is deterministic (same message and same key yield the same signature) and canonical
// in accordance with RFC6979 and BIP0062.
func (p *PrivateKey) Sign(hash []byte) (*Signature, error) {
return signRFC6979(p, hash)
}
// PrivKeyBytesLen defines the length in bytes of a serialized private key.
const PrivKeyBytesLen = 32
// Serialize returns the private key number d as a big-endian binary-encoded
// number, padded to a length of 32 bytes.
func (p *PrivateKey) Serialize() []byte {
b := make([]byte, 0, PrivKeyBytesLen)
return paddedAppend(PrivKeyBytesLen, b, p.ToECDSA().D.Bytes())
}
// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"bytes"
"testing"
)
func TestPrivKeys(t *testing.T) {
tests := []struct {
name string
key []byte
}{
{
name: "check curve",
key: []byte{
0xea, 0xf0, 0x2c, 0xa3, 0x48, 0xc5, 0x24, 0xe6,
0x39, 0x26, 0x55, 0xba, 0x4d, 0x29, 0x60, 0x3c,
0xd1, 0xa7, 0x34, 0x7d, 0x9d, 0x65, 0xcf, 0xe9,
0x3c, 0xe1, 0xeb, 0xff, 0xdc, 0xa2, 0x26, 0x94,
},
},
}
for _, test := range tests {
priv, pub := PrivKeyFromBytes(S256(), test.key)
_, err := ParsePubKey(pub.SerializeUncompressed(), S256())
if err != nil {
t.Errorf("%s privkey: %v", test.name, err)
continue
}
hash := []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9}
sig, err := priv.Sign(hash)
if err != nil {
t.Errorf("%s could not sign: %v", test.name, err)
continue
}
if !sig.Verify(hash, pub) {
t.Errorf("%s could not verify: %v", test.name, err)
continue
}
serializedKey := priv.Serialize()
if !bytes.Equal(serializedKey, test.key) {
t.Errorf("%s unexpected serialized bytes - got: %x, "+
"want: %x", test.name, serializedKey, test.key)
}
}
}
// Copyright (c) 2013-2014 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
)
// These constants define the lengths of serialized public keys.
const (
PubKeyBytesLenCompressed = 33
PubKeyBytesLenUncompressed = 65
PubKeyBytesLenHybrid = 65
)
func isOdd(a *big.Int) bool {
return a.Bit(0) == 1
}
// decompressPoint decompresses a point on the secp256k1 curve given the X point and
// the solution to use.
func decompressPoint(curve *KoblitzCurve, bigX *big.Int, ybit bool) (*big.Int, error) {
var x fieldVal
x.SetByteSlice(bigX.Bytes())
// Compute x^3 + B mod p.
var x3 fieldVal
x3.SquareVal(&x).Mul(&x)
x3.Add(curve.fieldB).Normalize()
// Now calculate sqrt mod p of x^3 + B
// This code used to do a full sqrt based on tonelli/shanks,
// but this was replaced by the algorithms referenced in
// https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294
var y fieldVal
y.SqrtVal(&x3).Normalize()
if ybit != y.IsOdd() {
y.Negate(1).Normalize()
}
// Check that y is a square root of x^3 + B.
var y2 fieldVal
y2.SquareVal(&y).Normalize()
if !y2.Equals(&x3) {
return nil, fmt.Errorf("invalid square root")
}
// Verify that y-coord has expected parity.
if ybit != y.IsOdd() {
return nil, fmt.Errorf("ybit doesn't match oddness")
}
return new(big.Int).SetBytes(y.Bytes()[:]), nil
}
const (
pubkeyCompressed byte = 0x2 // y_bit + x coord
pubkeyUncompressed byte = 0x4 // x coord + y coord
pubkeyHybrid byte = 0x6 // y_bit + x coord + y coord
)
// IsCompressedPubKey returns true the the passed serialized public key has
// been encoded in compressed format, and false otherwise.
func IsCompressedPubKey(pubKey []byte) bool {
// The public key is only compressed if it is the correct length and
// the format (first byte) is one of the compressed pubkey values.
return len(pubKey) == PubKeyBytesLenCompressed &&
(pubKey[0]&^byte(0x1) == pubkeyCompressed)
}
// ParsePubKey parses a public key for a koblitz curve from a bytestring into a
// ecdsa.Publickey, verifying that it is valid. It supports compressed,
// uncompressed and hybrid signature formats.
func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *PublicKey, err error) {
pubkey := PublicKey{}
pubkey.Curve = curve
if len(pubKeyStr) == 0 {
return nil, errors.New("pubkey string is empty")
}
format := pubKeyStr[0]
ybit := (format & 0x1) == 0x1
format &= ^byte(0x1)
switch len(pubKeyStr) {
case PubKeyBytesLenUncompressed:
if format != pubkeyUncompressed && format != pubkeyHybrid {
return nil, fmt.Errorf("invalid magic in pubkey str: "+
"%d", pubKeyStr[0])
}
pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33])
pubkey.Y = new(big.Int).SetBytes(pubKeyStr[33:])
// hybrid keys have extra information, make use of it.
if format == pubkeyHybrid && ybit != isOdd(pubkey.Y) {
return nil, fmt.Errorf("ybit doesn't match oddness")
}
if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 {
return nil, fmt.Errorf("pubkey X parameter is >= to P")
}
if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 {
return nil, fmt.Errorf("pubkey Y parameter is >= to P")
}
if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) {
return nil, fmt.Errorf("pubkey isn't on secp256k1 curve")
}
case PubKeyBytesLenCompressed:
// format is 0x2 | solution, <X coordinate>
// solution determines which solution of the curve we use.
/// y^2 = x^3 + Curve.B
if format != pubkeyCompressed {
return nil, fmt.Errorf("invalid magic in compressed "+
"pubkey string: %d", pubKeyStr[0])
}
pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33])
pubkey.Y, err = decompressPoint(curve, pubkey.X, ybit)
if err != nil {
return nil, err
}
default: // wrong!
return nil, fmt.Errorf("invalid pub key length %d",
len(pubKeyStr))
}
return &pubkey, nil
}
// PublicKey is an ecdsa.PublicKey with additional functions to
// serialize in uncompressed, compressed, and hybrid formats.
type PublicKey ecdsa.PublicKey
// ToECDSA returns the public key as a *ecdsa.PublicKey.
func (p *PublicKey) ToECDSA() *ecdsa.PublicKey {
return (*ecdsa.PublicKey)(p)
}
// SerializeUncompressed serializes a public key in a 65-byte uncompressed
// format.
func (p *PublicKey) SerializeUncompressed() []byte {
b := make([]byte, 0, PubKeyBytesLenUncompressed)
b = append(b, pubkeyUncompressed)
b = paddedAppend(32, b, p.X.Bytes())
return paddedAppend(32, b, p.Y.Bytes())
}
// SerializeCompressed serializes a public key in a 33-byte compressed format.
func (p *PublicKey) SerializeCompressed() []byte {
b := make([]byte, 0, PubKeyBytesLenCompressed)
format := pubkeyCompressed
if isOdd(p.Y) {
format |= 0x1
}
b = append(b, format)
return paddedAppend(32, b, p.X.Bytes())
}
// SerializeHybrid serializes a public key in a 65-byte hybrid format.
func (p *PublicKey) SerializeHybrid() []byte {
b := make([]byte, 0, PubKeyBytesLenHybrid)
format := pubkeyHybrid
if isOdd(p.Y) {
format |= 0x1
}
b = append(b, format)
b = paddedAppend(32, b, p.X.Bytes())
return paddedAppend(32, b, p.Y.Bytes())
}
// IsEqual compares this PublicKey instance to the one passed, returning true if
// both PublicKeys are equivalent. A PublicKey is equivalent to another, if they
// both have the same X and Y coordinate.
func (p *PublicKey) IsEqual(otherPubKey *PublicKey) bool {
return p.X.Cmp(otherPubKey.X) == 0 &&
p.Y.Cmp(otherPubKey.Y) == 0
}
// paddedAppend appends the src byte slice to dst, returning the new slice.
// If the length of the source is smaller than the passed size, leading zero
// bytes are appended to the dst slice before appending src.
func paddedAppend(size uint, dst, src []byte) []byte {
for i := 0; i < int(size)-len(src); i++ {
dst = append(dst, 0)
}
return append(dst, src...)
}
// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"bytes"
"testing"
"github.com/davecgh/go-spew/spew"
)
type pubKeyTest struct {
name string
key []byte
format byte
isValid bool
}
var pubKeyTests = []pubKeyTest{
// pubkey from bitcoin blockchain tx
// 0437cd7f8525ceed2324359c2d0ba26006d92d85
{
name: "uncompressed ok",
key: []byte{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
0xb4, 0x12, 0xa3,
},
isValid: true,
format: pubkeyUncompressed,
},
{
name: "uncompressed x changed",
key: []byte{0x04, 0x15, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
0xb4, 0x12, 0xa3,
},
isValid: false,
},
{
name: "uncompressed y changed",
key: []byte{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
0xb4, 0x12, 0xa4,
},
isValid: false,
},
{
name: "uncompressed claims compressed",
key: []byte{0x03, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
0xb4, 0x12, 0xa3,
},
isValid: false,
},
{
name: "uncompressed as hybrid ok",
key: []byte{0x07, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
0xb4, 0x12, 0xa3,
},
isValid: true,
format: pubkeyHybrid,
},
{
name: "uncompressed as hybrid wrong",
key: []byte{0x06, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
0xb4, 0x12, 0xa3,
},
isValid: false,
},
// from tx 0b09c51c51ff762f00fb26217269d2a18e77a4fa87d69b3c363ab4df16543f20
{
name: "compressed ok (ybit = 0)",
key: []byte{0x02, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b,
0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1,
0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21,
0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d,
},
isValid: true,
format: pubkeyCompressed,
},
// from tx fdeb8e72524e8dab0da507ddbaf5f88fe4a933eb10a66bc4745bb0aa11ea393c
{
name: "compressed ok (ybit = 1)",
key: []byte{0x03, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33,
0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34,
0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4,
0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e,
},
isValid: true,
format: pubkeyCompressed,
},
{
name: "compressed claims uncompressed (ybit = 0)",
key: []byte{0x04, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b,
0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1,
0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21,
0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d,
},
isValid: false,
},
{
name: "compressed claims uncompressed (ybit = 1)",
key: []byte{0x05, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33,
0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34,
0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4,
0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e,
},
isValid: false,
},
{
name: "wrong length)",
key: []byte{0x05},
isValid: false,
},
{
name: "X == P",
key: []byte{0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F, 0xb2, 0xe0,
0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
0xb4, 0x12, 0xa3,
},
isValid: false,
},
{
name: "X > P",
key: []byte{0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFD, 0x2F, 0xb2, 0xe0,
0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
0xb4, 0x12, 0xa3,
},
isValid: false,
},
{
name: "Y == P",
key: []byte{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF,
0xFF, 0xFC, 0x2F,
},
isValid: false,
},
{
name: "Y > P",
key: []byte{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF,
0xFF, 0xFD, 0x2F,
},
isValid: false,
},
{
name: "hybrid",
key: []byte{0x06, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb,
0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59,
0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a,
0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb,
0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48,
0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb,
0x10, 0xd4, 0xb8,
},
format: pubkeyHybrid,
isValid: true,
},
}
func TestPubKeys(t *testing.T) {
for _, test := range pubKeyTests {
pk, err := ParsePubKey(test.key, S256())
if err != nil {
if test.isValid {
t.Errorf("%s pubkey failed when shouldn't %v",
test.name, err)
}
continue
}
if !test.isValid {
t.Errorf("%s counted as valid when it should fail",
test.name)
continue
}
var pkStr []byte
switch test.format {
case pubkeyUncompressed:
pkStr = pk.SerializeUncompressed()
case pubkeyCompressed:
pkStr = pk.SerializeCompressed()
case pubkeyHybrid:
pkStr = pk.SerializeHybrid()
}
if !bytes.Equal(test.key, pkStr) {
t.Errorf("%s pubkey: serialized keys do not match.",
test.name)
spew.Dump(test.key)
spew.Dump(pkStr)
}
}
}
func TestPublicKeyIsEqual(t *testing.T) {
pubKey1, err := ParsePubKey(
[]byte{0x03, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33,
0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34,
0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4,
0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e,
},
S256(),
)
if err != nil {
t.Fatalf("failed to parse raw bytes for pubKey1: %v", err)
}
pubKey2, err := ParsePubKey(
[]byte{0x02, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b,
0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1,
0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21,
0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d,
},
S256(),
)
if err != nil {
t.Fatalf("failed to parse raw bytes for pubKey2: %v", err)
}
if !pubKey1.IsEqual(pubKey1) {
t.Fatalf("value of IsEqual is incorrect, %v is "+
"equal to %v", pubKey1, pubKey1)
}
if pubKey1.IsEqual(pubKey2) {
t.Fatalf("value of IsEqual is incorrect, %v is not "+
"equal to %v", pubKey1, pubKey2)
}
}
func TestIsCompressed(t *testing.T) {
for _, test := range pubKeyTests {
isCompressed := IsCompressedPubKey(test.key)
wantCompressed := (test.format == pubkeyCompressed)
if isCompressed != wantCompressed {
t.Fatalf("%s (%x) pubkey: unexpected compressed result, "+
"got %v, want %v", test.name, test.key,
isCompressed, wantCompressed)
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
// Copyright (c) 2013-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/hmac"
"crypto/sha256"
"errors"
"fmt"
"hash"
"math/big"
)
// Errors returned by canonicalPadding.
var (
errNegativeValue = errors.New("value may be interpreted as negative")
errExcessivelyPaddedValue = errors.New("value is excessively padded")
)
// Signature is a type representing an ecdsa signature.
type Signature struct {
R *big.Int
S *big.Int
}
var (
// Used in RFC6979 implementation when testing the nonce for correctness
one = big.NewInt(1)
// oneInitializer is used to fill a byte slice with byte 0x01. It is provided
// here to avoid the need to create it multiple times.
oneInitializer = []byte{0x01}
)
// Serialize returns the ECDSA signature in the more strict DER format. Note
// that the serialized bytes returned do not include the appended hash type
// used in Bitcoin signature scripts.
//
// encoding/asn1 is broken so we hand roll this output:
//
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
func (sig *Signature) Serialize() []byte {
// low 'S' malleability breaker
sigS := sig.S
if sigS.Cmp(S256().halfOrder) == 1 {
sigS = new(big.Int).Sub(S256().N, sigS)
}
// Ensure the encoded bytes for the r and s values are canonical and
// thus suitable for DER encoding.
rb := canonicalizeInt(sig.R)
sb := canonicalizeInt(sigS)
// total length of returned signature is 1 byte for each magic and
// length (6 total), plus lengths of r and s
length := 6 + len(rb) + len(sb)
b := make([]byte, length)
b[0] = 0x30
b[1] = byte(length - 2)
b[2] = 0x02
b[3] = byte(len(rb))
offset := copy(b[4:], rb) + 4
b[offset] = 0x02
b[offset+1] = byte(len(sb))
copy(b[offset+2:], sb)
return b
}
// Verify calls ecdsa.Verify to verify the signature of hash using the public
// key. It returns true if the signature is valid, false otherwise.
func (sig *Signature) Verify(hash []byte, pubKey *PublicKey) bool {
return ecdsa.Verify(pubKey.ToECDSA(), hash, sig.R, sig.S)
}
// IsEqual compares this Signature instance to the one passed, returning true
// if both Signatures are equivalent. A signature is equivalent to another, if
// they both have the same scalar value for R and S.
func (sig *Signature) IsEqual(otherSig *Signature) bool {
return sig.R.Cmp(otherSig.R) == 0 &&
sig.S.Cmp(otherSig.S) == 0
}
// MinSigLen is the minimum length of a DER encoded signature and is when both R
// and S are 1 byte each.
// 0x30 + <1-byte> + 0x02 + 0x01 + <byte> + 0x2 + 0x01 + <byte>
const MinSigLen = 8
func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) {
// Originally this code used encoding/asn1 in order to parse the
// signature, but a number of problems were found with this approach.
// Despite the fact that signatures are stored as DER, the difference
// between go's idea of a bignum (and that they have sign) doesn't agree
// with the openssl one (where they do not). The above is true as of
// Go 1.1. In the end it was simpler to rewrite the code to explicitly
// understand the format which is this:
// 0x30 <length of whole message> <0x02> <length of R> <R> 0x2
// <length of S> <S>.
signature := &Signature{}
if len(sigStr) < MinSigLen {
return nil, errors.New("malformed signature: too short")
}
// 0x30
index := 0
if sigStr[index] != 0x30 {
return nil, errors.New("malformed signature: no header magic")
}
index++
// length of remaining message
siglen := sigStr[index]
index++
// siglen should be less than the entire message and greater than
// the minimal message size.
if int(siglen+2) > len(sigStr) || int(siglen+2) < MinSigLen {
return nil, errors.New("malformed signature: bad length")
}
// trim the slice we're working on so we only look at what matters.
sigStr = sigStr[:siglen+2]
// 0x02
if sigStr[index] != 0x02 {
return nil,
errors.New("malformed signature: no 1st int marker")
}
index++
// Length of signature R.
rLen := int(sigStr[index])
// must be positive, must be able to fit in another 0x2, <len> <s>
// hence the -3. We assume that the length must be at least one byte.
index++
if rLen <= 0 || rLen > len(sigStr)-index-3 {
return nil, errors.New("malformed signature: bogus R length")
}
// Then R itself.
rBytes := sigStr[index : index+rLen]
if der {
switch err := canonicalPadding(rBytes); err {
case errNegativeValue:
return nil, errors.New("signature R is negative")
case errExcessivelyPaddedValue:
return nil, errors.New("signature R is excessively padded")
}
}
signature.R = new(big.Int).SetBytes(rBytes)
index += rLen
// 0x02. length already checked in previous if.
if sigStr[index] != 0x02 {
return nil, errors.New("malformed signature: no 2nd int marker")
}
index++
// Length of signature S.
sLen := int(sigStr[index])
index++
// S should be the rest of the string.
if sLen <= 0 || sLen > len(sigStr)-index {
return nil, errors.New("malformed signature: bogus S length")
}
// Then S itself.
sBytes := sigStr[index : index+sLen]
if der {
switch err := canonicalPadding(sBytes); err {
case errNegativeValue:
return nil, errors.New("signature S is negative")
case errExcessivelyPaddedValue:
return nil, errors.New("signature S is excessively padded")
}
}
signature.S = new(big.Int).SetBytes(sBytes)
index += sLen
// sanity check length parsing
if index != len(sigStr) {
return nil, fmt.Errorf("malformed signature: bad final length %v != %v",
index, len(sigStr))
}
// Verify also checks this, but we can be more sure that we parsed
// correctly if we verify here too.
// FWIW the ecdsa spec states that R and S must be | 1, N - 1 |
// but crypto/ecdsa only checks for Sign != 0. Mirror that.
if signature.R.Sign() != 1 {
return nil, errors.New("signature R isn't 1 or more")
}
if signature.S.Sign() != 1 {
return nil, errors.New("signature S isn't 1 or more")
}
if signature.R.Cmp(curve.Params().N) >= 0 {
return nil, errors.New("signature R is >= curve.N")
}
if signature.S.Cmp(curve.Params().N) >= 0 {
return nil, errors.New("signature S is >= curve.N")
}
return signature, nil
}
// ParseSignature parses a signature in BER format for the curve type `curve'
// into a Signature type, perfoming some basic sanity checks. If parsing
// according to the more strict DER format is needed, use ParseDERSignature.
func ParseSignature(sigStr []byte, curve elliptic.Curve) (*Signature, error) {
return parseSig(sigStr, curve, false)
}
// ParseDERSignature parses a signature in DER format for the curve type
// `curve` into a Signature type. If parsing according to the less strict
// BER format is needed, use ParseSignature.
func ParseDERSignature(sigStr []byte, curve elliptic.Curve) (*Signature, error) {
return parseSig(sigStr, curve, true)
}
// canonicalizeInt returns the bytes for the passed big integer adjusted as
// necessary to ensure that a big-endian encoded integer can't possibly be
// misinterpreted as a negative number. This can happen when the most
// significant bit is set, so it is padded by a leading zero byte in this case.
// Also, the returned bytes will have at least a single byte when the passed
// value is 0. This is required for DER encoding.
func canonicalizeInt(val *big.Int) []byte {
b := val.Bytes()
if len(b) == 0 {
b = []byte{0x00}
}
if b[0]&0x80 != 0 {
paddedBytes := make([]byte, len(b)+1)
copy(paddedBytes[1:], b)
b = paddedBytes
}
return b
}
// canonicalPadding checks whether a big-endian encoded integer could
// possibly be misinterpreted as a negative number (even though OpenSSL
// treats all numbers as unsigned), or if there is any unnecessary
// leading zero padding.
func canonicalPadding(b []byte) error {
switch {
case b[0]&0x80 == 0x80:
return errNegativeValue
case len(b) > 1 && b[0] == 0x00 && b[1]&0x80 != 0x80:
return errExcessivelyPaddedValue
default:
return nil
}
}
// hashToInt converts a hash value to an integer. There is some disagreement
// about how this is done. [NSA] suggests that this is done in the obvious
// manner, but [SECG] truncates the hash to the bit-length of the curve order
// first. We follow [SECG] because that's what OpenSSL does. Additionally,
// OpenSSL right shifts excess bits from the number if the hash is too large
// and we mirror that too.
// This is borrowed from crypto/ecdsa.
func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
orderBits := c.Params().N.BitLen()
orderBytes := (orderBits + 7) / 8
if len(hash) > orderBytes {
hash = hash[:orderBytes]
}
ret := new(big.Int).SetBytes(hash)
excess := len(hash)*8 - orderBits
if excess > 0 {
ret.Rsh(ret, uint(excess))
}
return ret
}
// recoverKeyFromSignature recovers a public key from the signature "sig" on the
// given message hash "msg". Based on the algorithm found in section 4.1.6 of
// SEC 1 Ver 2.0, page 47-48 (53 and 54 in the pdf). This performs the details
// in the inner loop in Step 1. The counter provided is actually the j parameter
// of the loop * 2 - on the first iteration of j we do the R case, else the -R
// case in step 1.6. This counter is used in the bitcoin compressed signature
// format and thus we match bitcoind's behaviour here.
func recoverKeyFromSignature(curve *KoblitzCurve, sig *Signature, msg []byte,
iter int, doChecks bool) (*PublicKey, error) {
// Parse and validate the R and S signature components.
//
// Fail if r and s are not in [1, N-1].
if sig.R.Cmp(curve.Params().N) != -1 {
return nil, errors.New("signature R is >= curve order")
}
if sig.R.Sign() == 0 {
return nil, errors.New("signature R is 0")
}
if sig.S.Cmp(curve.Params().N) != -1 {
return nil, errors.New("signature S is >= curve order")
}
if sig.S.Sign() == 0 {
return nil, errors.New("signature S is 0")
}
// 1.1 x = (n * i) + r
Rx := new(big.Int).Mul(curve.Params().N,
new(big.Int).SetInt64(int64(iter/2)))
Rx.Add(Rx, sig.R)
if Rx.Cmp(curve.Params().P) != -1 {
return nil, errors.New("calculated Rx is larger than curve P")
}
// convert 02<Rx> to point R. (step 1.2 and 1.3). If we are on an odd
// iteration then 1.6 will be done with -R, so we calculate the other
// term when uncompressing the point.
Ry, err := decompressPoint(curve, Rx, iter%2 == 1)
if err != nil {
return nil, err
}
// 1.4 Check n*R is point at infinity
if doChecks {
nRx, nRy := curve.ScalarMult(Rx, Ry, curve.Params().N.Bytes())
if nRx.Sign() != 0 || nRy.Sign() != 0 {
return nil, errors.New("n*R does not equal the point at infinity")
}
}
// 1.5 calculate e from message using the same algorithm as ecdsa
// signature calculation.
e := hashToInt(msg, curve)
// Step 1.6.1:
// We calculate the two terms sR and eG separately multiplied by the
// inverse of r (from the signature). We then add them to calculate
// Q = r^-1(sR-eG)
invr := new(big.Int).ModInverse(sig.R, curve.Params().N)
// first term.
invrS := new(big.Int).Mul(invr, sig.S)
invrS.Mod(invrS, curve.Params().N)
sRx, sRy := curve.ScalarMult(Rx, Ry, invrS.Bytes())
// second term.
e.Neg(e)
e.Mod(e, curve.Params().N)
e.Mul(e, invr)
e.Mod(e, curve.Params().N)
minuseGx, minuseGy := curve.ScalarBaseMult(e.Bytes())
// TODO: this would be faster if we did a mult and add in one
// step to prevent the jacobian conversion back and forth.
Qx, Qy := curve.Add(sRx, sRy, minuseGx, minuseGy)
if Qx.Sign() == 0 && Qy.Sign() == 0 {
return nil, errors.New("point (Qx, Qy) equals the point at infinity")
}
return &PublicKey{
Curve: curve,
X: Qx,
Y: Qy,
}, nil
}
// SignCompact produces a compact signature of the data in hash with the given
// private key on the given koblitz curve. The isCompressed parameter should
// be used to detail if the given signature should reference a compressed
// public key or not. If successful the bytes of the compact signature will be
// returned in the format:
// <(byte of 27+public key solution)+4 if compressed >< padded bytes for signature R><padded bytes for signature S>
// where the R and S parameters are padde up to the bitlengh of the curve.
func SignCompact(curve *KoblitzCurve, key *PrivateKey,
hash []byte, isCompressedKey bool) ([]byte, error) {
sig, err := key.Sign(hash)
if err != nil {
return nil, err
}
// bitcoind checks the bit length of R and S here. The ecdsa signature
// algorithm returns R and S mod N therefore they will be the bitsize of
// the curve, and thus correctly sized.
for i := 0; i < (curve.H+1)*2; i++ {
pk, err := recoverKeyFromSignature(curve, sig, hash, i, true)
if err == nil && pk.X.Cmp(key.X) == 0 && pk.Y.Cmp(key.Y) == 0 {
result := make([]byte, 1, 2*curve.byteSize+1)
result[0] = 27 + byte(i)
if isCompressedKey {
result[0] += 4
}
// Not sure this needs rounding but safer to do so.
curvelen := (curve.BitSize + 7) / 8
// Pad R and S to curvelen if needed.
bytelen := (sig.R.BitLen() + 7) / 8
if bytelen < curvelen {
result = append(result,
make([]byte, curvelen-bytelen)...)
}
result = append(result, sig.R.Bytes()...)
bytelen = (sig.S.BitLen() + 7) / 8
if bytelen < curvelen {
result = append(result,
make([]byte, curvelen-bytelen)...)
}
result = append(result, sig.S.Bytes()...)
return result, nil
}
}
return nil, errors.New("no valid solution for pubkey found")
}
// RecoverCompact verifies the compact signature "signature" of "hash" for the
// Koblitz curve in "curve". If the signature matches then the recovered public
// key will be returned as well as a boolean if the original key was compressed
// or not, else an error will be returned.
func RecoverCompact(curve *KoblitzCurve, signature,
hash []byte) (*PublicKey, bool, error) {
bitlen := (curve.BitSize + 7) / 8
if len(signature) != 1+bitlen*2 {
return nil, false, errors.New("invalid compact signature size")
}
iteration := int((signature[0] - 27) & ^byte(4))
// format is <header byte><bitlen R><bitlen S>
sig := &Signature{
R: new(big.Int).SetBytes(signature[1 : bitlen+1]),
S: new(big.Int).SetBytes(signature[bitlen+1:]),
}
// The iteration used here was encoded
key, err := recoverKeyFromSignature(curve, sig, hash, iteration, false)
if err != nil {
return nil, false, err
}
return key, ((signature[0] - 27) & 4) == 4, nil
}
// signRFC6979 generates a deterministic ECDSA signature according to RFC 6979 and BIP 62.
func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) {
privkey := privateKey.ToECDSA()
N := S256().N
halfOrder := S256().halfOrder
k := nonceRFC6979(privkey.D, hash)
inv := new(big.Int).ModInverse(k, N)
r, _ := privkey.Curve.ScalarBaseMult(k.Bytes())
r.Mod(r, N)
if r.Sign() == 0 {
return nil, errors.New("calculated R is zero")
}
e := hashToInt(hash, privkey.Curve)
s := new(big.Int).Mul(privkey.D, r)
s.Add(s, e)
s.Mul(s, inv)
s.Mod(s, N)
if s.Cmp(halfOrder) == 1 {
s.Sub(N, s)
}
if s.Sign() == 0 {
return nil, errors.New("calculated S is zero")
}
return &Signature{R: r, S: s}, nil
}
// nonceRFC6979 generates an ECDSA nonce (`k`) deterministically according to RFC 6979.
// It takes a 32-byte hash as an input and returns 32-byte nonce to be used in ECDSA algorithm.
func nonceRFC6979(privkey *big.Int, hash []byte) *big.Int {
curve := S256()
q := curve.Params().N
x := privkey
alg := sha256.New
qlen := q.BitLen()
holen := alg().Size()
rolen := (qlen + 7) >> 3
bx := append(int2octets(x, rolen), bits2octets(hash, curve, rolen)...)
// Step B
v := bytes.Repeat(oneInitializer, holen)
// Step C (Go zeroes the all allocated memory)
k := make([]byte, holen)
// Step D
k = mac(alg, k, append(append(v, 0x00), bx...))
// Step E
v = mac(alg, k, v)
// Step F
k = mac(alg, k, append(append(v, 0x01), bx...))
// Step G
v = mac(alg, k, v)
// Step H
for {
// Step H1
var t []byte
// Step H2
for len(t)*8 < qlen {
v = mac(alg, k, v)
t = append(t, v...)
}
// Step H3
secret := hashToInt(t, curve)
if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 {
return secret
}
k = mac(alg, k, append(v, 0x00))
v = mac(alg, k, v)
}
}
// mac returns an HMAC of the given key and message.
func mac(alg func() hash.Hash, k, m []byte) []byte {
h := hmac.New(alg, k)
h.Write(m)
return h.Sum(nil)
}
// https://tools.ietf.org/html/rfc6979#section-2.3.3
func int2octets(v *big.Int, rolen int) []byte {
out := v.Bytes()
// left pad with zeros if it's too short
if len(out) < rolen {
out2 := make([]byte, rolen)
copy(out2[rolen-len(out):], out)
return out2
}
// drop most significant bytes if it's too long
if len(out) > rolen {
out2 := make([]byte, rolen)
copy(out2, out[len(out)-rolen:])
return out2
}
return out
}
// https://tools.ietf.org/html/rfc6979#section-2.3.4
func bits2octets(in []byte, curve elliptic.Curve, rolen int) []byte {
z1 := hashToInt(in, curve)
z2 := new(big.Int).Sub(z1, curve.Params().N)
if z2.Sign() < 0 {
return int2octets(z1, rolen)
}
return int2octets(z2, rolen)
}
// Copyright (c) 2013-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"math/big"
"reflect"
"testing"
)
type signatureTest struct {
name string
sig []byte
der bool
isValid bool
}
// decodeHex decodes the passed hex string and returns the resulting bytes. It
// panics if an error occurs. This is only used in the tests as a helper since
// the only way it can fail is if there is an error in the test source code.
func decodeHex(hexStr string) []byte {
b, err := hex.DecodeString(hexStr)
if err != nil {
panic("invalid hex string in test source: err " + err.Error() +
", hex: " + hexStr)
}
return b
}
var signatureTests = []signatureTest{
// signatures from bitcoin blockchain tx
// 0437cd7f8525ceed2324359c2d0ba26006d92d85
{
name: "valid signature.",
sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: true,
},
{
name: "empty.",
sig: []byte{},
isValid: false,
},
{
name: "bad magic.",
sig: []byte{0x31, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "bad 1st int marker magic.",
sig: []byte{0x30, 0x44, 0x03, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "bad 2nd int marker.",
sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x03, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "short len",
sig: []byte{0x30, 0x43, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "invalid message length",
sig: []byte{0x30, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00},
der: false,
isValid: false,
},
{
name: "long len",
sig: []byte{0x30, 0x45, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "long X",
sig: []byte{0x30, 0x44, 0x02, 0x42, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "long Y",
sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x21, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "short Y",
sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x19, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "trailing crap.",
sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01,
},
der: true,
// This test is now passing (used to be failing) because there
// are signatures in the blockchain that have trailing zero
// bytes before the hashtype. So ParseSignature was fixed to
// permit buffers with trailing nonsense after the actual
// signature.
isValid: true,
},
{
name: "X == N ",
sig: []byte{0x30, 0x44, 0x02, 0x20, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48,
0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41,
0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "X == N ",
sig: []byte{0x30, 0x44, 0x02, 0x20, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48,
0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41,
0x42, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: false,
isValid: false,
},
{
name: "Y == N",
sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41,
},
der: true,
isValid: false,
},
{
name: "Y > N",
sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x42,
},
der: false,
isValid: false,
},
{
name: "0 len X.",
sig: []byte{0x30, 0x24, 0x02, 0x00, 0x02, 0x20, 0x18, 0x15,
0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60, 0xa4,
0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5, 0x6c,
0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8, 0x76,
0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "0 len Y.",
sig: []byte{0x30, 0x24, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x00,
},
der: true,
isValid: false,
},
{
name: "extra R padding.",
sig: []byte{0x30, 0x45, 0x02, 0x21, 0x00, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
{
name: "extra S padding.",
sig: []byte{0x30, 0x45, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x21, 0x00, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca,
0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90,
0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
der: true,
isValid: false,
},
// Standard checks (in BER format, without checking for 'canonical' DER
// signatures) don't test for negative numbers here because there isn't
// a way that is the same between openssl and go that will mark a number
// as negative. The Go ASN.1 parser marks numbers as negative when
// openssl does not (it doesn't handle negative numbers that I can tell
// at all. When not parsing DER signatures, which is done by by bitcoind
// when accepting transactions into its mempool, we otherwise only check
// for the coordinates being zero.
{
name: "X == 0",
sig: []byte{0x30, 0x25, 0x02, 0x01, 0x00, 0x02, 0x20, 0x18,
0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60,
0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5,
0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8,
0x76, 0x8d, 0x1d, 0x09,
},
der: false,
isValid: false,
},
{
name: "Y == 0.",
sig: []byte{0x30, 0x25, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1,
0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6,
0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd,
0x41, 0x02, 0x01, 0x00,
},
der: false,
isValid: false,
},
}
func TestSignatures(t *testing.T) {
for _, test := range signatureTests {
var err error
if test.der {
_, err = ParseDERSignature(test.sig, S256())
} else {
_, err = ParseSignature(test.sig, S256())
}
if err != nil {
if test.isValid {
t.Errorf("%s signature failed when shouldn't %v",
test.name, err)
} /* else {
t.Errorf("%s got error %v", test.name, err)
} */
continue
}
if !test.isValid {
t.Errorf("%s counted as valid when it should fail",
test.name)
}
}
}
// TestSignatureSerialize ensures that serializing signatures works as expected.
func TestSignatureSerialize(t *testing.T) {
tests := []struct {
name string
ecsig *Signature
expected []byte
}{
// signature from bitcoin blockchain tx
// 0437cd7f8525ceed2324359c2d0ba26006d92d85
{
"valid 1 - r and s most significant bits are zero",
&Signature{
R: fromHex("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"),
S: fromHex("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"),
},
[]byte{
0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69,
0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3,
0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32,
0xe9, 0xd6, 0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab,
0x5f, 0xb8, 0xcd, 0x41, 0x02, 0x20, 0x18, 0x15,
0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60,
0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c,
0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22,
0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
},
},
// signature from bitcoin blockchain tx
// cb00f8a0573b18faa8c4f467b049f5d202bf1101d9ef2633bc611be70376a4b4
{
"valid 2 - r most significant bit is one",
&Signature{
R: fromHex("0082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"),
S: fromHex("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"),
},
[]byte{
0x30, 0x45, 0x02, 0x21, 0x00, 0x82, 0x23, 0x5e,
0x21, 0xa2, 0x30, 0x00, 0x22, 0x73, 0x8d, 0xab,
0xb8, 0xe1, 0xbb, 0xd9, 0xd1, 0x9c, 0xfb, 0x1e,
0x7a, 0xb8, 0xc3, 0x0a, 0x23, 0xb0, 0xaf, 0xbb,
0x8d, 0x17, 0x8a, 0xbc, 0xf3, 0x02, 0x20, 0x24,
0xbf, 0x68, 0xe2, 0x56, 0xc5, 0x34, 0xdd, 0xfa,
0xf9, 0x66, 0xbf, 0x90, 0x8d, 0xeb, 0x94, 0x43,
0x05, 0x59, 0x6f, 0x7b, 0xdc, 0xc3, 0x8d, 0x69,
0xac, 0xad, 0x7f, 0x9c, 0x86, 0x87, 0x24,
},
},
// signature from bitcoin blockchain tx
// fda204502a3345e08afd6af27377c052e77f1fefeaeb31bdd45f1e1237ca5470
{
"valid 3 - s most significant bit is one",
&Signature{
R: fromHex("1cadddc2838598fee7dc35a12b340c6bde8b389f7bfd19a1252a17c4b5ed2d71"),
S: new(big.Int).Add(fromHex("00c1a251bbecb14b058a8bd77f65de87e51c47e95904f4c0e9d52eddc21c1415ac"), S256().N),
},
[]byte{
0x30, 0x45, 0x02, 0x20, 0x1c, 0xad, 0xdd, 0xc2,
0x83, 0x85, 0x98, 0xfe, 0xe7, 0xdc, 0x35, 0xa1,
0x2b, 0x34, 0x0c, 0x6b, 0xde, 0x8b, 0x38, 0x9f,
0x7b, 0xfd, 0x19, 0xa1, 0x25, 0x2a, 0x17, 0xc4,
0xb5, 0xed, 0x2d, 0x71, 0x02, 0x21, 0x00, 0xc1,
0xa2, 0x51, 0xbb, 0xec, 0xb1, 0x4b, 0x05, 0x8a,
0x8b, 0xd7, 0x7f, 0x65, 0xde, 0x87, 0xe5, 0x1c,
0x47, 0xe9, 0x59, 0x04, 0xf4, 0xc0, 0xe9, 0xd5,
0x2e, 0xdd, 0xc2, 0x1c, 0x14, 0x15, 0xac,
},
},
{
"valid 4 - s is bigger than half order",
&Signature{
R: fromHex("a196ed0e7ebcbe7b63fe1d8eecbdbde03a67ceba4fc8f6482bdcb9606a911404"),
S: fromHex("971729c7fa944b465b35250c6570a2f31acbb14b13d1565fab7330dcb2b3dfb1"),
},
[]byte{
0x30, 0x45, 0x02, 0x21, 0x00, 0xa1, 0x96, 0xed,
0x0e, 0x7e, 0xbc, 0xbe, 0x7b, 0x63, 0xfe, 0x1d,
0x8e, 0xec, 0xbd, 0xbd, 0xe0, 0x3a, 0x67, 0xce,
0xba, 0x4f, 0xc8, 0xf6, 0x48, 0x2b, 0xdc, 0xb9,
0x60, 0x6a, 0x91, 0x14, 0x04, 0x02, 0x20, 0x68,
0xe8, 0xd6, 0x38, 0x05, 0x6b, 0xb4, 0xb9, 0xa4,
0xca, 0xda, 0xf3, 0x9a, 0x8f, 0x5d, 0x0b, 0x9f,
0xe3, 0x2b, 0x9b, 0x9b, 0x77, 0x49, 0xdc, 0x14,
0x5f, 0x2d, 0xb0, 0x1d, 0x82, 0x61, 0x90,
},
},
{
"zero signature",
&Signature{
R: big.NewInt(0),
S: big.NewInt(0),
},
[]byte{0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00},
},
}
for i, test := range tests {
result := test.ecsig.Serialize()
if !bytes.Equal(result, test.expected) {
t.Errorf("Serialize #%d (%s) unexpected result:\n"+
"got: %x\nwant: %x", i, test.name, result,
test.expected)
}
}
}
func testSignCompact(t *testing.T, tag string, curve *KoblitzCurve,
data []byte, isCompressed bool) {
priv, _ := NewPrivateKey(curve)
hashed := []byte("testing")
sig, err := SignCompact(curve, priv, hashed, isCompressed)
if err != nil {
t.Errorf("%s: error signing: %s", tag, err)
return
}
pk, wasCompressed, err := RecoverCompact(curve, sig, hashed)
if err != nil {
t.Errorf("%s: error recovering: %s", tag, err)
return
}
if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 {
t.Errorf("%s: recovered pubkey doesn't match original "+
"(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y)
return
}
if wasCompressed != isCompressed {
t.Errorf("%s: recovered pubkey doesn't match compressed state "+
"(%v vs %v)", tag, isCompressed, wasCompressed)
return
}
// If we change the compressed bit we should get the same key back,
// but the compressed flag should be reversed.
if isCompressed {
sig[0] -= 4
} else {
sig[0] += 4
}
pk, wasCompressed, err = RecoverCompact(curve, sig, hashed)
if err != nil {
t.Errorf("%s: error recovering (2): %s", tag, err)
return
}
if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 {
t.Errorf("%s: recovered pubkey (2) doesn't match original "+
"(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y)
return
}
if wasCompressed == isCompressed {
t.Errorf("%s: recovered pubkey doesn't match reversed "+
"compressed state (%v vs %v)", tag, isCompressed,
wasCompressed)
return
}
}
func TestSignCompact(t *testing.T) {
for i := 0; i < 256; i++ {
name := fmt.Sprintf("test %d", i)
data := make([]byte, 32)
_, err := rand.Read(data)
if err != nil {
t.Errorf("failed to read random data for %s", name)
continue
}
compressed := i%2 != 0
testSignCompact(t, name, S256(), data, compressed)
}
}
// recoveryTests assert basic tests for public key recovery from signatures.
// The cases are borrowed from github.com/fjl/btcec-issue.
var recoveryTests = []struct {
msg string
sig string
pub string
err error
}{
{
// Valid curve point recovered.
msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008",
sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93",
pub: "04E32DF42865E97135ACFB65F3BAE71BDC86F4D49150AD6A440B6F15878109880A0A2B2667F7E725CEEA70C673093BF67663E0312623C8E091B13CF2C0F11EF652",
},
{
// Invalid curve point recovered.
msg: "00c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c",
sig: "0100b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f00b940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
err: fmt.Errorf("invalid square root"),
},
{
// Point at infinity recovered
msg: "6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9",
sig: "0079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9",
err: fmt.Errorf("point (Qx, Qy) equals the point at infinity"),
},
{
// Low R and S values.
msg: "ba09edc1275a285fb27bfe82c4eea240a907a0dbaf9e55764b8f318c37d5974f",
sig: "00000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000004",
pub: "04A7640409AA2083FDAD38B2D8DE1263B2251799591D840653FB02DBBA503D7745FCB83D80E08A1E02896BE691EA6AFFB8A35939A646F1FC79052A744B1C82EDC3",
},
{
// Zero R value
//
// Test case contributed by Ethereum Swarm: GH-1651
msg: "3060d2c77c1e192d62ad712fb400e04e6f779914a6876328ff3b213fa85d2012",
sig: "65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037a3",
err: fmt.Errorf("signature R is 0"),
},
{
// Zero R value
//
// Test case contributed by Ethereum Swarm: GH-1651
msg: "2bcebac60d8a78e520ae81c2ad586792df495ed429bd730dcd897b301932d054",
sig: "060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c",
err: fmt.Errorf("signature R is 0"),
},
{
// R = N (curve order of secp256k1)
msg: "2bcebac60d8a78e520ae81c2ad586792df495ed429bd730dcd897b301932d054",
sig: "65fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414100000000000000000000000000000000000000000000000000000000000037a3",
err: fmt.Errorf("signature R is >= curve order"),
},
{
// Zero S value
msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008",
sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549980000000000000000000000000000000000000000000000000000000000000000",
err: fmt.Errorf("signature S is 0"),
},
{
// S = N (curve order of secp256k1)
msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008",
sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e54998fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
err: fmt.Errorf("signature S is >= curve order"),
},
}
func TestRecoverCompact(t *testing.T) {
for i, test := range recoveryTests {
msg := decodeHex(test.msg)
sig := decodeHex(test.sig)
// Magic DER constant.
sig[0] += 27
pub, _, err := RecoverCompact(S256(), sig, msg)
// Verify that returned error matches as expected.
if !reflect.DeepEqual(test.err, err) {
t.Errorf("unexpected error returned from pubkey "+
"recovery #%d: wanted %v, got %v",
i, test.err, err)
continue
}
// If check succeeded because a proper error was returned, we
// ignore the returned pubkey.
if err != nil {
continue
}
// Otherwise, ensure the correct public key was recovered.
exPub, _ := ParsePubKey(decodeHex(test.pub), S256())
if !exPub.IsEqual(pub) {
t.Errorf("unexpected recovered public key #%d: "+
"want %v, got %v", i, exPub, pub)
}
}
}
func TestRFC6979(t *testing.T) {
// Test vectors matching Trezor and CoreBitcoin implementations.
// - https://github.com/trezor/trezor-crypto/blob/9fea8f8ab377dc514e40c6fd1f7c89a74c1d8dc6/tests.c#L432-L453
// - https://github.com/oleganza/CoreBitcoin/blob/e93dd71207861b5bf044415db5fa72405e7d8fbc/CoreBitcoin/BTCKey%2BTests.m#L23-L49
tests := []struct {
key string
msg string
nonce string
signature string
}{
{
"cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50",
"sample",
"2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3",
"3045022100af340daf02cc15c8d5d08d7735dfe6b98a474ed373bdb5fbecf7571be52b384202205009fb27f37034a9b24b707b7c6b79ca23ddef9e25f7282e8a797efe53a8f124",
},
{
// This signature hits the case when S is higher than halforder.
// If S is not canonicalized (lowered by halforder), this test will fail.
"0000000000000000000000000000000000000000000000000000000000000001",
"Satoshi Nakamoto",
"8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15",
"3045022100934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d802202442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5",
},
{
"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"Satoshi Nakamoto",
"33a19b60e25fb6f4435af53a3d42d493644827367e6453928554f43e49aa6f90",
"3045022100fd567d121db66e382991534ada77a6bd3106f0a1098c231e47993447cd6af2d002206b39cd0eb1bc8603e159ef5c20a5c8ad685a45b06ce9bebed3f153d10d93bed5",
},
{
"f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181",
"Alan Turing",
"525a82b70e67874398067543fd84c83d30c175fdc45fdeee082fe13b1d7cfdf1",
"304402207063ae83e7f62bbb171798131b4a0564b956930092b33b07b395615d9ec7e15c022058dfcc1e00a35e1572f366ffe34ba0fc47db1e7189759b9fb233c5b05ab388ea",
},
{
"0000000000000000000000000000000000000000000000000000000000000001",
"All those moments will be lost in time, like tears in rain. Time to die...",
"38aa22d72376b4dbc472e06c3ba403ee0a394da63fc58d88686c611aba98d6b3",
"30450221008600dbd41e348fe5c9465ab92d23e3db8b98b873beecd930736488696438cb6b0220547fe64427496db33bf66019dacbf0039c04199abb0122918601db38a72cfc21",
},
{
"e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2",
"There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!",
"1f4b84c23a86a221d233f2521be018d9318639d5b8bbd6374a8a59232d16ad3d",
"3045022100b552edd27580141f3b2a5463048cb7cd3e047b97c9f98076c32dbdf85a68718b0220279fa72dd19bfae05577e06c7c0c1900c371fcd5893f7e1d56a37d30174671f6",
},
}
for i, test := range tests {
privKey, _ := PrivKeyFromBytes(S256(), decodeHex(test.key))
hash := sha256.Sum256([]byte(test.msg))
// Ensure deterministically generated nonce is the expected value.
gotNonce := nonceRFC6979(privKey.D, hash[:]).Bytes()
wantNonce := decodeHex(test.nonce)
if !bytes.Equal(gotNonce, wantNonce) {
t.Errorf("NonceRFC6979 #%d (%s): Nonce is incorrect: "+
"%x (expected %x)", i, test.msg, gotNonce,
wantNonce)
continue
}
// Ensure deterministically generated signature is the expected value.
gotSig, err := privKey.Sign(hash[:])
if err != nil {
t.Errorf("Sign #%d (%s): unexpected error: %v", i,
test.msg, err)
continue
}
gotSigBytes := gotSig.Serialize()
wantSigBytes := decodeHex(test.signature)
if !bytes.Equal(gotSigBytes, wantSigBytes) {
t.Errorf("Sign #%d (%s): mismatched signature: %x "+
"(expected %x)", i, test.msg, gotSigBytes,
wantSigBytes)
continue
}
}
}
func TestSignatureIsEqual(t *testing.T) {
sig1 := &Signature{
R: fromHex("0082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"),
S: fromHex("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"),
}
sig2 := &Signature{
R: fromHex("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"),
S: fromHex("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"),
}
if !sig1.IsEqual(sig1) {
t.Fatalf("value of IsEqual is incorrect, %v is "+
"equal to %v", sig1, sig1)
}
if sig1.IsEqual(sig2) {
t.Fatalf("value of IsEqual is incorrect, %v is not "+
"equal to %v", sig1, sig2)
}
}
......@@ -23,7 +23,7 @@ import (
"fmt"
"math/big"
"github.com/btcsuite/btcd/btcec"
"github.com/ethereum/go-ethereum/crypto/btcec"
)
// Ecrecover returns the uncompressed public key that created the given signature.
......
......@@ -3,7 +3,6 @@ module github.com/ethereum/go-ethereum
go 1.17
require (
github.com/btcsuite/btcd v0.22.0-beta // indirect
github.com/holiman/uint256 v1.2.0 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment