Skip to content

Commit

Permalink
change public key recover logic
Browse files Browse the repository at this point in the history
  • Loading branch information
huangzhiran committed Nov 7, 2024
1 parent bcb1f18 commit 4e02879
Show file tree
Hide file tree
Showing 4 changed files with 94 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
56 changes: 56 additions & 0 deletions main/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

import (
"crypto/sha256"
"encoding/json"
"fmt"
"log/slog"

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

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

func main() {
sigStr := "0xf48697dfd90cb6d64daff8ba2e9cb089434745924f52c93af4fd8532acd8db11eda477dd906db3cbd4bd366e4a22cdf0f08bcb1307175bf2475c11d9f8ac6afa"
sig, err := hexutil.Decode(sigStr)
if err != nil {
panic(err)
}
req := &queryReq{
DeviceID: "did:io:0x004521b395a8a54c698bb8f29d4934579d8bda4a",
}
reqJson, _ := json.Marshal(req)
h := sha256.Sum256(reqJson)
fmt.Println(hexutil.Encode(h[:]))
recoveryID := uint8(0)

for recoveryID = 0; recoveryID < 2; recoveryID++ {
v := byte(recoveryID)
n := append(sig, v)

//slog.Info("current signature", "signature", hexutil.Encode(ns))
if a, err := recover(n, h[:]); err == nil {
slog.Info("recover owner success", "r_id", recoveryID)
fmt.Println(a.String())
} else {
slog.Error("failed", "error", err)
}
}

}

func 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")
}
fmt.Println("public key", hexutil.Encode(crypto.FromECDSAPub(sigpk)))
return crypto.PubkeyToAddress(*sigpk), nil
}

0 comments on commit 4e02879

Please sign in to comment.