Apply cryptographic verification on (nearly?) all endpoints
rfornea opened this issue · 0 comments
rfornea commented
Instead of the client just sending their AccountID with requests, they will also send a signature so that we can verify that the correct user is the one who initiated the action.
The endpoint to create an account can be updated in the following manner:
- Remove
AccountID
from top level object and replace withSignature
. - Nest
StorageLimit
,DurationInMonths
, andMetadataKey
under an object living under the top level.
So this:
type accountCreateReq struct {
AccountID string `json:"accountID" binding:"required,len=64"`
StorageLimit int `json:"storageLimit" binding:"required,gte=100"`
DurationInMonths int `json:"durationInMonths" binding:"required,gte=1"`
MetadataKey string `json:"metadataKey" binding:"required,len=64"`
}
Becomes something like this:
type accountCreateReq struct {
Signature string `json:"signature" binding:"required,len=130"`
AccountCreation accountCreateObj `json:"accountCreation" binding:"required"`
}
type accountCreateObj struct {
StorageLimit int `json:"storageLimit" binding:"required,gte=100"`
DurationInMonths int `json:"durationInMonths" binding:"required,gte=1"`
MetadataKey string `json:"metadataKey" binding:"required,len=64"`
}
json.Marshal
therequest.AccountCreation
, then create a hash of the returned[]byte
withutils.Hash
. Callutils.Recover
on the hash and signature. The resulting public key is what we will use as theAccountID
when we create the account.- Create the account as we normally do using the information in
request.AccountCreation
.
Other endpoints can be updated in the following manner:
- Add
Signature
andAddress
(orAccountID
) at the top level, and nest the other parameters under an object under the top level. json.Marshal
the object holding the nested parameters. Callutils.Hash
on the returned value. Then callutils.VerifyFromStrings
on theAddress/AccountID
, the hash you just created encoded as a hex string, and theSignature
. This will return a boolean and an error. If the boolean is true, then that means the correct user sent the request and we can proceed with the rest of the logic in the handler. Otherwise callForbiddenResponse
.
For an example of the above changes, look at the recent changes in the setMetadata
method (link to changes). If we can, let's add some method that captures the needed logic changes all in one place so we aren't repeating ourselves, and let's create some test utility methods so we aren't overly repeating ourselves in the tests.