Skip to content

Commit

Permalink
change public key recover logic (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
huangzhiran authored Nov 7, 2024
1 parent bcb1f18 commit ff5e1b7
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 26 deletions.
58 changes: 35 additions & 23 deletions api/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (s *httpServer) query(c *gin.Context) {
sigStr := req.Signature
req.Signature = ""

owner, err := s.owner(sigStr, req)
owners, err := s.owner(sigStr, req)
if err != nil {
slog.Error("failed to recover owner from signature", "error", err)
c.JSON(http.StatusBadRequest, newErrResp(errors.Wrap(err, "failed to recover owner from signature")))
Expand All @@ -89,13 +89,13 @@ func (s *httpServer) query(c *gin.Context) {
c.JSON(http.StatusInternalServerError, newErrResp(errors.Wrap(err, "failed to query device")))
return
}
if d != nil && d.Owner != owner.String() {
slog.Error("failed to check device permission in db", "device_id", req.DeviceID, "recovered_owner", owner.String(), "owner", d.Owner)
if d != nil && !isOwner(common.HexToAddress(d.Owner), owners) {
slog.Error("failed to check device permission in db", "device_id", req.DeviceID, "owner", d.Owner)
c.JSON(http.StatusForbidden, newErrResp(errors.New("no permission to access the device")))
return
}
if d == nil {
nd, code, err := s.ensureDevice(req.DeviceID, owner)
nd, code, err := s.ensureDevice(req.DeviceID, owners)
if err != nil {
slog.Error("failed to ensure device", "error", err, "device_id", req.DeviceID)
c.JSON(code, newErrResp(err))
Expand Down Expand Up @@ -150,7 +150,7 @@ func (s *httpServer) receive(c *gin.Context) {
sigStr := req.Signature
req.Signature = ""

owner, err := s.owner(sigStr, req)
owners, err := s.owner(sigStr, req)
if err != nil {
slog.Error("failed to recover owner from signature", "error", err)
c.JSON(http.StatusBadRequest, newErrResp(errors.Wrap(err, "failed to recover owner from signature")))
Expand All @@ -163,13 +163,13 @@ func (s *httpServer) receive(c *gin.Context) {
c.JSON(http.StatusInternalServerError, newErrResp(errors.Wrap(err, "failed to query device")))
return
}
if d != nil && d.Owner != owner.String() {
slog.Error("failed to check device permission in db", "device_id", req.DeviceID, "recovered_owner", owner.String(), "owner", d.Owner)
if d != nil && !isOwner(common.HexToAddress(d.Owner), owners) {
slog.Error("failed to check device permission in db", "device_id", req.DeviceID, "owner", d.Owner)
c.JSON(http.StatusForbidden, newErrResp(errors.New("no permission to access the device")))
return
}
if d == nil {
if _, code, err := s.ensureDevice(req.DeviceID, owner); err != nil {
if _, code, err := s.ensureDevice(req.DeviceID, owners); err != nil {
slog.Error("failed to ensure device", "error", err, "device_id", req.DeviceID)
c.JSON(code, newErrResp(err))
return
Expand Down Expand Up @@ -203,42 +203,54 @@ func (s *httpServer) receive(c *gin.Context) {
c.Status(http.StatusOK)
}

func (s *httpServer) owner(sigStr string, o any) (common.Address, error) {
func (s *httpServer) owner(sigStr string, o any) ([]common.Address, error) {
reqJson, err := json.Marshal(o)
if err != nil {
return common.Address{}, errors.Wrap(err, "failed to marshal request into json format")
return nil, errors.Wrap(err, "failed to marshal request into json format")
}
sig, err := hexutil.Decode(sigStr)
if err != nil {
return common.Address{}, errors.Wrapf(err, "failed to decode signature from hex format, signature %s", sigStr)
return nil, errors.Wrapf(err, "failed to decode signature from hex format, signature %s", sigStr)
}
hash := sha256.New()
hash.Write(reqJson)
h := hash.Sum(nil)

rID := []uint8{0, 1, 2, 3, 4, 27, 28}
res := []common.Address{}
rID := []uint8{0, 1}
for _, id := range rID {
ns := append(sig, byte(id))
slog.Info("current signature", "signature", hexutil.Encode(ns))
if a, err := s.recover(ns, h); err == nil {
slog.Info("recover owner success", "r_id", id)
return a, nil
if a, err := s.recover(ns, h); err != nil {
slog.Info("failed to recover address from signature", "error", err, "recover_id", id, "signature", sigStr)
} else {
slog.Error("failed to recover public key from signature", "error", err, "r_id", id)
res = append(res, a)
}
}
return common.Address{}, errors.New("failed to recover public key from signature")
if len(res) == 0 {
return nil, errors.New("failed to recover public key from signature")
}
return res, nil
}

func (s *httpServer) recover(sig, h []byte) (common.Address, error) {
sigpk, err := crypto.SigToPub(h, sig)
if err != nil {
return common.Address{}, errors.Wrapf(err, "failed to recover public key from signature")
}
slog.Info("public key", "data", hexutil.Encode(crypto.FromECDSAPub(sigpk)))
return crypto.PubkeyToAddress(*sigpk), nil
}

func (s *httpServer) ensureDevice(deviceID string, owner common.Address) (*db.Device, int, error) {
func isOwner(o common.Address, os []common.Address) bool {
for _, i := range os {
if bytes.Equal(i.Bytes(), o.Bytes()) {
return true
}
}
return false
}

func (s *httpServer) ensureDevice(deviceID string, owners []common.Address) (*db.Device, int, error) {
deviceAddr := common.HexToAddress(strings.TrimPrefix(deviceID, "did:io:"))
tokenID, err := s.ioidRegistryInstance.DeviceTokenId(nil, deviceAddr)
if err != nil {
Expand All @@ -248,17 +260,17 @@ func (s *httpServer) ensureDevice(deviceID string, owner common.Address) (*db.De
if err != nil {
return nil, http.StatusInternalServerError, errors.Wrap(err, "failed to query device owner")
}
if !bytes.Equal(deviceOwner.Bytes(), owner.Bytes()) {
slog.Error("failed to check device permission in contract", "device_id", deviceID, "recovered_owner", owner.String(), "owner", deviceOwner.String())
if !isOwner(deviceOwner, owners) {
slog.Error("failed to check device permission in contract", "device_id", deviceID, "owner", deviceOwner.String())
return nil, http.StatusForbidden, errors.New("no permission to access the device")
}

dev := &db.Device{
ID: deviceID,
Owner: owner.String(),
Owner: deviceOwner.String(),
Address: deviceAddr.String(),
Status: db.CONFIRM,
Proposer: owner.String(),
Proposer: deviceOwner.String(),
OperationTimes: db.NewOperationTimes(),
}
if err := s.db.UpsertDevice(dev); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.10.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
Expand Down

0 comments on commit ff5e1b7

Please sign in to comment.