173 lines
3.8 KiB
Go
173 lines
3.8 KiB
Go
package gostdlib
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/ed25519"
|
|
"errors"
|
|
|
|
"github.com/safing/jess/tools"
|
|
"github.com/safing/structures/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. This is currently ineffective, see known issues in the project's README.
|
|
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
|
|
}
|