Skip to content

Commit

Permalink
wip: key sign
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Nov 28, 2023
1 parent 3ae04c5 commit e868792
Showing 1 changed file with 107 additions and 0 deletions.
107 changes: 107 additions & 0 deletions core/commands/keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"crypto/ed25519"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io"
"os"
Expand All @@ -24,6 +25,7 @@ import (
migrations "github.com/ipfs/kubo/repo/fsrepo/migrations"
"github.com/libp2p/go-libp2p/core/crypto"
peer "github.com/libp2p/go-libp2p/core/peer"
mbase "github.com/multiformats/go-multibase"
)

var KeyCmd = &cmds.Command{
Expand Down Expand Up @@ -51,6 +53,8 @@ publish'.
"rename": keyRenameCmd,
"rm": keyRmCmd,
"rotate": keyRotateCmd,
"sign": keySignCmd,
"verify": keyVerifyCmd,
},
}

Expand Down Expand Up @@ -688,6 +692,109 @@ func keyOutputListEncoders() cmds.EncoderFunc {
})
}

type KeySignOutput struct {
Key string
Signature string
}

var keySignCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Generates a signature for the given data with a specified key.",
},
Options: []cmds.Option{
cmds.StringOption("key", "k", "The name of the key to use for signing."),
cmds.StringOption("base", "b", "The multibase encoding of the output.").WithDefault("base64url"),
},
Arguments: []cmds.Argument{
cmds.FileArg("data", true, false, "The data to sign.").EnableStdin(),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
var sk crypto.PrivKey

name, _ := req.Options["key"].(string)
if name == "" || name == "self" {
node, err := cmdenv.GetNode(env)
if err != nil {
return err
}

// TODO: Do we want to allow this or only other keys?
sk = node.PrivateKey
} else {
cfgRoot, err := cmdenv.GetConfigRoot(env)
if err != nil {
return err
}

// Signing is read-only: safe to read key without acquiring repo lock
// (this makes sign work when ipfs daemon is already running)
ksp := filepath.Join(cfgRoot, "keystore")
ks, err := keystore.NewFSKeystore(ksp)
if err != nil {
return err
}

sk, err = ks.Get(name)
if err != nil {
return fmt.Errorf("key with name '%s' doesn't exist", name)
}
}

pid, err := peer.IDFromPrivateKey(sk)
if err != nil {
return err
}

// Read given data.
file, err := cmdenv.GetFileArg(req.Files.Entries())
if err != nil {
return err
}
defer file.Close()

data, err := io.ReadAll(file)
if err != nil {
return err
}

// Sign it!
sig, err := sk.Sign(data)
if err != nil {
return err
}

encoder, err := mbase.EncoderByName("base64url")
if err != nil {
return err
}

res.Emit(&KeySignOutput{
Key: peer.ToCid(pid).String(),
Signature: encoder.Encode(sig),
})

return nil
},
Type: KeySignOutput{},
}

var keyVerifyCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Verify that the given data and signature match.",
},
Options: []cmds.Option{
cmds.StringOption("key", "k", "The name of the key to use for signing."),
cmds.StringOption("signature", "s", "Multibase-encoded signature to verify."),
cmds.StringOption("base", "b", "The multibase encoding of the output.").WithDefault("base64url"),
},
Arguments: []cmds.Argument{
cmds.FileArg("data", true, false, "The data to verify against the given signature."),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
return errors.New("TODO")
},
}

// DaemonNotRunning checks to see if the ipfs repo is locked, indicating that
// the daemon is running, and returns and error if the daemon is running.
func DaemonNotRunning(req *cmds.Request, env cmds.Environment) error {
Expand Down

0 comments on commit e868792

Please sign in to comment.