forked from TrueCloudLab/neoneo-go
_pkg.dev: drop crypto/elliptic
It's the same implementation that we have in pkg/crypto (based on https://github.com/vsergeev/btckeygenie) but with tests preserved. I don't see any reason to port tests from it because even the pkg/crypto copy should go away to fix #245.
This commit is contained in:
parent
2275b9e4ad
commit
b19190b32f
4 changed files with 0 additions and 632 deletions
|
@ -1,18 +0,0 @@
|
|||
## Package - Elliptic
|
||||
|
||||
### Why
|
||||
|
||||
The curve and arithmetic functions have been modularised, so that curves can be swapped in and out, without effecting the functionality.
|
||||
|
||||
The modular arithmetic used is not specialised for a specific curve.
|
||||
|
||||
In order to use this package, you must declare an ellipticcurve struct and then set the curve.
|
||||
|
||||
Example:
|
||||
|
||||
`
|
||||
|
||||
curve = NewEllipticCurve(Secp256k1)
|
||||
|
||||
`
|
||||
If no curve is set, the default curve is the r1 curve used for NEO. The tests are done using the k1 curve, so in the elliptic_test.go file, the curve is changed accordingly.
|
|
@ -1,64 +0,0 @@
|
|||
package elliptic
|
||||
|
||||
/*
|
||||
This file was originally made by vsergeev.
|
||||
|
||||
Modifications have been made under the MIT license.
|
||||
License: MIT
|
||||
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var curve Curve
|
||||
|
||||
type curveType string
|
||||
|
||||
const (
|
||||
// Secp256r1 curve type
|
||||
Secp256r1 curveType = "Secp256r1"
|
||||
// Secp256k1 curve type
|
||||
Secp256k1 curveType = "Secp256k1"
|
||||
)
|
||||
|
||||
// SetCurveSecp256r1 Will set the curve parameters to match Secp256r1
|
||||
func (ChosenCurve *Curve) SetCurveSecp256r1() {
|
||||
ChosenCurve.P, _ = new(big.Int).SetString("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16) //Q
|
||||
ChosenCurve.A, _ = new(big.Int).SetString("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16)
|
||||
ChosenCurve.B, _ = new(big.Int).SetString("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", 16)
|
||||
ChosenCurve.G.X, _ = new(big.Int).SetString("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 16)
|
||||
ChosenCurve.G.Y, _ = new(big.Int).SetString("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", 16)
|
||||
ChosenCurve.N, _ = new(big.Int).SetString("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 16)
|
||||
ChosenCurve.H, _ = new(big.Int).SetString("01", 16)
|
||||
ChosenCurve.Name = "Secp256r1"
|
||||
}
|
||||
|
||||
// SetCurveSecp256k1 Will set the curve parameters to match Secp256k1
|
||||
func (ChosenCurve *Curve) SetCurveSecp256k1() {
|
||||
ChosenCurve.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16)
|
||||
ChosenCurve.A, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000000", 16)
|
||||
ChosenCurve.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16)
|
||||
ChosenCurve.G.X, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
|
||||
ChosenCurve.G.Y, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16)
|
||||
ChosenCurve.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
|
||||
ChosenCurve.H, _ = new(big.Int).SetString("01", 16)
|
||||
ChosenCurve.Name = "Secp256k1"
|
||||
}
|
||||
|
||||
//NewEllipticCurve will instantiate a new EllipticCurve
|
||||
//Defaults to secp256r1
|
||||
func NewEllipticCurve(ct curveType) Curve {
|
||||
var curve Curve
|
||||
switch ct {
|
||||
case Secp256k1:
|
||||
curve.SetCurveSecp256k1()
|
||||
case Secp256r1:
|
||||
curve.SetCurveSecp256r1()
|
||||
default:
|
||||
curve.SetCurveSecp256r1()
|
||||
}
|
||||
return curve
|
||||
}
|
|
@ -1,319 +0,0 @@
|
|||
/*
|
||||
This file has been modified under the MIT license.
|
||||
Original: https://github.com/vsergeev/btckeygenie
|
||||
*/
|
||||
|
||||
package elliptic
|
||||
|
||||
import (
|
||||
nativeelliptic "crypto/elliptic"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// Point represents a point on an EllipticCurve.
|
||||
type Point struct {
|
||||
X *big.Int
|
||||
Y *big.Int
|
||||
}
|
||||
|
||||
// Curve represents the parameters of a short Weierstrass equation elliptic curve.
|
||||
/* y**2 = x**3 + a*x + b % p */
|
||||
type Curve struct {
|
||||
A *big.Int
|
||||
B *big.Int
|
||||
P *big.Int
|
||||
G Point
|
||||
N *big.Int
|
||||
H *big.Int
|
||||
Name string
|
||||
}
|
||||
|
||||
// dump dumps the bytes of a point for debugging.
|
||||
func (p *Point) dump() {
|
||||
fmt.Print(p.format())
|
||||
}
|
||||
|
||||
// format formats the bytes of a point for debugging.
|
||||
func (p *Point) format() string {
|
||||
if p.X == nil && p.Y == nil {
|
||||
return "(inf,inf)"
|
||||
}
|
||||
return fmt.Sprintf("(%s,%s)", hex.EncodeToString(p.X.Bytes()), hex.EncodeToString(p.Y.Bytes()))
|
||||
}
|
||||
|
||||
// Params represent the paramters for the Elliptic Curve
|
||||
func (ec Curve) Params() *nativeelliptic.CurveParams {
|
||||
return &nativeelliptic.CurveParams{
|
||||
P: ec.P,
|
||||
N: ec.N,
|
||||
B: ec.B,
|
||||
Gx: ec.G.X,
|
||||
Gy: ec.G.Y,
|
||||
BitSize: 256,
|
||||
Name: ec.Name,
|
||||
}
|
||||
}
|
||||
|
||||
/*** Modular Arithmetic ***/
|
||||
|
||||
/* NOTE: Returning a new z each time below is very space inefficient, but the
|
||||
* alternate accumulator based design makes the point arithmetic functions look
|
||||
* absolutely hideous. I may still change this in the future. */
|
||||
|
||||
// addMod computes z = (x + y) % p.
|
||||
func addMod(x *big.Int, y *big.Int, p *big.Int) (z *big.Int) {
|
||||
z = new(big.Int).Add(x, y)
|
||||
z.Mod(z, p)
|
||||
return z
|
||||
}
|
||||
|
||||
// subMod computes z = (x - y) % p.
|
||||
func subMod(x *big.Int, y *big.Int, p *big.Int) (z *big.Int) {
|
||||
z = new(big.Int).Sub(x, y)
|
||||
z.Mod(z, p)
|
||||
return z
|
||||
}
|
||||
|
||||
// mulMod computes z = (x * y) % p.
|
||||
func mulMod(x *big.Int, y *big.Int, p *big.Int) (z *big.Int) {
|
||||
n := new(big.Int).Set(x)
|
||||
z = big.NewInt(0)
|
||||
|
||||
for i := 0; i < y.BitLen(); i++ {
|
||||
if y.Bit(i) == 1 {
|
||||
z = addMod(z, n, p)
|
||||
}
|
||||
n = addMod(n, n, p)
|
||||
}
|
||||
|
||||
return z
|
||||
}
|
||||
|
||||
// invMod computes z = (1/x) % p.
|
||||
func invMod(x *big.Int, p *big.Int) (z *big.Int) {
|
||||
z = new(big.Int).ModInverse(x, p)
|
||||
return z
|
||||
}
|
||||
|
||||
// expMod computes z = (x^e) % p.
|
||||
func expMod(x *big.Int, y *big.Int, p *big.Int) (z *big.Int) {
|
||||
z = new(big.Int).Exp(x, y, p)
|
||||
return z
|
||||
}
|
||||
|
||||
// sqrtMod computes z = sqrt(x) % p.
|
||||
func sqrtMod(x *big.Int, p *big.Int) (z *big.Int) {
|
||||
/* assert that p % 4 == 3 */
|
||||
if new(big.Int).Mod(p, big.NewInt(4)).Cmp(big.NewInt(3)) != 0 {
|
||||
panic("p is not equal to 3 mod 4!")
|
||||
}
|
||||
|
||||
/* z = sqrt(x) % p = x^((p+1)/4) % p */
|
||||
|
||||
/* e = (p+1)/4 */
|
||||
e := new(big.Int).Add(p, big.NewInt(1))
|
||||
e = e.Rsh(e, 2)
|
||||
|
||||
z = expMod(x, e, p)
|
||||
return z
|
||||
}
|
||||
|
||||
/*** Point Arithmetic on Curve ***/
|
||||
|
||||
// IsInfinity checks if point P is infinity on EllipticCurve ec.
|
||||
func (ec *Curve) IsInfinity(P Point) bool {
|
||||
/* We use (nil,nil) to represent O, the point at infinity. */
|
||||
|
||||
if P.X == nil && P.Y == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// IsOnCurve checks if point P is on EllipticCurve ec.
|
||||
func (ec Curve) IsOnCurve(P1, P2 *big.Int) bool {
|
||||
P := Point{P1, P2}
|
||||
if ec.IsInfinity(P) {
|
||||
return false
|
||||
}
|
||||
|
||||
/* y**2 = x**3 + a*x + b % p */
|
||||
lhs := mulMod(P.Y, P.Y, ec.P)
|
||||
rhs := addMod(
|
||||
addMod(
|
||||
expMod(P.X, big.NewInt(3), ec.P),
|
||||
mulMod(ec.A, P.X, ec.P), ec.P),
|
||||
ec.B, ec.P)
|
||||
|
||||
if lhs.Cmp(rhs) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Add computes R = P + Q on EllipticCurve ec.
|
||||
func (ec Curve) Add(P1, P2, Q1, Q2 *big.Int) (R1 *big.Int, R2 *big.Int) {
|
||||
/* See rules 1-5 on SEC1 pg.7 http://www.secg.org/collateral/sec1_final.pdf */
|
||||
P := Point{P1, P2}
|
||||
Q := Point{Q1, Q2}
|
||||
R := Point{}
|
||||
if ec.IsInfinity(P) && ec.IsInfinity(Q) {
|
||||
/* Rule #1 Identity */
|
||||
/* R = O + O = O */
|
||||
|
||||
R.X = nil
|
||||
R.Y = nil
|
||||
|
||||
} else if ec.IsInfinity(P) {
|
||||
/* Rule #2 Identity */
|
||||
/* R = O + Q = Q */
|
||||
|
||||
R.X = new(big.Int).Set(Q.X)
|
||||
R.Y = new(big.Int).Set(Q.Y)
|
||||
|
||||
} else if ec.IsInfinity(Q) {
|
||||
/* Rule #2 Identity */
|
||||
/* R = P + O = P */
|
||||
|
||||
R.X = new(big.Int).Set(P.X)
|
||||
R.Y = new(big.Int).Set(P.Y)
|
||||
|
||||
} else if P.X.Cmp(Q.X) == 0 && addMod(P.Y, Q.Y, ec.P).Sign() == 0 {
|
||||
/* Rule #3 Identity */
|
||||
/* R = (x,y) + (x,-y) = O */
|
||||
|
||||
R.X = nil
|
||||
R.Y = nil
|
||||
|
||||
} else if P.X.Cmp(Q.X) == 0 && P.Y.Cmp(Q.Y) == 0 && P.Y.Sign() != 0 {
|
||||
/* Rule #5 Point doubling */
|
||||
/* R = P + P */
|
||||
|
||||
/* Lambda = (3*P.X*P.X + a) / (2*P.Y) */
|
||||
num := addMod(
|
||||
mulMod(big.NewInt(3),
|
||||
mulMod(P.X, P.X, ec.P), ec.P),
|
||||
ec.A, ec.P)
|
||||
den := invMod(mulMod(big.NewInt(2), P.Y, ec.P), ec.P)
|
||||
lambda := mulMod(num, den, ec.P)
|
||||
|
||||
/* R.X = lambda*lambda - 2*P.X */
|
||||
R.X = subMod(
|
||||
mulMod(lambda, lambda, ec.P),
|
||||
mulMod(big.NewInt(2), P.X, ec.P),
|
||||
ec.P)
|
||||
/* R.Y = lambda*(P.X - R.X) - P.Y */
|
||||
R.Y = subMod(
|
||||
mulMod(lambda, subMod(P.X, R.X, ec.P), ec.P),
|
||||
P.Y, ec.P)
|
||||
|
||||
} else if P.X.Cmp(Q.X) != 0 {
|
||||
/* Rule #4 Point addition */
|
||||
/* R = P + Q */
|
||||
|
||||
/* Lambda = (Q.Y - P.Y) / (Q.X - P.X) */
|
||||
num := subMod(Q.Y, P.Y, ec.P)
|
||||
den := invMod(subMod(Q.X, P.X, ec.P), ec.P)
|
||||
lambda := mulMod(num, den, ec.P)
|
||||
|
||||
/* R.X = lambda*lambda - P.X - Q.X */
|
||||
R.X = subMod(
|
||||
subMod(
|
||||
mulMod(lambda, lambda, ec.P),
|
||||
P.X, ec.P),
|
||||
Q.X, ec.P)
|
||||
|
||||
/* R.Y = lambda*(P.X - R.X) - P.Y */
|
||||
R.Y = subMod(
|
||||
mulMod(lambda,
|
||||
subMod(P.X, R.X, ec.P), ec.P),
|
||||
P.Y, ec.P)
|
||||
} else {
|
||||
panic(fmt.Sprintf("Unsupported point addition: %v + %v", P.format(), Q.format()))
|
||||
}
|
||||
|
||||
return R.X, R.Y
|
||||
}
|
||||
|
||||
// ScalarMult computes Q = k * P on EllipticCurve ec.
|
||||
func (ec Curve) ScalarMult(P1, P2 *big.Int, l []byte) (Q1, Q2 *big.Int) {
|
||||
/* Note: this function is not constant time, due to the branching nature of
|
||||
* the underlying point Add() function. */
|
||||
|
||||
/* Montgomery Ladder Point Multiplication
|
||||
*
|
||||
* Implementation based on pseudocode here:
|
||||
* See https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Montgomery_ladder */
|
||||
|
||||
P := Point{P1, P2}
|
||||
k := big.Int{}
|
||||
k.SetBytes(l)
|
||||
|
||||
var R0 Point
|
||||
var R1 Point
|
||||
|
||||
R0.X = nil
|
||||
R0.Y = nil
|
||||
R1.X = new(big.Int).Set(P.X)
|
||||
R1.Y = new(big.Int).Set(P.Y)
|
||||
|
||||
for i := ec.N.BitLen() - 1; i >= 0; i-- {
|
||||
if k.Bit(i) == 0 {
|
||||
R1.X, R1.Y = ec.Add(R0.X, R0.Y, R1.X, R1.Y)
|
||||
R0.X, R0.Y = ec.Add(R0.X, R0.Y, R0.X, R0.Y)
|
||||
} else {
|
||||
R0.X, R0.Y = ec.Add(R0.X, R0.Y, R1.X, R1.Y)
|
||||
R1.X, R1.Y = ec.Add(R1.X, R1.Y, R1.X, R1.Y)
|
||||
}
|
||||
}
|
||||
|
||||
return R0.X, R0.Y
|
||||
}
|
||||
|
||||
// ScalarBaseMult computes Q = k * G on EllipticCurve ec.
|
||||
func (ec Curve) ScalarBaseMult(k []byte) (Q1, Q2 *big.Int) {
|
||||
|
||||
return ec.ScalarMult(ec.G.X, ec.G.Y, k)
|
||||
}
|
||||
|
||||
// Decompress decompresses coordinate x and ylsb (y's least significant bit) into a Point P on EllipticCurve ec.
|
||||
func (ec *Curve) Decompress(x *big.Int, ylsb uint) (P Point, err error) {
|
||||
/* y**2 = x**3 + a*x + b % p */
|
||||
rhs := addMod(
|
||||
addMod(
|
||||
expMod(x, big.NewInt(3), ec.P),
|
||||
mulMod(ec.A, x, ec.P),
|
||||
ec.P),
|
||||
ec.B, ec.P)
|
||||
|
||||
/* y = sqrt(rhs) % p */
|
||||
y := sqrtMod(rhs, ec.P)
|
||||
|
||||
/* Use -y if opposite lsb is required */
|
||||
if y.Bit(0) != (ylsb & 0x1) {
|
||||
y = subMod(big.NewInt(0), y, ec.P)
|
||||
}
|
||||
|
||||
P.X = x
|
||||
P.Y = y
|
||||
|
||||
if !ec.IsOnCurve(P.X, P.Y) {
|
||||
return P, errors.New("compressed (x, ylsb) not on curve")
|
||||
}
|
||||
|
||||
return P, nil
|
||||
}
|
||||
|
||||
// Double will return the (x1+x1,y1+y1)
|
||||
func (ec Curve) Double(x1, y1 *big.Int) (x, y *big.Int) {
|
||||
x = &big.Int{}
|
||||
x.SetBytes([]byte{0x00})
|
||||
y = &big.Int{}
|
||||
y.SetBytes([]byte{0x00})
|
||||
return x, y
|
||||
}
|
|
@ -1,231 +0,0 @@
|
|||
/* btckeygenie v1.0.0
|
||||
* https://github.com/vsergeev/btckeygenie
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
package elliptic
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
curve = NewEllipticCurve(Secp256k1)
|
||||
}
|
||||
|
||||
func hex2int(hexstring string) (v *big.Int) {
|
||||
v, _ = new(big.Int).SetString(hexstring, 16)
|
||||
return v
|
||||
}
|
||||
|
||||
func TestOnCurve(t *testing.T) {
|
||||
if !curve.IsOnCurve(curve.G.X, curve.G.Y) {
|
||||
t.Fatal("failure G on curve")
|
||||
}
|
||||
|
||||
t.Log("G on curve")
|
||||
}
|
||||
|
||||
func TestInfinity(t *testing.T) {
|
||||
O := Point{nil, nil}
|
||||
|
||||
/* O not on curve */
|
||||
if curve.IsOnCurve(O.X, O.Y) {
|
||||
t.Fatal("failure O on curve")
|
||||
}
|
||||
|
||||
/* O is infinity */
|
||||
if !curve.IsInfinity(O) {
|
||||
t.Fatal("failure O not infinity on curve")
|
||||
}
|
||||
|
||||
t.Log("O is not on curve and is infinity")
|
||||
}
|
||||
|
||||
func TestPointAdd(t *testing.T) {
|
||||
X := "50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
|
||||
Y := "2cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6"
|
||||
|
||||
P := Point{hex2int(X), hex2int(Y)}
|
||||
O := Point{nil, nil}
|
||||
|
||||
/* R = O + O = O */
|
||||
{
|
||||
R1, R2 := curve.Add(O.X, O.Y, O.X, O.Y)
|
||||
R := Point{R1, R2}
|
||||
if !curve.IsInfinity(R) {
|
||||
t.Fatal("failure O + O = O")
|
||||
}
|
||||
t.Log("success O + O = O")
|
||||
}
|
||||
|
||||
/* R = P + O = P */
|
||||
{
|
||||
R1, R2 := curve.Add(P.X, P.Y, O.X, O.Y)
|
||||
R := Point{R1, R2}
|
||||
if R.X.Cmp(P.X) != 0 || R.Y.Cmp(P.Y) != 0 {
|
||||
t.Fatal("failure P + O = P")
|
||||
}
|
||||
t.Log("success P + O = P")
|
||||
}
|
||||
|
||||
/* R = O + Q = Q */
|
||||
{
|
||||
R1, R2 := curve.Add(O.X, O.Y, P.X, P.Y)
|
||||
R := Point{R1, R2}
|
||||
if R.X.Cmp(P.X) != 0 || R.Y.Cmp(P.Y) != 0 {
|
||||
t.Fatal("failure O + Q = Q")
|
||||
}
|
||||
t.Log("success O + Q = Q")
|
||||
}
|
||||
|
||||
/* R = (x,y) + (x,-y) = O */
|
||||
{
|
||||
Q := Point{P.X, subMod(big.NewInt(0), P.Y, curve.P)}
|
||||
|
||||
R1, R2 := curve.Add(P.X, P.Y, Q.X, Q.Y)
|
||||
R := Point{R1, R2}
|
||||
if !curve.IsInfinity(R) {
|
||||
t.Fatal("failure (x,y) + (x,-y) = O")
|
||||
}
|
||||
t.Log("success (x,y) + (x,-y) = O")
|
||||
}
|
||||
|
||||
/* R = P + P */
|
||||
{
|
||||
PP := Point{hex2int("5dbcd5dfea550eb4fd3b5333f533f086bb5267c776e2a1a9d8e84c16a6743d82"), hex2int("8dde3986b6cbe395da64b6e95fb81f8af73f6e0cf1100555005bb4ba2a6a4a07")}
|
||||
|
||||
R1, R2 := curve.Add(P.X, P.Y, P.X, P.Y)
|
||||
R := Point{R1, R2}
|
||||
if R.X.Cmp(PP.X) != 0 || R.Y.Cmp(PP.Y) != 0 {
|
||||
t.Fatal("failure P + P")
|
||||
}
|
||||
t.Log("success P + P")
|
||||
}
|
||||
|
||||
Q := Point{hex2int("a83b8de893467d3a88d959c0eb4032d9ce3bf80f175d4d9e75892a3ebb8ab7e5"), hex2int("370f723328c24b7a97fe34063ba68f253fb08f8645d7c8b9a4ff98e3c29e7f0d")}
|
||||
PQ := Point{hex2int("fe7d540002e4355eb0ec36c217b4735495de7bd8634055ded3683b0e9da70ef1"), hex2int("fc033c1d74cb34e087a3495e505c0fc0e9e3e8297994878d89d882254ce8a9ef")}
|
||||
|
||||
/* R = P + Q */
|
||||
{
|
||||
R1, R2 := curve.Add(P.X, P.Y, Q.X, Q.Y)
|
||||
R := Point{R1, R2}
|
||||
if R.X.Cmp(PQ.X) != 0 || R.Y.Cmp(PQ.Y) != 0 {
|
||||
t.Fatal("failure P + Q")
|
||||
}
|
||||
t.Log("success P + Q")
|
||||
}
|
||||
|
||||
/* R = Q + P */
|
||||
{
|
||||
R1, R2 := curve.Add(Q.X, Q.Y, P.X, P.Y)
|
||||
R := Point{R1, R2}
|
||||
if R.X.Cmp(PQ.X) != 0 || R.Y.Cmp(PQ.Y) != 0 {
|
||||
t.Fatal("failure Q + P")
|
||||
}
|
||||
t.Log("success Q + P")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointScalarMult(t *testing.T) {
|
||||
X := "50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
|
||||
Y := "2cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6"
|
||||
P := Point{hex2int(X), hex2int(Y)}
|
||||
|
||||
/* Q = k*P */
|
||||
{
|
||||
T := Point{hex2int("87d592bfdd24adb52147fea343db93e10d0585bc66d91e365c359973c0dc7067"), hex2int("a374e206cb7c8cd1074bdf9bf6ddea135f983aaa6475c9ab3bb4c38a0046541b")}
|
||||
input, _ := hex.DecodeString("14eb373700c3836404acd0820d9fa8dfa098d26177ca6e18b1c7f70c6af8fc18")
|
||||
|
||||
Q1, Q2 := curve.ScalarMult(P.X, P.Y, input)
|
||||
Q := Point{Q1, Q2}
|
||||
if Q.X.Cmp(T.X) != 0 || Q.Y.Cmp(T.Y) != 0 {
|
||||
t.Fatal("failure k*P")
|
||||
}
|
||||
t.Log("success k*P")
|
||||
}
|
||||
|
||||
/* Q = n*G = O */
|
||||
{
|
||||
Q1, Q2 := curve.ScalarMult(curve.G.X, curve.G.Y, curve.N.Bytes())
|
||||
Q := Point{Q1, Q2}
|
||||
if !curve.IsInfinity(Q) {
|
||||
t.Fatal("failure n*G = O")
|
||||
}
|
||||
t.Log("success n*G = O")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointScalarBaseMult(t *testing.T) {
|
||||
/* Sample Private Key */
|
||||
D := "18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725"
|
||||
/* Sample Corresponding Public Key */
|
||||
X := "50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"
|
||||
Y := "2cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6"
|
||||
|
||||
P := Point{hex2int(X), hex2int(Y)}
|
||||
|
||||
/* Q = d*G = P */
|
||||
|
||||
Q1, Q2 := curve.ScalarBaseMult(hex2int(D).Bytes())
|
||||
Q := Point{Q1, Q2}
|
||||
if P.X.Cmp(Q.X) != 0 || P.Y.Cmp(Q.Y) != 0 {
|
||||
t.Fatal("failure Q = d*G")
|
||||
}
|
||||
t.Log("success Q = d*G")
|
||||
|
||||
/* Q on curve */
|
||||
if !curve.IsOnCurve(Q.X, Q.Y) {
|
||||
t.Fatal("failure Q on curve")
|
||||
}
|
||||
t.Log("success Q on curve")
|
||||
|
||||
/* R = 0*G = O */
|
||||
R1, R2 := curve.ScalarBaseMult(big.NewInt(0).Bytes())
|
||||
R := Point{R1, R2}
|
||||
if !curve.IsInfinity(R) {
|
||||
t.Fatal("failure 0*G = O")
|
||||
}
|
||||
t.Log("success 0*G = O")
|
||||
}
|
||||
|
||||
func TestPointDecompress(t *testing.T) {
|
||||
/* Valid points */
|
||||
var validDecompressVectors = []Point{
|
||||
{hex2int("50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352"), hex2int("2cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6")},
|
||||
{hex2int("a83b8de893467d3a88d959c0eb4032d9ce3bf80f175d4d9e75892a3ebb8ab7e5"), hex2int("370f723328c24b7a97fe34063ba68f253fb08f8645d7c8b9a4ff98e3c29e7f0d")},
|
||||
{hex2int("f680556678e25084a82fa39e1b1dfd0944f7e69fddaa4e03ce934bd6b291dca0"), hex2int("52c10b721d34447e173721fb0151c68de1106badb089fb661523b8302a9097f5")},
|
||||
{hex2int("241febb8e23cbd77d664a18f66ad6240aaec6ecdc813b088d5b901b2e285131f"), hex2int("513378d9ff94f8d3d6c420bd13981df8cd50fd0fbd0cb5afabb3e66f2750026d")},
|
||||
}
|
||||
|
||||
for i := 0; i < len(validDecompressVectors); i++ {
|
||||
P, err := curve.Decompress(validDecompressVectors[i].X, validDecompressVectors[i].Y.Bit(0))
|
||||
if err != nil {
|
||||
t.Fatalf("failure decompress P, got error %v on index %d", err, i)
|
||||
}
|
||||
if P.X.Cmp(validDecompressVectors[i].X) != 0 || P.Y.Cmp(validDecompressVectors[i].Y) != 0 {
|
||||
t.Fatalf("failure decompress P, got mismatch on index %d", i)
|
||||
}
|
||||
}
|
||||
t.Log("success Decompress() on valid vectors")
|
||||
|
||||
/* Invalid points */
|
||||
var invalidDecompressVectors = []struct {
|
||||
X *big.Int
|
||||
YLsb uint
|
||||
}{
|
||||
{hex2int("c8e337cee51ae9af3c0ef923705a0cb1b76f7e8463b3d3060a1c8d795f9630fd"), 0},
|
||||
{hex2int("c8e337cee51ae9af3c0ef923705a0cb1b76f7e8463b3d3060a1c8d795f9630fd"), 1},
|
||||
}
|
||||
|
||||
for i := 0; i < len(invalidDecompressVectors); i++ {
|
||||
_, err := curve.Decompress(invalidDecompressVectors[i].X, invalidDecompressVectors[i].YLsb)
|
||||
if err == nil {
|
||||
t.Fatalf("failure decompress invalid P, got decompressed point on index %d", i)
|
||||
}
|
||||
}
|
||||
t.Log("success Decompress() on invalid vectors")
|
||||
}
|
Loading…
Reference in a new issue