good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
open
bor
Commits
c24018e2
Commit
c24018e2
authored
Dec 9, 2014
by
Jeffrey Wilcke
Browse files
Options
Downloads
Patches
Plain Diff
Added S256 curve
parent
df5157c0
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
crypto/curve.go
+363
-0
363 additions, 0 deletions
crypto/curve.go
with
363 additions
and
0 deletions
crypto/curve.go
0 → 100644
+
363
−
0
View file @
c24018e2
package
crypto
// Copyright 2010 The Go Authors. All rights reserved.
// Copyright 2011 ThePiachu. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package bitelliptic implements several Koblitz elliptic curves over prime
// fields.
// 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"
"io"
"math/big"
"sync"
)
// A BitCurve represents a Koblitz Curve with a=0.
// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
type
BitCurve
struct
{
P
*
big
.
Int
// the order of the underlying field
N
*
big
.
Int
// the order of the base point
B
*
big
.
Int
// the constant of the BitCurve equation
Gx
,
Gy
*
big
.
Int
// (x,y) of the base point
BitSize
int
// the size of the underlying field
}
func
(
BitCurve
*
BitCurve
)
Params
()
*
elliptic
.
CurveParams
{
return
&
elliptic
.
CurveParams
{
BitCurve
.
P
,
BitCurve
.
N
,
BitCurve
.
B
,
BitCurve
.
Gx
,
BitCurve
.
Gy
,
BitCurve
.
BitSize
}
}
// IsOnBitCurve returns true if the given (x,y) lies on the BitCurve.
func
(
BitCurve
*
BitCurve
)
IsOnCurve
(
x
,
y
*
big
.
Int
)
bool
{
// y² = x³ + b
y2
:=
new
(
big
.
Int
)
.
Mul
(
y
,
y
)
//y²
y2
.
Mod
(
y2
,
BitCurve
.
P
)
//y²%P
x3
:=
new
(
big
.
Int
)
.
Mul
(
x
,
x
)
//x²
x3
.
Mul
(
x3
,
x
)
//x³
x3
.
Add
(
x3
,
BitCurve
.
B
)
//x³+B
x3
.
Mod
(
x3
,
BitCurve
.
P
)
//(x³+B)%P
return
x3
.
Cmp
(
y2
)
==
0
}
//TODO: double check if the function is okay
// affineFromJacobian reverses the Jacobian transform. See the comment at the
// top of the file.
func
(
BitCurve
*
BitCurve
)
affineFromJacobian
(
x
,
y
,
z
*
big
.
Int
)
(
xOut
,
yOut
*
big
.
Int
)
{
zinv
:=
new
(
big
.
Int
)
.
ModInverse
(
z
,
BitCurve
.
P
)
zinvsq
:=
new
(
big
.
Int
)
.
Mul
(
zinv
,
zinv
)
xOut
=
new
(
big
.
Int
)
.
Mul
(
x
,
zinvsq
)
xOut
.
Mod
(
xOut
,
BitCurve
.
P
)
zinvsq
.
Mul
(
zinvsq
,
zinv
)
yOut
=
new
(
big
.
Int
)
.
Mul
(
y
,
zinvsq
)
yOut
.
Mod
(
yOut
,
BitCurve
.
P
)
return
}
// Add returns the sum of (x1,y1) and (x2,y2)
func
(
BitCurve
*
BitCurve
)
Add
(
x1
,
y1
,
x2
,
y2
*
big
.
Int
)
(
*
big
.
Int
,
*
big
.
Int
)
{
z
:=
new
(
big
.
Int
)
.
SetInt64
(
1
)
return
BitCurve
.
affineFromJacobian
(
BitCurve
.
addJacobian
(
x1
,
y1
,
z
,
x2
,
y2
,
z
))
}
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
// (x2, y2, z2) and returns their sum, also in Jacobian form.
func
(
BitCurve
*
BitCurve
)
addJacobian
(
x1
,
y1
,
z1
,
x2
,
y2
,
z2
*
big
.
Int
)
(
*
big
.
Int
,
*
big
.
Int
,
*
big
.
Int
)
{
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
z1z1
:=
new
(
big
.
Int
)
.
Mul
(
z1
,
z1
)
z1z1
.
Mod
(
z1z1
,
BitCurve
.
P
)
z2z2
:=
new
(
big
.
Int
)
.
Mul
(
z2
,
z2
)
z2z2
.
Mod
(
z2z2
,
BitCurve
.
P
)
u1
:=
new
(
big
.
Int
)
.
Mul
(
x1
,
z2z2
)
u1
.
Mod
(
u1
,
BitCurve
.
P
)
u2
:=
new
(
big
.
Int
)
.
Mul
(
x2
,
z1z1
)
u2
.
Mod
(
u2
,
BitCurve
.
P
)
h
:=
new
(
big
.
Int
)
.
Sub
(
u2
,
u1
)
if
h
.
Sign
()
==
-
1
{
h
.
Add
(
h
,
BitCurve
.
P
)
}
i
:=
new
(
big
.
Int
)
.
Lsh
(
h
,
1
)
i
.
Mul
(
i
,
i
)
j
:=
new
(
big
.
Int
)
.
Mul
(
h
,
i
)
s1
:=
new
(
big
.
Int
)
.
Mul
(
y1
,
z2
)
s1
.
Mul
(
s1
,
z2z2
)
s1
.
Mod
(
s1
,
BitCurve
.
P
)
s2
:=
new
(
big
.
Int
)
.
Mul
(
y2
,
z1
)
s2
.
Mul
(
s2
,
z1z1
)
s2
.
Mod
(
s2
,
BitCurve
.
P
)
r
:=
new
(
big
.
Int
)
.
Sub
(
s2
,
s1
)
if
r
.
Sign
()
==
-
1
{
r
.
Add
(
r
,
BitCurve
.
P
)
}
r
.
Lsh
(
r
,
1
)
v
:=
new
(
big
.
Int
)
.
Mul
(
u1
,
i
)
x3
:=
new
(
big
.
Int
)
.
Set
(
r
)
x3
.
Mul
(
x3
,
x3
)
x3
.
Sub
(
x3
,
j
)
x3
.
Sub
(
x3
,
v
)
x3
.
Sub
(
x3
,
v
)
x3
.
Mod
(
x3
,
BitCurve
.
P
)
y3
:=
new
(
big
.
Int
)
.
Set
(
r
)
v
.
Sub
(
v
,
x3
)
y3
.
Mul
(
y3
,
v
)
s1
.
Mul
(
s1
,
j
)
s1
.
Lsh
(
s1
,
1
)
y3
.
Sub
(
y3
,
s1
)
y3
.
Mod
(
y3
,
BitCurve
.
P
)
z3
:=
new
(
big
.
Int
)
.
Add
(
z1
,
z2
)
z3
.
Mul
(
z3
,
z3
)
z3
.
Sub
(
z3
,
z1z1
)
if
z3
.
Sign
()
==
-
1
{
z3
.
Add
(
z3
,
BitCurve
.
P
)
}
z3
.
Sub
(
z3
,
z2z2
)
if
z3
.
Sign
()
==
-
1
{
z3
.
Add
(
z3
,
BitCurve
.
P
)
}
z3
.
Mul
(
z3
,
h
)
z3
.
Mod
(
z3
,
BitCurve
.
P
)
return
x3
,
y3
,
z3
}
// Double returns 2*(x,y)
func
(
BitCurve
*
BitCurve
)
Double
(
x1
,
y1
*
big
.
Int
)
(
*
big
.
Int
,
*
big
.
Int
)
{
z1
:=
new
(
big
.
Int
)
.
SetInt64
(
1
)
return
BitCurve
.
affineFromJacobian
(
BitCurve
.
doubleJacobian
(
x1
,
y1
,
z1
))
}
// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
// returns its double, also in Jacobian form.
func
(
BitCurve
*
BitCurve
)
doubleJacobian
(
x
,
y
,
z
*
big
.
Int
)
(
*
big
.
Int
,
*
big
.
Int
,
*
big
.
Int
)
{
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
a
:=
new
(
big
.
Int
)
.
Mul
(
x
,
x
)
//X1²
b
:=
new
(
big
.
Int
)
.
Mul
(
y
,
y
)
//Y1²
c
:=
new
(
big
.
Int
)
.
Mul
(
b
,
b
)
//B²
d
:=
new
(
big
.
Int
)
.
Add
(
x
,
b
)
//X1+B
d
.
Mul
(
d
,
d
)
//(X1+B)²
d
.
Sub
(
d
,
a
)
//(X1+B)²-A
d
.
Sub
(
d
,
c
)
//(X1+B)²-A-C
d
.
Mul
(
d
,
big
.
NewInt
(
2
))
//2*((X1+B)²-A-C)
e
:=
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
3
),
a
)
//3*A
f
:=
new
(
big
.
Int
)
.
Mul
(
e
,
e
)
//E²
x3
:=
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
2
),
d
)
//2*D
x3
.
Sub
(
f
,
x3
)
//F-2*D
x3
.
Mod
(
x3
,
BitCurve
.
P
)
y3
:=
new
(
big
.
Int
)
.
Sub
(
d
,
x3
)
//D-X3
y3
.
Mul
(
e
,
y3
)
//E*(D-X3)
y3
.
Sub
(
y3
,
new
(
big
.
Int
)
.
Mul
(
big
.
NewInt
(
8
),
c
))
//E*(D-X3)-8*C
y3
.
Mod
(
y3
,
BitCurve
.
P
)
z3
:=
new
(
big
.
Int
)
.
Mul
(
y
,
z
)
//Y1*Z1
z3
.
Mul
(
big
.
NewInt
(
2
),
z3
)
//3*Y1*Z1
z3
.
Mod
(
z3
,
BitCurve
.
P
)
return
x3
,
y3
,
z3
}
//TODO: double check if it is okay
// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
func
(
BitCurve
*
BitCurve
)
ScalarMult
(
Bx
,
By
*
big
.
Int
,
k
[]
byte
)
(
*
big
.
Int
,
*
big
.
Int
)
{
// We have a slight problem in that the identity of the group (the
// point at infinity) cannot be represented in (x, y) form on a finite
// machine. Thus the standard add/double algorithm has to be tweaked
// slightly: our initial state is not the identity, but x, and we
// ignore the first true bit in |k|. If we don't find any true bits in
// |k|, then we return nil, nil, because we cannot return the identity
// element.
Bz
:=
new
(
big
.
Int
)
.
SetInt64
(
1
)
x
:=
Bx
y
:=
By
z
:=
Bz
seenFirstTrue
:=
false
for
_
,
byte
:=
range
k
{
for
bitNum
:=
0
;
bitNum
<
8
;
bitNum
++
{
if
seenFirstTrue
{
x
,
y
,
z
=
BitCurve
.
doubleJacobian
(
x
,
y
,
z
)
}
if
byte
&
0x80
==
0x80
{
if
!
seenFirstTrue
{
seenFirstTrue
=
true
}
else
{
x
,
y
,
z
=
BitCurve
.
addJacobian
(
Bx
,
By
,
Bz
,
x
,
y
,
z
)
}
}
byte
<<=
1
}
}
if
!
seenFirstTrue
{
return
nil
,
nil
}
return
BitCurve
.
affineFromJacobian
(
x
,
y
,
z
)
}
// ScalarBaseMult returns k*G, where G is the base point of the group and k is
// an integer in big-endian form.
func
(
BitCurve
*
BitCurve
)
ScalarBaseMult
(
k
[]
byte
)
(
*
big
.
Int
,
*
big
.
Int
)
{
return
BitCurve
.
ScalarMult
(
BitCurve
.
Gx
,
BitCurve
.
Gy
,
k
)
}
var
mask
=
[]
byte
{
0xff
,
0x1
,
0x3
,
0x7
,
0xf
,
0x1f
,
0x3f
,
0x7f
}
//TODO: double check if it is okay
// GenerateKey returns a public/private key pair. The private key is generated
// using the given reader, which must return random data.
func
(
BitCurve
*
BitCurve
)
GenerateKey
(
rand
io
.
Reader
)
(
priv
[]
byte
,
x
,
y
*
big
.
Int
,
err
error
)
{
byteLen
:=
(
BitCurve
.
BitSize
+
7
)
>>
3
priv
=
make
([]
byte
,
byteLen
)
for
x
==
nil
{
_
,
err
=
io
.
ReadFull
(
rand
,
priv
)
if
err
!=
nil
{
return
}
// We have to mask off any excess bits in the case that the size of the
// underlying field is not a whole number of bytes.
priv
[
0
]
&=
mask
[
BitCurve
.
BitSize
%
8
]
// This is because, in tests, rand will return all zeros and we don't
// want to get the point at infinity and loop forever.
priv
[
1
]
^=
0x42
x
,
y
=
BitCurve
.
ScalarBaseMult
(
priv
)
}
return
}
// Marshal converts a point into the form specified in section 4.3.6 of ANSI
// X9.62.
func
(
BitCurve
*
BitCurve
)
Marshal
(
x
,
y
*
big
.
Int
)
[]
byte
{
byteLen
:=
(
BitCurve
.
BitSize
+
7
)
>>
3
ret
:=
make
([]
byte
,
1
+
2
*
byteLen
)
ret
[
0
]
=
4
// uncompressed point
xBytes
:=
x
.
Bytes
()
copy
(
ret
[
1
+
byteLen
-
len
(
xBytes
)
:
],
xBytes
)
yBytes
:=
y
.
Bytes
()
copy
(
ret
[
1
+
2
*
byteLen
-
len
(
yBytes
)
:
],
yBytes
)
return
ret
}
// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
// error, x = nil.
func
(
BitCurve
*
BitCurve
)
Unmarshal
(
data
[]
byte
)
(
x
,
y
*
big
.
Int
)
{
byteLen
:=
(
BitCurve
.
BitSize
+
7
)
>>
3
if
len
(
data
)
!=
1
+
2
*
byteLen
{
return
}
if
data
[
0
]
!=
4
{
// uncompressed form
return
}
x
=
new
(
big
.
Int
)
.
SetBytes
(
data
[
1
:
1
+
byteLen
])
y
=
new
(
big
.
Int
)
.
SetBytes
(
data
[
1
+
byteLen
:
])
return
}
//curve parameters taken from:
//http://www.secg.org/collateral/sec2_final.pdf
var
initonce
sync
.
Once
var
ecp160k1
*
BitCurve
var
ecp192k1
*
BitCurve
var
ecp224k1
*
BitCurve
var
ecp256k1
*
BitCurve
func
initAll
()
{
initS160
()
initS192
()
initS224
()
initS256
()
}
func
initS160
()
{
// See SEC 2 section 2.4.1
ecp160k1
=
new
(
BitCurve
)
ecp160k1
.
P
,
_
=
new
(
big
.
Int
)
.
SetString
(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"
,
16
)
ecp160k1
.
N
,
_
=
new
(
big
.
Int
)
.
SetString
(
"0100000000000000000001B8FA16DFAB9ACA16B6B3"
,
16
)
ecp160k1
.
B
,
_
=
new
(
big
.
Int
)
.
SetString
(
"0000000000000000000000000000000000000007"
,
16
)
ecp160k1
.
Gx
,
_
=
new
(
big
.
Int
)
.
SetString
(
"3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
,
16
)
ecp160k1
.
Gy
,
_
=
new
(
big
.
Int
)
.
SetString
(
"938CF935318FDCED6BC28286531733C3F03C4FEE"
,
16
)
ecp160k1
.
BitSize
=
160
}
func
initS192
()
{
// See SEC 2 section 2.5.1
ecp192k1
=
new
(
BitCurve
)
ecp192k1
.
P
,
_
=
new
(
big
.
Int
)
.
SetString
(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"
,
16
)
ecp192k1
.
N
,
_
=
new
(
big
.
Int
)
.
SetString
(
"FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"
,
16
)
ecp192k1
.
B
,
_
=
new
(
big
.
Int
)
.
SetString
(
"000000000000000000000000000000000000000000000003"
,
16
)
ecp192k1
.
Gx
,
_
=
new
(
big
.
Int
)
.
SetString
(
"DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
,
16
)
ecp192k1
.
Gy
,
_
=
new
(
big
.
Int
)
.
SetString
(
"9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"
,
16
)
ecp192k1
.
BitSize
=
192
}
func
initS224
()
{
// See SEC 2 section 2.6.1
ecp224k1
=
new
(
BitCurve
)
ecp224k1
.
P
,
_
=
new
(
big
.
Int
)
.
SetString
(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D"
,
16
)
ecp224k1
.
N
,
_
=
new
(
big
.
Int
)
.
SetString
(
"010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"
,
16
)
ecp224k1
.
B
,
_
=
new
(
big
.
Int
)
.
SetString
(
"00000000000000000000000000000000000000000000000000000005"
,
16
)
ecp224k1
.
Gx
,
_
=
new
(
big
.
Int
)
.
SetString
(
"A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
,
16
)
ecp224k1
.
Gy
,
_
=
new
(
big
.
Int
)
.
SetString
(
"7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"
,
16
)
ecp224k1
.
BitSize
=
224
}
func
initS256
()
{
// See SEC 2 section 2.7.1
ecp256k1
=
new
(
BitCurve
)
ecp256k1
.
P
,
_
=
new
(
big
.
Int
)
.
SetString
(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"
,
16
)
ecp256k1
.
N
,
_
=
new
(
big
.
Int
)
.
SetString
(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
,
16
)
ecp256k1
.
B
,
_
=
new
(
big
.
Int
)
.
SetString
(
"0000000000000000000000000000000000000000000000000000000000000007"
,
16
)
ecp256k1
.
Gx
,
_
=
new
(
big
.
Int
)
.
SetString
(
"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
,
16
)
ecp256k1
.
Gy
,
_
=
new
(
big
.
Int
)
.
SetString
(
"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"
,
16
)
ecp256k1
.
BitSize
=
256
}
// S160 returns a BitCurve which implements secp160k1 (see SEC 2 section 2.4.1)
func
S160
()
*
BitCurve
{
initonce
.
Do
(
initAll
)
return
ecp160k1
}
// S192 returns a BitCurve which implements secp192k1 (see SEC 2 section 2.5.1)
func
S192
()
*
BitCurve
{
initonce
.
Do
(
initAll
)
return
ecp192k1
}
// S224 returns a BitCurve which implements secp224k1 (see SEC 2 section 2.6.1)
func
S224
()
*
BitCurve
{
initonce
.
Do
(
initAll
)
return
ecp224k1
}
// S256 returns a BitCurve which implements secp256k1 (see SEC 2 section 2.7.1)
func
S256
()
*
BitCurve
{
initonce
.
Do
(
initAll
)
return
ecp256k1
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment