mirror of
https://github.com/golang/go
synced 2024-11-24 23:47:55 -07:00
crypto/elliptic: add serialisation and key pair generation.
This is a prerequisite to ECDHE support in crypto/tls. R=r, rsc CC=golang-dev https://golang.org/cl/3685043
This commit is contained in:
parent
b3e8fdce8d
commit
1e3b9524d2
@ -15,15 +15,18 @@ package elliptic
|
||||
|
||||
import (
|
||||
"big"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A Curve represents a short-form Weierstrass curve with a=-3.
|
||||
// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
|
||||
type Curve struct {
|
||||
P *big.Int // the order of the underlying field
|
||||
B *big.Int // the constant of the curve equation
|
||||
Gx, Gy *big.Int // (x,y) of the base point
|
||||
P *big.Int // the order of the underlying field
|
||||
B *big.Int // the constant of the curve equation
|
||||
Gx, Gy *big.Int // (x,y) of the base point
|
||||
BitSize int // the size of the underlying field
|
||||
}
|
||||
|
||||
// IsOnCurve returns true if the given (x,y) lies on the curve.
|
||||
@ -241,6 +244,60 @@ func (curve *Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
|
||||
return curve.ScalarMult(curve.Gx, curve.Gy, k)
|
||||
}
|
||||
|
||||
var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
|
||||
|
||||
// GenerateKey returns a public/private key pair. The private key is generated
|
||||
// using the given reader, which must return random data.
|
||||
func (curve *Curve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err os.Error) {
|
||||
byteLen := (curve.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[curve.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 = curve.ScalarBaseMult(priv)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Marshal converts a point into the form specified in section 4.3.6 of ANSI
|
||||
// X9.62.
|
||||
func (curve *Curve) Marshal(x, y *big.Int) []byte {
|
||||
byteLen := (curve.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 (curve *Curve) Unmarshal(data []byte) (x, y *big.Int) {
|
||||
byteLen := (curve.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
|
||||
}
|
||||
|
||||
var initonce sync.Once
|
||||
var p224 *Curve
|
||||
var p256 *Curve
|
||||
@ -261,6 +318,7 @@ func initP224() {
|
||||
p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16)
|
||||
p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16)
|
||||
p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16)
|
||||
p224.BitSize = 224
|
||||
}
|
||||
|
||||
func initP256() {
|
||||
@ -270,6 +328,7 @@ func initP256() {
|
||||
p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
|
||||
p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
|
||||
p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
|
||||
p256.BitSize = 256
|
||||
}
|
||||
|
||||
func initP384() {
|
||||
@ -279,6 +338,7 @@ func initP384() {
|
||||
p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16)
|
||||
p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16)
|
||||
p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16)
|
||||
p384.BitSize = 384
|
||||
}
|
||||
|
||||
func initP521() {
|
||||
@ -288,6 +348,7 @@ func initP521() {
|
||||
p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16)
|
||||
p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16)
|
||||
p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16)
|
||||
p521.BitSize = 521
|
||||
}
|
||||
|
||||
// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2)
|
||||
|
@ -6,6 +6,7 @@ package elliptic
|
||||
|
||||
import (
|
||||
"big"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
@ -309,3 +310,22 @@ func BenchmarkBaseMult(b *testing.B) {
|
||||
p224.ScalarBaseMult(k.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshal(t *testing.T) {
|
||||
p224 := P224()
|
||||
_, x, y, err := p224.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
serialised := p224.Marshal(x, y)
|
||||
xx, yy := p224.Unmarshal(serialised)
|
||||
if xx == nil {
|
||||
t.Error("failed to unmarshal")
|
||||
return
|
||||
}
|
||||
if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 {
|
||||
t.Error("unmarshal returned different values")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user