Skip to content

Commit

Permalink
fix SMC get key via http GET
Browse files Browse the repository at this point in the history
  • Loading branch information
jbsv committed Mar 11, 2024
1 parent 1bca58c commit 2afce36
Show file tree
Hide file tree
Showing 6 changed files with 358 additions and 4 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

gradle.properties

chaincli
smccli
*/chaincli
*/smccli

profile.cov
report.json
Expand Down
2 changes: 1 addition & 1 deletion server/scripts/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ tmux send-keys -t ${S}:smc.0 "./publish_roster.sh" C-m
tmux select-pane -t ${S}:smc.0
tmux send-keys -t ${S}:smc.0 "# TMUX MINI CHEAT SHEET" C-m
tmux send-keys -t ${S}:smc.0 "# Use 'tmux lscm' to list tmux commands" C-m
tmux send-keys -t ${S}:smc.0 "# Use 'Ctrl+B N (or P)' for next (previous) window" C-m
tmux send-keys -t ${S}:smc.0 "# Use 'Ctrl+B N (or P)' for next (or previous) window" C-m
tmux send-keys -t ${S}:smc.0 "# Use 'Ctrl+B <arrow>' to select pane" C-m
tmux send-keys -t ${S}:smc.0 "# './teardown.sh' to clean this tmux session" C-m
tmux attach -t ${S}
3 changes: 2 additions & 1 deletion server/scripts/start_chain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ do
echo -e "${GREEN}creating node #${i} on port ${p}${NC}"
# session s, window 0, panes 1 to N
tmux send-keys -t ${S}:${W}.${i} "LLVL=${L} LOGF=./${W}${i}.log chaincli --config /tmp/${W}${i} start --listen tcp://127.0.0.1:${p}" C-m
sleep 0.5
sleep 1
i=$((i + 1));
done

Expand All @@ -71,6 +71,7 @@ while [ ${i} -le ${N} ]
do
echo -e "joining node ${i} on master pane ${MASTERPANE}"
tmux send-keys -t "${MASTERPANE}" "chaincli --config /tmp/${W}${i} minogrpc join --address //127.0.0.1:${p} $(chaincli --config /tmp/${W}1 minogrpc token)" C-m
sleep 1
i=$((i + 1));
done

Expand Down
2 changes: 2 additions & 0 deletions server/scripts/start_smc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ i=2;
p=$((P + 1))
while [ ${i} -le ${N} ]
do
sleep 1
tmux send-keys -t "${MASTERPANE}" "smccli --config /tmp/${W}${i} minogrpc join --address //127.0.0.1:${p} $(smccli --config /tmp/${W}1 minogrpc token)" C-m
sleep 1
i=$((i + 1));
done

Expand Down
264 changes: 264 additions & 0 deletions server/smc/smccli/web/action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
package web

import (
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"strings"

"github.com/gorilla/mux"
"github.com/rs/zerolog/log"
"go.dedis.ch/dela"
"go.dedis.ch/dela/cli/node"
"go.dedis.ch/dela/dkg"
"go.dedis.ch/dela/mino/proxy"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/kyber/v3/suites"

"golang.org/x/xerrors"
)

// suite is the Kyber suite for Pedersen.
var suite = suites.MustFind("Ed25519")

const separator = ":"
const malformedEncoded = "malformed encoded: %s"

// RegisterAction is an action to register the HTTP handlers
//
// - implements node.ActionTemplate
type RegisterAction struct{}

// Execute implements node.ActionTemplate. It registers the handlers using the
// default proxy from the injector.
func (a *RegisterAction) Execute(ctx node.Context) error {
var p proxy.Proxy
err := ctx.Injector.Resolve(&p)
if err != nil {
return xerrors.Errorf("failed to resolve proxy: %v", err)
}

router := mux.NewRouter()

pk := &pubKeyHandler{ctx}
router.HandleFunc("/smc/pubkey", pk.ServeHTTP).Methods("GET")

re := &reencryptHandler{ctx}
router.HandleFunc("/smc/reencrypt", re.ServeHTTP).Methods("POST")

router.NotFoundHandler = http.HandlerFunc(notFoundHandler)
router.MethodNotAllowedHandler = http.HandlerFunc(notAllowedHandler)

p.RegisterHandler("/smc/", router.ServeHTTP)

dela.Logger.Info().Msg("proxy handlers registered")

return nil
}

type pubKeyHandler struct {
ctx node.Context
}

func (h *pubKeyHandler) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
var a dkg.Actor
err := h.ctx.Injector.Resolve(&a)
if err != nil {
http.Error(w, fmt.Sprintf("failed to resolve DKG actor: %v", err),
http.StatusInternalServerError)
return
}

pk, err := a.GetPublicKey()
if err != nil {
http.Error(w, fmt.Sprintf("failed retrieving public key: %v", err),
http.StatusInternalServerError)
return
}

b, err := pk.MarshalBinary()
if err != nil {
http.Error(w, fmt.Sprintf("failed to marshal public key: %v", err),
http.StatusInternalServerError)
return
}

encoder := json.NewEncoder(w)
err = encoder.Encode(b)
if err != nil {
http.Error(w, fmt.Sprintf("failed to respond: %v", err),
http.StatusInternalServerError)
return
}
}

type reencryptHandler struct {
ctx node.Context
}

func (h *reencryptHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var a dkg.Actor
err := h.ctx.Injector.Resolve(&a)
if err != nil {
http.Error(w, fmt.Sprintf("failed to resolve DKG actor: %v", err),
http.StatusInternalServerError)
return
}

err = r.ParseForm()
if err != nil {
log.Err(err).Msg("failed to parse form")
http.Error(w, "failed to parse form", http.StatusInternalServerError)
return
}

// XHATENC=$(smccli --config /tmp/smc1 dkg reencrypt --encrypted ${CIPHER} --pubk ${PUBK})

// retrieve the public key
pubkString := r.FormValue("pubk")
pubk, err := decodePublicKey(pubkString)
if err != nil {
http.Error(w, fmt.Sprintf("failed to decode public key str: %v", err),
http.StatusInternalServerError)
return
}

// retrieve the encrypted cypher
encrypted := r.FormValue("encrypted")
k, _, err := decodeEncrypted(encrypted)
if err != nil {
http.Error(w, fmt.Sprintf("failed to decode encrypted str: %v", err),
http.StatusInternalServerError)
return
}

// re-encrypt the message
hatenc, err := a.Reencrypt(k, pubk)
if err != nil {
http.Error(w, fmt.Sprintf("failed to re-encrypt: %v", err),
http.StatusInternalServerError)
return
}

// write back the re-encrypted message
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
encoder := json.NewEncoder(w)
err = encoder.Encode(hatenc)
if err != nil {
http.Error(w, fmt.Sprintf("failed to encode response: %v", err),
http.StatusInternalServerError)
return
}

dela.Logger.Debug().Msgf("Re-encrypted message: %v", hatenc)
}

// -----------------------------------------------------------------------------
// Helper functions
func decodePublicKey(str string) (kyber.Point, error) {
pkbuff, err := hex.DecodeString(str)
if err != nil {
return nil, xerrors.Errorf(malformedEncoded, str)
}

pk := suite.Point()
err = pk.UnmarshalBinary(pkbuff)
if err != nil {
return nil, xerrors.Errorf("failed to unmarshal pk: %v", err)
}

return pk, nil
}

func decodeEncrypted(str string) (kyber.Point, []kyber.Point, error) {
parts := strings.Split(str, separator)
if len(parts) < 2 {
return nil, nil, xerrors.Errorf(malformedEncoded, str)
}

// Decode K
kbuff, err := hex.DecodeString(parts[0])
if err != nil {
return nil, nil, xerrors.Errorf("failed to decode k point: %v", err)
}

k := suite.Point()
err = k.UnmarshalBinary(kbuff)
if err != nil {
return nil, nil, xerrors.Errorf("failed to unmarshal k point: %v", err)
}

// Decode Cs
cs := make([]kyber.Point, 0, len(parts)-1)
for _, p := range parts[1:] {
cbuff, err := hex.DecodeString(p)
if err != nil {
return nil, nil, xerrors.Errorf("failed to decode c point: %v", err)
}

c := suite.Point()
err = c.UnmarshalBinary(cbuff)
if err != nil {
return nil, nil, xerrors.Errorf("failed to unmarshal c point: %v", err)
}

cs = append(cs, c)
}

dela.Logger.Debug().Msgf("Decoded K: %v and Cs: %v", k, cs)

return k, cs, nil
}

// -----------------------------------------------------------------------------
// Helper functions

// HTTPError defines the standard error format
type HTTPError struct {
Title string
Code uint
Message string
Args map[string]interface{}
}

// notFoundHandler defines a generic handler for 404
func notFoundHandler(w http.ResponseWriter, r *http.Request) {
err := HTTPError{
Title: "Not found",
Code: http.StatusNotFound,
Message: "The requested endpoint was not found",
Args: map[string]interface{}{
"url": r.URL.String(),
"method": r.Method,
},
}

buf, _ := json.MarshalIndent(&err, "", " ")

w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(http.StatusNotFound)
fmt.Fprintln(w, string(buf))
}

// notAllowedHandler degines a generic handler for 405
func notAllowedHandler(w http.ResponseWriter, r *http.Request) {
err := HTTPError{
Title: "Not allowed",
Code: http.StatusMethodNotAllowed,
Message: "The requested endpoint was not allowed",
Args: map[string]interface{}{
"url": r.URL.String(),
"method": r.Method,
},
}

buf, _ := json.MarshalIndent(&err, "", " ")

w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(http.StatusMethodNotAllowed)
fmt.Fprintln(w, string(buf))
}
87 changes: 87 additions & 0 deletions server/smc/smccli/web/web.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package web

import (
"os"
"time"

"go.dedis.ch/dela"
"go.dedis.ch/dela/cli"
"go.dedis.ch/dela/cli/node"
"go.dedis.ch/dela/mino/proxy"
"go.dedis.ch/dela/mino/proxy/http"
"golang.org/x/xerrors"
)

var defaultRetry = 10
var proxyFac func(string) proxy.Proxy = http.NewHTTP

const defaultProxyAddr = "127.0.0.1:3002"

// NewController returns a new controller initializer
func NewController() node.Initializer {
return controller{}
}

// controller is an initializer with a set of commands.
//
// - implements node.Initializer
type controller struct{}

// Build implements node.Initializer.
func (m controller) SetCommands(builder node.Builder) {
builder.SetStartFlags(
cli.StringFlag{
Name: "proxyaddr",
Usage: "the proxy address",
Required: false,
Value: defaultProxyAddr,
},
)
}

// OnStart implements node.Initializer. It creates and registers a pedersen DKG.
func (m controller) OnStart(ctx cli.Flags, inj node.Injector) error {
dela.Logger.Info().Msg("Installing SMC proxy")

proxyAddr := ctx.String("proxyaddr")

proxyhttp := proxyFac(proxyAddr)

inj.Inject(proxyhttp)

go proxyhttp.Listen()

for i := 0; i < defaultRetry && proxyhttp.GetAddr() == nil; i++ {
time.Sleep(time.Second)
}

if proxyhttp.GetAddr() == nil {
return xerrors.Errorf("failed to start proxy server")
}

// We assume the listen worked proprely, however it might not be the case.
// The log should inform the user about that.
dela.Logger.Info().Msgf("started proxy server on %s", proxyhttp.GetAddr().String())

//
// Register the smc proxy handlers
//

register := RegisterAction{}
err := register.Execute(node.Context{
Injector: inj,
Flags: node.FlagSet{},
Out: os.Stdout,
})

if err != nil {
return xerrors.Errorf("failed to register SMC web handlers: %v", err)
}

return nil
}

// OnStop implements node.Initializer.
func (controller) OnStop(_ node.Injector) error {
return nil
}

0 comments on commit 2afce36

Please sign in to comment.