173 lines
3.9 KiB
Go
173 lines
3.9 KiB
Go
package ecdh
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/elliptic"
|
|
"math/big"
|
|
|
|
"github.com/safing/jess/tools"
|
|
"github.com/safing/portbase/container"
|
|
|
|
"github.com/aead/ecdh"
|
|
)
|
|
|
|
var (
|
|
nistCurveInfo = &tools.ToolInfo{
|
|
Purpose: tools.PurposeKeyExchange,
|
|
Comment: "FIPS 186",
|
|
Author: "NIST, 2009",
|
|
}
|
|
)
|
|
|
|
func init() {
|
|
tools.Register(&tools.Tool{
|
|
Info: nistCurveInfo.With(&tools.ToolInfo{
|
|
Name: "ECDH-P224",
|
|
SecurityLevel: 112,
|
|
}),
|
|
Factory: func() tools.ToolLogic { return &NistCurve{curve: ecdh.Generic(elliptic.P224())} },
|
|
})
|
|
tools.Register(&tools.Tool{
|
|
Info: nistCurveInfo.With(&tools.ToolInfo{
|
|
Name: "ECDH-P256",
|
|
SecurityLevel: 128,
|
|
}),
|
|
Factory: func() tools.ToolLogic { return &NistCurve{curve: ecdh.Generic(elliptic.P256())} },
|
|
})
|
|
tools.Register(&tools.Tool{
|
|
Info: nistCurveInfo.With(&tools.ToolInfo{
|
|
Name: "ECDH-P384",
|
|
SecurityLevel: 192,
|
|
}),
|
|
Factory: func() tools.ToolLogic { return &NistCurve{curve: ecdh.Generic(elliptic.P384())} },
|
|
})
|
|
tools.Register(&tools.Tool{
|
|
Info: nistCurveInfo.With(&tools.ToolInfo{
|
|
Name: "ECDH-P521",
|
|
SecurityLevel: 256,
|
|
}),
|
|
Factory: func() tools.ToolLogic { return &NistCurve{curve: ecdh.Generic(elliptic.P521())} },
|
|
})
|
|
}
|
|
|
|
// NistCurve implements the cryptographic interface for ECDH key exchange with NIST curves.
|
|
type NistCurve struct {
|
|
tools.ToolLogicBase
|
|
curve ecdh.KeyExchange
|
|
}
|
|
|
|
// MakeSharedKey implements the ToolLogic interface.
|
|
func (ec *NistCurve) MakeSharedKey(local tools.SignetInt, remote tools.SignetInt) ([]byte, error) {
|
|
return ec.curve.ComputeSecret(local.PrivateKey(), remote.PublicKey()), nil
|
|
}
|
|
|
|
// LoadKey implements the ToolLogic interface.
|
|
func (ec *NistCurve) LoadKey(signet tools.SignetInt) error {
|
|
var pubKey crypto.PublicKey
|
|
var privKey crypto.PrivateKey
|
|
|
|
key, public := signet.GetStoredKey()
|
|
c := container.New(key)
|
|
|
|
// check serialization version
|
|
version, err := c.GetNextN8()
|
|
if err != nil || version != 1 {
|
|
return tools.ErrInvalidKey
|
|
}
|
|
|
|
// load public key
|
|
// extract public key data
|
|
pointXData, err := c.GetNextBlock()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pointYData, err := c.GetNextBlock()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// transform public key data
|
|
point := ecdh.Point{}
|
|
point.X = new(big.Int).SetBytes(pointXData)
|
|
point.Y = new(big.Int).SetBytes(pointYData)
|
|
pubKey = point
|
|
|
|
// check public key
|
|
err = ec.curve.Check(pubKey)
|
|
if err != nil {
|
|
return tools.ErrInvalidKey
|
|
}
|
|
|
|
// load private key
|
|
if !public {
|
|
privKey = c.CompileData()
|
|
}
|
|
|
|
signet.SetLoadedKeys(pubKey, privKey)
|
|
return nil
|
|
}
|
|
|
|
// StoreKey implements the ToolLogic interface.
|
|
func (ec *NistCurve) StoreKey(signet tools.SignetInt) error {
|
|
pubKey := signet.PublicKey()
|
|
privKey := signet.PrivateKey()
|
|
public := privKey == nil
|
|
|
|
// create storage with serialization version
|
|
c := container.New()
|
|
c.AppendNumber(1)
|
|
|
|
// store public key
|
|
curvePoint := pubKey.(ecdh.Point)
|
|
c.AppendAsBlock(curvePoint.X.Bytes())
|
|
c.AppendAsBlock(curvePoint.Y.Bytes())
|
|
|
|
// store private key
|
|
if !public {
|
|
c.Append(privKey.([]byte))
|
|
}
|
|
|
|
signet.SetStoredKey(c.CompileData(), public)
|
|
return nil
|
|
}
|
|
|
|
// GenerateKey implements the ToolLogic interface.
|
|
func (ec *NistCurve) GenerateKey(signet tools.SignetInt) error {
|
|
// define variable types for API security
|
|
var pubKey crypto.PublicKey
|
|
var privKey crypto.PrivateKey
|
|
var err error
|
|
|
|
// generate keys
|
|
privKey, pubKey, err = ec.curve.GenerateKey(ec.Helper().Random())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
signet.SetLoadedKeys(pubKey, privKey)
|
|
return nil
|
|
}
|
|
|
|
// BurnKey implements the ToolLogic interface.
|
|
func (ec *NistCurve) BurnKey(signet tools.SignetInt) error {
|
|
pubKey := signet.PublicKey()
|
|
privKey := signet.PrivateKey()
|
|
|
|
// burn public key
|
|
if pubKey != nil {
|
|
point, ok := pubKey.(*ecdh.Point)
|
|
if ok {
|
|
point.X.Set(big.NewInt(0))
|
|
point.Y.Set(big.NewInt(0))
|
|
}
|
|
}
|
|
|
|
// burn private key
|
|
if privKey != nil {
|
|
data, ok := privKey.([]byte)
|
|
if ok {
|
|
ec.Helper().Burn(data)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|