@@ -2,7 +2,6 @@ package api
2
2
3
3
import (
4
4
"bytes"
5
- "crypto/ecdsa"
6
5
"crypto/sha256"
7
6
"encoding/json"
8
7
"fmt"
@@ -34,13 +33,12 @@ func newErrResp(err error) *errResp {
34
33
}
35
34
36
35
type 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"`
44
42
}
45
43
46
44
type CreateTaskResp struct {
@@ -69,6 +67,11 @@ type httpServer struct {
69
67
proverAddr string
70
68
}
71
69
70
+ type recoverRes struct {
71
+ addr common.Address
72
+ sig []byte
73
+ }
74
+
72
75
func (s * httpServer ) createTask (c * gin.Context ) {
73
76
req := & CreateTaskReq {}
74
77
if err := c .ShouldBindJSON (req ); err != nil {
@@ -77,8 +80,8 @@ func (s *httpServer) createTask(c *gin.Context) {
77
80
return
78
81
}
79
82
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 {
82
85
slog .Error ("failed to decode project id string" , "project_id" , req .ProjectID )
83
86
c .JSON (http .StatusBadRequest , newErrResp (errors .New ("failed to decode project id string" )))
84
87
return
@@ -89,42 +92,42 @@ func (s *httpServer) createTask(c *gin.Context) {
89
92
c .JSON (http .StatusBadRequest , newErrResp (errors .Wrap (err , "failed to decode signature from hex format" )))
90
93
return
91
94
}
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 )
94
97
if err != nil {
95
98
slog .Error ("failed to recover public key" , "error" , err )
96
99
c .JSON (http .StatusBadRequest , newErrResp (errors .Wrap (err , "invalid signature; could not recover public key" )))
97
100
return
98
101
}
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
+ }
105
117
}
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 ())
108
120
c .JSON (http .StatusForbidden , newErrResp (errors .New ("device does not have permission" )))
109
121
return
110
122
}
111
123
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 )
123
125
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 " )))
126
128
return
127
129
}
130
+
128
131
taskID := crypto .Keccak256Hash (sig )
129
132
130
133
if err := s .db .CreateTask (
@@ -134,7 +137,7 @@ func (s *httpServer) createTask(c *gin.Context) {
134
137
Nonce : req .Nonce ,
135
138
ProjectID : pid .String (),
136
139
ProjectVersion : req .ProjectVersion ,
137
- Payloads : payloadsJ ,
140
+ Payload : payload ,
138
141
Signature : sig ,
139
142
Algorithm : alg ,
140
143
},
@@ -175,40 +178,27 @@ func (s *httpServer) createTask(c *gin.Context) {
175
178
})
176
179
}
177
180
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 ) {
179
182
req .Signature = ""
180
183
reqJson , err := json .Marshal (req )
181
184
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" )
183
186
}
184
187
185
188
switch req .Algorithm {
186
189
default :
187
190
h := sha256 .Sum256 (reqJson )
188
- res := []struct {
189
- pk * ecdsa.PublicKey
190
- sig []byte
191
- }{}
191
+ res := []* recoverRes {}
192
192
rID := []uint8 {0 , 1 }
193
193
for _ , id := range rID {
194
194
ns := append (sig , byte (id ))
195
195
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 )
197
197
} 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 })
209
199
}
210
200
}
211
- return common. Address {}, nil , " " , errors . New ( "failed to recover public key from signature" )
201
+ return res , "ES256 " , nil
212
202
}
213
203
}
214
204
0 commit comments