package ecdh
import (
"bytes"
"crypto/internal/boring"
"crypto/internal/fips140/ecdh"
"crypto/internal/fips140only"
"errors"
"io"
)
type nistCurve struct {
name string
generate func (io .Reader ) (*ecdh .PrivateKey , error )
newPrivateKey func ([]byte ) (*ecdh .PrivateKey , error )
newPublicKey func (publicKey []byte ) (*ecdh .PublicKey , error )
sharedSecret func (*ecdh .PrivateKey , *ecdh .PublicKey ) (sharedSecret []byte , err error )
}
func (c *nistCurve ) String () string {
return c .name
}
func (c *nistCurve ) GenerateKey (rand io .Reader ) (*PrivateKey , error ) {
if boring .Enabled && rand == boring .RandReader {
key , bytes , err := boring .GenerateKeyECDH (c .name )
if err != nil {
return nil , err
}
pub , err := key .PublicKey ()
if err != nil {
return nil , err
}
k := &PrivateKey {
curve : c ,
privateKey : bytes ,
publicKey : &PublicKey {curve : c , publicKey : pub .Bytes (), boring : pub },
boring : key ,
}
return k , nil
}
if fips140only .Enabled && !fips140only .ApprovedRandomReader (rand ) {
return nil , errors .New ("crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-only mode" )
}
privateKey , err := c .generate (rand )
if err != nil {
return nil , err
}
k := &PrivateKey {
curve : c ,
privateKey : privateKey .Bytes (),
fips : privateKey ,
publicKey : &PublicKey {
curve : c ,
publicKey : privateKey .PublicKey ().Bytes (),
fips : privateKey .PublicKey (),
},
}
if boring .Enabled {
bk , err := boring .NewPrivateKeyECDH (c .name , k .privateKey )
if err != nil {
return nil , err
}
pub , err := bk .PublicKey ()
if err != nil {
return nil , err
}
k .boring = bk
k .publicKey .boring = pub
}
return k , nil
}
func (c *nistCurve ) NewPrivateKey (key []byte ) (*PrivateKey , error ) {
if boring .Enabled {
bk , err := boring .NewPrivateKeyECDH (c .name , key )
if err != nil {
return nil , errors .New ("crypto/ecdh: invalid private key" )
}
pub , err := bk .PublicKey ()
if err != nil {
return nil , errors .New ("crypto/ecdh: invalid private key" )
}
k := &PrivateKey {
curve : c ,
privateKey : bytes .Clone (key ),
publicKey : &PublicKey {curve : c , publicKey : pub .Bytes (), boring : pub },
boring : bk ,
}
return k , nil
}
fk , err := c .newPrivateKey (key )
if err != nil {
return nil , err
}
k := &PrivateKey {
curve : c ,
privateKey : bytes .Clone (key ),
fips : fk ,
publicKey : &PublicKey {
curve : c ,
publicKey : fk .PublicKey ().Bytes (),
fips : fk .PublicKey (),
},
}
return k , nil
}
func (c *nistCurve ) NewPublicKey (key []byte ) (*PublicKey , error ) {
if len (key ) == 0 || key [0 ] != 4 {
return nil , errors .New ("crypto/ecdh: invalid public key" )
}
k := &PublicKey {
curve : c ,
publicKey : bytes .Clone (key ),
}
if boring .Enabled {
bk , err := boring .NewPublicKeyECDH (c .name , k .publicKey )
if err != nil {
return nil , errors .New ("crypto/ecdh: invalid public key" )
}
k .boring = bk
} else {
fk , err := c .newPublicKey (key )
if err != nil {
return nil , err
}
k .fips = fk
}
return k , nil
}
func (c *nistCurve ) ecdh (local *PrivateKey , remote *PublicKey ) ([]byte , error ) {
if boring .Enabled {
return boring .ECDH (local .boring , remote .boring )
}
return c .sharedSecret (local .fips , remote .fips )
}
func P256 () Curve { return p256 }
var p256 = &nistCurve {
name : "P-256" ,
generate : func (r io .Reader ) (*ecdh .PrivateKey , error ) {
return ecdh .GenerateKey (ecdh .P256 (), r )
},
newPrivateKey : func (b []byte ) (*ecdh .PrivateKey , error ) {
return ecdh .NewPrivateKey (ecdh .P256 (), b )
},
newPublicKey : func (publicKey []byte ) (*ecdh .PublicKey , error ) {
return ecdh .NewPublicKey (ecdh .P256 (), publicKey )
},
sharedSecret : func (priv *ecdh .PrivateKey , pub *ecdh .PublicKey ) (sharedSecret []byte , err error ) {
return ecdh .ECDH (ecdh .P256 (), priv , pub )
},
}
func P384 () Curve { return p384 }
var p384 = &nistCurve {
name : "P-384" ,
generate : func (r io .Reader ) (*ecdh .PrivateKey , error ) {
return ecdh .GenerateKey (ecdh .P384 (), r )
},
newPrivateKey : func (b []byte ) (*ecdh .PrivateKey , error ) {
return ecdh .NewPrivateKey (ecdh .P384 (), b )
},
newPublicKey : func (publicKey []byte ) (*ecdh .PublicKey , error ) {
return ecdh .NewPublicKey (ecdh .P384 (), publicKey )
},
sharedSecret : func (priv *ecdh .PrivateKey , pub *ecdh .PublicKey ) (sharedSecret []byte , err error ) {
return ecdh .ECDH (ecdh .P384 (), priv , pub )
},
}
func P521 () Curve { return p521 }
var p521 = &nistCurve {
name : "P-521" ,
generate : func (r io .Reader ) (*ecdh .PrivateKey , error ) {
return ecdh .GenerateKey (ecdh .P521 (), r )
},
newPrivateKey : func (b []byte ) (*ecdh .PrivateKey , error ) {
return ecdh .NewPrivateKey (ecdh .P521 (), b )
},
newPublicKey : func (publicKey []byte ) (*ecdh .PublicKey , error ) {
return ecdh .NewPublicKey (ecdh .P521 (), publicKey )
},
sharedSecret : func (priv *ecdh .PrivateKey , pub *ecdh .PublicKey ) (sharedSecret []byte , err error ) {
return ecdh .ECDH (ecdh .P521 (), priv , pub )
},
}
The pages are generated with Golds v0.7.3 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .