Skip to content

Commit

Permalink
add public key http api, query contains a signature (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
huangzhiran authored Nov 13, 2024
1 parent 4097dce commit d493c90
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 14 deletions.
61 changes: 48 additions & 13 deletions api/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"bytes"
"crypto/ecdsa"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
Expand Down Expand Up @@ -38,17 +39,23 @@ func newErrResp(err error) *errResp {
return &errResp{Error: err.Error()}
}

type pubkeyResp struct {
Pubkey string `json:"publicKey"`
}

type queryReq struct {
DeviceID string `json:"deviceID" binding:"required"`
Signature string `json:"signature,omitempty" binding:"required"`
}

type queryResp struct {
Status int32 `json:"status"`
Owner string `json:"owner"`
Firmware string `json:"firmware,omitempty"`
URI string `json:"uri,omitempty"`
Version string `json:"version,omitempty"`
Timestamp int32 `json:"timestamp"`
Status int32 `json:"status"`
Owner string `json:"owner"`
Firmware string `json:"firmware,omitempty"`
URI string `json:"uri,omitempty"`
Version string `json:"version,omitempty"`
Signature string `json:"signature,omitempty"`
}

type receiveReq struct {
Expand All @@ -63,10 +70,17 @@ type receiveReq struct {
type httpServer struct {
engine *gin.Engine
db *db.DB
prv *ecdsa.PrivateKey
ioidInstance *ioid.Ioid
ioidRegistryInstance *ioidregistry.Ioidregistry
}

func (s *httpServer) pubkey(c *gin.Context) {
c.JSON(http.StatusOK, &pubkeyResp{
Pubkey: hexutil.Encode(crypto.FromECDSAPub(&s.prv.PublicKey)),
})
}

func (s *httpServer) query(c *gin.Context) {
req := &queryReq{}
if err := c.ShouldBindJSON(req); err != nil {
Expand Down Expand Up @@ -133,13 +147,32 @@ func (s *httpServer) query(c *gin.Context) {
}
}

c.JSON(http.StatusOK, &queryResp{
Status: d.Status,
Owner: d.Owner,
Firmware: firmware,
URI: uri,
Version: version,
})
resp := &queryResp{
Timestamp: int32(time.Now().Unix()),
Status: d.Status,
Owner: d.Owner,
Firmware: firmware,
URI: uri,
Version: version,
}
respJ, err := json.Marshal(resp)
if err != nil {
slog.Error("failed to marshal response", "error", err)
c.JSON(http.StatusBadRequest, newErrResp(errors.Wrap(err, "failed to marshal response")))
return
}
hash := sha256.New()
hash.Write(respJ)
h := hash.Sum(nil)
sig, err := crypto.Sign(h, s.prv)
if err != nil {
slog.Error("failed to sign response", "error", err)
c.JSON(http.StatusBadRequest, newErrResp(errors.Wrap(err, "failed to sign response")))
return
}
resp.Signature = hexutil.Encode(sig)

c.JSON(http.StatusOK, resp)
}

func (s *httpServer) receive(c *gin.Context) {
Expand Down Expand Up @@ -381,7 +414,7 @@ func (s *httpServer) handleSensor(id string, pkg *proto.BinPackage, data *proto.
return errors.Wrapf(err, "failed to create senser data: %s", id)
}

func Run(db *db.DB, address string, client *ethclient.Client, ioidAddr, ioidRegistryAddr common.Address) error {
func Run(db *db.DB, address string, client *ethclient.Client, prv *ecdsa.PrivateKey, ioidAddr, ioidRegistryAddr common.Address) error {
ioidInstance, err := ioid.NewIoid(ioidAddr, client)
if err != nil {
return errors.Wrap(err, "failed to new ioid contract instance")
Expand All @@ -393,11 +426,13 @@ func Run(db *db.DB, address string, client *ethclient.Client, ioidAddr, ioidRegi
s := &httpServer{
engine: gin.Default(),
db: db,
prv: prv,
ioidInstance: ioidInstance,
ioidRegistryInstance: ioidRegistryInstance,
}

s.engine.GET("/metrics", gin.WrapH(promhttp.Handler()))
s.engine.GET("/public_key", s.pubkey)
s.engine.GET("/device", s.query)
s.engine.POST("/device", s.receive)

Expand Down
1 change: 1 addition & 0 deletions cmd/server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
type Config struct {
LogLevel slog.Level `env:"LOG_LEVEL,optional"`
ServiceEndpoint string `env:"HTTP_SERVICE_ENDPOINT"`
PrvKey string `env:"PRIVATE_KEY,optional"`
DatabaseDSN string `env:"DATABASE_DSN"`
ChainEndpoint string `env:"CHAIN_ENDPOINT,optional"`
BeginningBlockNumber uint64 `env:"BEGINNING_BLOCK_NUMBER,optional"`
Expand Down
8 changes: 7 additions & 1 deletion cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"syscall"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/pkg/errors"

Expand All @@ -25,6 +26,11 @@ func main() {
cfg.Print()
slog.Info("pebble server config loaded")

prv, err := crypto.HexToECDSA(cfg.PrvKey)
if err != nil {
log.Fatal(errors.Wrap(err, "failed to parse private key"))
}

db, err := db.New(cfg.DatabaseDSN, cfg.IoIDProjectID)
if err != nil {
log.Fatal(errors.Wrap(err, "failed to new db"))
Expand All @@ -49,7 +55,7 @@ func main() {
}

go func() {
if err := api.Run(db, cfg.ServiceEndpoint, client, common.HexToAddress(cfg.IoIDContractAddr), common.HexToAddress(cfg.IoIDRegistryContractAddr)); err != nil {
if err := api.Run(db, cfg.ServiceEndpoint, client, prv, common.HexToAddress(cfg.IoIDContractAddr), common.HexToAddress(cfg.IoIDRegistryContractAddr)); err != nil {
log.Fatal(err)
}
}()
Expand Down

0 comments on commit d493c90

Please sign in to comment.