@@ -2,7 +2,6 @@ package api
22
33import (
44 "bytes"
5- "crypto/ecdsa"
65 "crypto/sha256"
76 "encoding/json"
87 "fmt"
@@ -34,13 +33,12 @@ func newErrResp(err error) *errResp {
3433}
3534
3635type CreateTaskReq struct {
37- Nonce uint64 `json:"nonce" binding:"required"`
38- DeviceID string `json:"deviceID" binding:"required"`
39- ProjectID string `json:"projectID" binding:"required"`
40- ProjectVersion string `json:"projectVersion,omitempty"`
41- Payloads []string `json:"payloads" binding:"required"`
42- Algorithm string `json:"algorithm,omitempty"` // Refer to the constants defined in JWT (JSON Web Token) https://jwt.io/
43- Signature string `json:"signature,omitempty" binding:"required"`
36+ Nonce uint64 `json:"nonce" binding:"required"`
37+ ProjectID string `json:"projectID" binding:"required"`
38+ ProjectVersion string `json:"projectVersion,omitempty"`
39+ Payload string `json:"payload" binding:"required"`
40+ Algorithm string `json:"algorithm,omitempty"` // Refer to the constants defined in JWT (JSON Web Token) https://jwt.io/
41+ Signature string `json:"signature,omitempty" binding:"required"`
4442}
4543
4644type CreateTaskResp struct {
@@ -69,6 +67,11 @@ type httpServer struct {
6967 proverAddr string
7068}
7169
70+ type recoverRes struct {
71+ addr common.Address
72+ sig []byte
73+ }
74+
7275func (s * httpServer ) createTask (c * gin.Context ) {
7376 req := & CreateTaskReq {}
7477 if err := c .ShouldBindJSON (req ); err != nil {
@@ -77,8 +80,8 @@ func (s *httpServer) createTask(c *gin.Context) {
7780 return
7881 }
7982
80- pid := new (big.Int )
81- if _ , ok := pid . SetString ( req . ProjectID , 10 ); ! ok {
83+ pid , ok := new (big.Int ). SetString ( req . ProjectID , 10 )
84+ if ! ok {
8285 slog .Error ("failed to decode project id string" , "project_id" , req .ProjectID )
8386 c .JSON (http .StatusBadRequest , newErrResp (errors .New ("failed to decode project id string" )))
8487 return
@@ -89,42 +92,42 @@ func (s *httpServer) createTask(c *gin.Context) {
8992 c .JSON (http .StatusBadRequest , newErrResp (errors .Wrap (err , "failed to decode signature from hex format" )))
9093 return
9194 }
92- deviceAddr := common . HexToAddress ( strings . TrimPrefix ( req . DeviceID , "did:io:" ))
93- addr , sig , alg , err := recoverAddr (* req , sig , deviceAddr )
95+
96+ recovered , alg , err := recover (* req , sig )
9497 if err != nil {
9598 slog .Error ("failed to recover public key" , "error" , err )
9699 c .JSON (http .StatusBadRequest , newErrResp (errors .Wrap (err , "invalid signature; could not recover public key" )))
97100 return
98101 }
99-
100- ok , err := s .db .IsDeviceApproved (pid , addr )
101- if err != nil {
102- slog .Error ("failed to check device permission" , "error" , err )
103- c .JSON (http .StatusInternalServerError , newErrResp (errors .Wrap (err , "failed to check device permission" )))
104- return
102+ var addr common.Address
103+ var approved bool
104+ for _ , r := range recovered {
105+ ok , err := s .db .IsDeviceApproved (pid , r .addr )
106+ if err != nil {
107+ slog .Error ("failed to check device permission" , "error" , err )
108+ c .JSON (http .StatusInternalServerError , newErrResp (errors .Wrap (err , "failed to check device permission" )))
109+ return
110+ }
111+ if ok {
112+ approved = true
113+ addr = r .addr
114+ sig = r .sig
115+ break
116+ }
105117 }
106- if ! ok {
107- slog .Error ("device does not have permission" , "project_id" , pid .String (), "device_address" , addr . String () )
118+ if ! approved {
119+ slog .Error ("device does not have permission" , "project_id" , pid .String ())
108120 c .JSON (http .StatusForbidden , newErrResp (errors .New ("device does not have permission" )))
109121 return
110122 }
111123
112- payloadsB := make ([][]byte , 0 , len (req .Payloads ))
113- for _ , p := range req .Payloads {
114- d , err := hexutil .Decode (p )
115- if err != nil {
116- slog .Error ("failed to decode payload from hex format" , "error" , err )
117- c .JSON (http .StatusBadRequest , newErrResp (errors .Wrap (err , "failed to decode payload from hex format" )))
118- return
119- }
120- payloadsB = append (payloadsB , d )
121- }
122- payloadsJ , err := json .Marshal (payloadsB )
124+ payload , err := hexutil .Decode (req .Payload )
123125 if err != nil {
124- slog .Error ("failed to marshal payloads " , "error" , err )
125- c .JSON (http .StatusInternalServerError , newErrResp (errors .Wrap (err , "failed to marshal payloads " )))
126+ slog .Error ("failed to decode payload from hex format " , "error" , err )
127+ c .JSON (http .StatusBadRequest , newErrResp (errors .Wrap (err , "failed to decode payload from hex format " )))
126128 return
127129 }
130+
128131 taskID := crypto .Keccak256Hash (sig )
129132
130133 if err := s .db .CreateTask (
@@ -134,7 +137,7 @@ func (s *httpServer) createTask(c *gin.Context) {
134137 Nonce : req .Nonce ,
135138 ProjectID : pid .String (),
136139 ProjectVersion : req .ProjectVersion ,
137- Payloads : payloadsJ ,
140+ Payload : payload ,
138141 Signature : sig ,
139142 Algorithm : alg ,
140143 },
@@ -175,40 +178,27 @@ func (s *httpServer) createTask(c *gin.Context) {
175178 })
176179}
177180
178- func recoverAddr (req CreateTaskReq , sig []byte , deviceAddr common. Address ) (common. Address , [] byte , string , error ) {
181+ func recover (req CreateTaskReq , sig []byte ) ([] * recoverRes , string , error ) {
179182 req .Signature = ""
180183 reqJson , err := json .Marshal (req )
181184 if err != nil {
182- return common. Address {}, nil , "" , errors .Wrap (err , "failed to marshal request into json format" )
185+ return nil , "" , errors .Wrap (err , "failed to marshal request into json format" )
183186 }
184187
185188 switch req .Algorithm {
186189 default :
187190 h := sha256 .Sum256 (reqJson )
188- res := []struct {
189- pk * ecdsa.PublicKey
190- sig []byte
191- }{}
191+ res := []* recoverRes {}
192192 rID := []uint8 {0 , 1 }
193193 for _ , id := range rID {
194194 ns := append (sig , byte (id ))
195195 if pk , err := crypto .SigToPub (h [:], ns ); err != nil {
196- slog . Debug ( "failed to recover public key from signature" , "error" , err , " recover_id" , id , "signature" , hexutil . Encode ( sig ) )
196+ return nil , "" , errors . Wrapf ( err , "failed to recover public key from signature, recover_id %d" , id )
197197 } else {
198- res = append (res , struct {
199- pk * ecdsa.PublicKey
200- sig []byte
201- }{pk : pk , sig : ns })
202- }
203- }
204-
205- for _ , r := range res {
206- addr := crypto .PubkeyToAddress (* r .pk )
207- if bytes .Equal (addr .Bytes (), deviceAddr .Bytes ()) {
208- return addr , r .sig , "ES256" , nil
198+ res = append (res , & recoverRes {addr : crypto .PubkeyToAddress (* pk ), sig : ns })
209199 }
210200 }
211- return common. Address {}, nil , " " , errors . New ( "failed to recover public key from signature" )
201+ return res , "ES256 " , nil
212202 }
213203}
214204
0 commit comments