safing-jess/tools/gostdlib/ed25519.go
2020-01-13 00:15:58 +01:00

173 lines
3.7 KiB
Go

package gostdlib
import (
"crypto"
"crypto/ed25519"
"errors"
"github.com/safing/jess/tools"
"github.com/safing/portbase/container"
)
func init() {
tools.Register(&tools.Tool{
Info: &tools.ToolInfo{
Name: "Ed25519",
Purpose: tools.PurposeSigning,
Options: []uint8{tools.OptionNeedsManagedHasher},
SecurityLevel: 128,
Comment: "",
Author: "Daniel J. Bernstein, 2011",
},
Factory: func() tools.ToolLogic { return &Ed25519{} },
})
}
// Ed25519 implements the cryptographic interface for Ed25519 signatures.
type Ed25519 struct {
tools.ToolLogicBase
}
// Sign implements the ToolLogic interface.
func (ed *Ed25519) Sign(data, associatedData []byte, signet tools.SignetInt) ([]byte, error) {
edPrivKey, ok := signet.PrivateKey().(ed25519.PrivateKey)
if !ok {
return nil, tools.ErrInvalidKey
}
if len(edPrivKey) != ed25519.PrivateKeySize {
return nil, tools.ErrInvalidKey
}
hashsum, err := ed.ManagedHashSum()
if err != nil {
return nil, err
}
return ed25519.Sign(edPrivKey, hashsum), nil
}
// Verify implements the ToolLogic interface.
func (ed *Ed25519) Verify(data, associatedData, signature []byte, signet tools.SignetInt) error {
edPubKey, ok := signet.PublicKey().(ed25519.PublicKey)
if !ok {
return tools.ErrInvalidKey
}
if len(edPubKey) != ed25519.PublicKeySize {
return tools.ErrInvalidKey
}
hashsum, err := ed.ManagedHashSum()
if err != nil {
return err
}
if !ed25519.Verify(edPubKey, hashsum, signature) {
return errors.New("signature invalid")
}
return nil
}
// LoadKey implements the ToolLogic interface.
func (ed *Ed25519) LoadKey(signet tools.SignetInt) error {
var pubKey crypto.PublicKey
var privKey ed25519.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
data := c.CompileData()
// assign and check data
if public {
if len(data) != ed25519.PublicKeySize {
return tools.ErrInvalidKey
}
pubKey = ed25519.PublicKey(data)
} else {
if len(data) != ed25519.PrivateKeySize {
return tools.ErrInvalidKey
}
privKey = ed25519.PrivateKey(data)
pubKey = privKey.Public()
}
signet.SetLoadedKeys(pubKey, privKey)
return nil
}
// StoreKey implements the ToolLogic interface.
func (ed *Ed25519) 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 keys
if public {
pubKeyData, ok := pubKey.(ed25519.PublicKey)
if !ok {
return tools.ErrInvalidKey
}
c.Append(pubKeyData)
} else {
privKeyData, ok := privKey.(ed25519.PrivateKey)
if !ok {
return tools.ErrInvalidKey
}
c.Append(privKeyData)
}
signet.SetStoredKey(c.CompileData(), public)
return nil
}
// GenerateKey implements the ToolLogic interface.
func (ed *Ed25519) GenerateKey(signet tools.SignetInt) error {
// define variable types for API security
var pubKey ed25519.PublicKey
var privKey ed25519.PrivateKey
var err error
// generate keys
pubKey, privKey, err = ed25519.GenerateKey(ed.Helper().Random())
if err != nil {
return err
}
signet.SetLoadedKeys(pubKey, privKey)
return nil
}
// BurnKey implements the ToolLogic interface.
func (ed *Ed25519) BurnKey(signet tools.SignetInt) error {
pubKey := signet.PublicKey()
privKey := signet.PrivateKey()
// burn public key
if pubKey != nil {
data, ok := pubKey.([]byte)
if ok {
ed.Helper().Burn(data)
}
}
// burn private key
if privKey != nil {
data, ok := privKey.([]byte)
if ok {
ed.Helper().Burn(data)
}
}
return nil
}