Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
288c7b42
Commit
288c7b42
authored
Oct 06, 2021
by
George Hotz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bring btcec into minigeth
parent
81bec775
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
7396 additions
and
2 deletions
+7396
-2
README.md
minigeth/crypto/btcec/README.md
+68
-0
bench_test.go
minigeth/crypto/btcec/bench_test.go
+145
-0
btcec.go
minigeth/crypto/btcec/btcec.go
+978
-0
btcec_test.go
minigeth/crypto/btcec/btcec_test.go
+889
-0
ciphering.go
minigeth/crypto/btcec/ciphering.go
+216
-0
ciphering_test.go
minigeth/crypto/btcec/ciphering_test.go
+174
-0
doc.go
minigeth/crypto/btcec/doc.go
+21
-0
example_test.go
minigeth/crypto/btcec/example_test.go
+168
-0
field.go
minigeth/crypto/btcec/field.go
+1356
-0
field_test.go
minigeth/crypto/btcec/field_test.go
+1121
-0
genprecomps.go
minigeth/crypto/btcec/genprecomps.go
+64
-0
gensecp256k1.go
minigeth/crypto/btcec/gensecp256k1.go
+203
-0
precompute.go
minigeth/crypto/btcec/precompute.go
+67
-0
privkey.go
minigeth/crypto/btcec/privkey.go
+73
-0
privkey_test.go
minigeth/crypto/btcec/privkey_test.go
+55
-0
pubkey.go
minigeth/crypto/btcec/pubkey.go
+194
-0
pubkey_test.go
minigeth/crypto/btcec/pubkey_test.go
+296
-0
secp256k1.go
minigeth/crypto/btcec/secp256k1.go
+10
-0
signature.go
minigeth/crypto/btcec/signature.go
+563
-0
signature_test.go
minigeth/crypto/btcec/signature_test.go
+734
-0
signature_nocgo.go
minigeth/crypto/signature_nocgo.go
+1
-1
go.mod
minigeth/go.mod
+0
-1
No files found.
minigeth/crypto/btcec/README.md
0 → 100644
View file @
288c7b42
btcec
=====
[

](https://github.com/btcsuite/btcd/actions)
[

](http://copyfree.org)
[

](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.
minigeth/crypto/btcec/bench_test.go
0 → 100644
View file @
288c7b42
// 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
}
minigeth/crypto/btcec/btcec.go
0 → 100644
View file @
288c7b42
// 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
}
minigeth/crypto/btcec/btcec_test.go
0 → 100644
View file @
288c7b42
// 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
\n
got: (%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
\n
got: (%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
\n
got: (%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
\n
got: (%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
)
}
}
}
minigeth/crypto/btcec/ciphering.go
0 → 100644
View file @
288c7b42
// 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
}
minigeth/crypto/btcec/ciphering_test.go
0 → 100644
View file @
288c7b42
// 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
)
}
}
}
minigeth/crypto/btcec/doc.go
0 → 100644
View file @
288c7b42
// 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
minigeth/crypto/btcec/example_test.go
0 → 100644
View file @
288c7b42
// 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
}
minigeth/crypto/btcec/field.go
0 → 100644
View file @
288c7b42
// 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
)
}
minigeth/crypto/btcec/field_test.go
0 → 100644
View file @
288c7b42
// 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
\n
got: %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
\n
got: %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
\n
want: %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
\n
want: %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
\n
want: %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
\n
want: %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
\n
want: %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
\n
want: %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
\n
want: %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
\n
want: %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
\n
want: %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
\n
want: %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
\n
want: %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
\n
got_neg: %v
\n
want: %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
\n
got_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
\n
got: %x
\n
want: %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
\n
got: %x
\n
want: %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
}
minigeth/crypto/btcec/genprecomps.go
0 → 100644
View file @
288c7b42
// 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
)
}
minigeth/crypto/btcec/gensecp256k1.go
0 → 100644
View file @
288c7b42
// 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
}
minigeth/crypto/btcec/precompute.go
0 → 100644
View file @
288c7b42
// 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
}
minigeth/crypto/btcec/privkey.go
0 → 100644
View file @
288c7b42
// 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
())
}
minigeth/crypto/btcec/privkey_test.go
0 → 100644
View file @
288c7b42
// 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
)
}
}
}
minigeth/crypto/btcec/pubkey.go
0 → 100644
View file @
288c7b42
// 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
...
)
}
minigeth/crypto/btcec/pubkey_test.go
0 → 100644
View file @
288c7b42
// 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
)
}
}
}
minigeth/crypto/btcec/secp256k1.go
0 → 100644
View file @
288c7b42
This source diff could not be displayed because it is too large. You can
view the blob
instead.
minigeth/crypto/btcec/signature.go
0 → 100644
View file @
288c7b42
// 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
)
}
minigeth/crypto/btcec/signature_test.go
0 → 100644
View file @
288c7b42
// 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
\n
want: %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
)
}
}
minigeth/crypto/signature_nocgo.go
View file @
288c7b42
...
@@ -23,7 +23,7 @@ import (
...
@@ -23,7 +23,7 @@ import (
"fmt"
"fmt"
"math/big"
"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.
// Ecrecover returns the uncompressed public key that created the given signature.
...
...
minigeth/go.mod
View file @
288c7b42
...
@@ -3,7 +3,6 @@ module github.com/ethereum/go-ethereum
...
@@ -3,7 +3,6 @@ module github.com/ethereum/go-ethereum
go 1.17
go 1.17
require (
require (
github.com/btcsuite/btcd v0.22.0-beta // indirect
github.com/holiman/uint256 v1.2.0 // indirect
github.com/holiman/uint256 v1.2.0 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment