0chain / blobber

A storage provider (blobber) interface to the blockchain and consumers of storage.
Other
19 stars 23 forks source link

blobber_ur/v1/file/stats gives invalid signature #227

Closed chauchausoup closed 3 years ago

chauchausoup commented 3 years ago

blobber_ur/v1/file/stats gives invalid signature but on cli ./zbox stats works fine. blobber_ur/v1/file/meta works fine. It was originally raised here : https://github.com/0chain/block-explorer/issues/220

stewartie4 commented 3 years ago

What method are you attempting to hit this endpoint with? Directly? Via CLI? Via browser?

It's strange that the cli works and elsewhere doesn't as they all use the same go sdk (minus direct of course)

shaktals commented 3 years ago

We found the issue on the browser and using REST client (postman). Postman calls directly to 0chain core APIs. The Explorer webapp uses js-sdk, that talks to go-sdk. I did some digging on the issue here.

stewartie4 commented 3 years ago

The link seems dead - what was the outcome? Postman and cli seems fine

shaktals commented 3 years ago

Hm, probably you don't have access to the block-explorer repo.

FIRST COMMENT: I can reproduce a similar error on one.devnet too. Although requests for 2 blobbers work, and for other 2 don't. I tried those same requests using Postman and got the same results.

However, when using zboxcli, all 4 results come through ok. zboxcli - getFileStats.txt

As the js-client-sdk talks directly to go-sdk, I wrote a small script to debug it there. When calling GetFileStats I also got 4 successful results. go-sdk - GetFileStats result.txt

The good and bad responses received from the explorer have some prop differences, if we compare with the go-sdk results. The good responses had, among other props:

write_marker_txn: "", blockchain_aware: false,

While the bad results had:

write_marker_txn: "some_random_hex_hash", blockchain_aware: true, ...

SECOND COMMENT: I just found that the error message is coming from 0chain VerifySignature function. I'm now pinging Ryan Stewart on slack about how to easier debug this. ---x---

In summary, the error seen in Postman was 'invalid signature', the same seen in the js-sdk internals, if I remember correctly. But that maybe is obscuring the real reason behind it.

shaktals commented 3 years ago

Hey @stewartie4, did you get a chance to take a look at it? If you point me in the right direction I can propose a fix PR. It's blocking for us to get correct file info on block-explorer.

stewartie4 commented 3 years ago

I would guess this is a mismatch in go sdk version or blobber version. The sdk and CLI all work a s they have been updated to correctly provide a request signature to the blober. If the block-explorer is failing then i would guess that the js sdk needs updated to provide the same signature by updating to use the latest go sdk

can you see an X-Client-Signature header being sent to the blobber from the explorer?

shaktals commented 3 years ago

@stewartie4 after reviewing issue #239 it seems like we are missing the X-Client-Signature header on js-client-sdk. I'll create a new branch there, make tests and come back here to confirm.

stewartie4 commented 3 years ago

That makes sense to me I wonder what we can do to stop this happening again, maybe we need better compatibility tests

shaktals commented 3 years ago

Also it might be helpful to have some way to broadcast breaking changes to APIs, maybe on slack?

shaktals commented 3 years ago

@stewartie4 I tested again the endpoint again via jsClientSDK and Postman, using a X-App-Client-Signature header what worked fine on another endpoint that requires the header, /shareinfo. But I still receive an invalid signature error in response. Does the endpoint work for you?

stewartie4 commented 3 years ago

Hey are you talking about /v1/marketplace/shareinfo/ ? If so that endpoint is new and I wasn't involved in the signature implementation for that one. I checked anyway and the signature does work for me

shaktals commented 3 years ago

Sorry @stewartie4 , I badly expressed myself.

I meant that, I tested again the v1/file/stats endpoint again via jsClientSDK and Postman, using a X-App-Client-Signature header, and it returns an invalid signature error.

The same header signature value works fine on another endpoint (/shareinfo),

stewartie4 commented 3 years ago

Hmmm that is strange It sounds like the two endpoints are calculating the signature differently In saying all that I just tested via postman and /v1/file/stats works fine for me using the same signature

stewartie4 commented 3 years ago

image

shaktals commented 3 years ago

I asked you on slack, but maybe better leave it recorded here, how are you generating your signature? It seems like the signature generated by js-client-sdk only works with 0box endpoints.

shaktals commented 3 years ago

Ryan answered me on slack, I repeat it here:

No I call herumi directly via an api The signature should be the signed sla3-256 hash of the allocation id

shaktals commented 3 years ago

@stewartie4 I built a quick script in go-sdk to confirm my signature was correct, and it seems to be (it matches the one created with js-client-sdk).

Then I built a little script in the blobbers code to test the verifySignatureFromRequest func in storage_handler.go, and it says my signature is invalid.

However, when testing the signature against go-sdk's zcncrypto Verify func, I get that the signature is valid.

Shouldn't those results match?

stewartie4 commented 3 years ago

you're right these should match, although it's strange that nowhere else is having these issues. The postman api regressions are working fine against that endpoint https://0chain.github.io/0chain/beta/latest/index.html#pills-requests see "QUERY ALLOCATION METADATA"

shaktals commented 3 years ago

Ah, the metadata endpoint is working fine indeed. I don't even need to provide the signature. However, it seems like we can't get the file/stats endpoint to work. I just created a new wallet, new allocation, new file, got the signature and I can't get the file stats.

How did you get the above results on Postman? What network are you testing against? Or are you querying against a local deployment? Might there be something on your pre-request script there? You mention you got your signature calling herumi directly via an api, what is that api?

Going through the docs, I saw that some other endpoints also ask for X-App-Client-Signature. But when I hit file/list for example, it works even without signature. On the other hand, I get the same invalid signature error on:

I stopped testing there. Would a local blobber deployment help to test this out? It shouldn't be necessary, right.

Here is data of one of the wallets I'm trying to get file stats from:

{
  "allocId": "22a63356ce2b8cb4138cab3278c5b70b2c08f9764ece67b822e8ce9e8e344c60",
  "clientId": "40d7918282887c85d87050f8a948757d9814e583eb2aee45996be26628e2d8fa",
  "privateKey": "59c8f250d38be6831e349e720962fe49b3c2978ff8b19efcfcefb6418efc1b12",
  "publicKey": "2c92576164ee9bd4e2d6139d0cbc53653080b3b7812c9142dfcc02b122ecd420ff621e4065f742d4e214a137c0127e4ad21532cbaac4e9c4d3f2b65d61d7e794"
}

The network is dev, the file path is /yolo/Movies.txt.

And the signature I get from herumi wasm bls (js-client-sdk) is: 787d133b86cc653671e8f9deec4ae9e0ee0c65d5c7d9eab0ff865b5d86a18a89 (that matches what I get from go-sdk)

Can you make that work? Or, can you share sample wallet data that is working on your side?

Should we maybe have a better/easier way to debug something like this?

shaktals commented 3 years ago

Ah, are there any other client apps/libraries regular and successfully consuming this endpoint now?

stewartie4 commented 3 years ago

Yes the pre-request script is generating the signature which is the BLS signing of the allocation id This gives the same result as the go sdk

Ultimately this has to be a problem with how you're generating your signature on the client side, because the postman generated signature and the one generated by the blobber match. /v1/file/upload and /v1/file/collaborator also uses exactly the same signature generation and works via the zbox cli and go sdk

shaktals commented 3 years ago

because the postman generated signature and the one generated by the blobber match

Yes, that seems to be exactly the root of the problem. Your Postman's signature and the blobber's somehow match, but I can't get go-sdk or herumi JS lib to match it.

Will you please share that pre-request script? How did you get the signature from go-sdk to compare against?

I have written a Go script to use go-sdk signing function directly, and it's the same signature I get from js-client-sdk, and the same I get from using herumi JS lib, for that matter.

Have you tested the data I shared with you? Do you get a different signature?

shaktals commented 3 years ago

Ok, I think I found out what is going on.

I did additional tests using zboxcli, which yielded the file stats correctly. So I drilled down into the code to check out the signature being generated by go-sdk there.

It turns out that the function being called to generate the signature in that logic is setClientInfoWithSign. And the key thing is that is uses the hash of allocationID as argument.

sign, err := client.Sign(encryption.Hash(allocation))

However, js-client-sdk was using the clientId as argument to the signature generator. Which result would match the go-sdk signature generated by:

retSignature, err := ss.Sign(clientId)

But, if I use a sha3_256 hash of the allocationId as argument, I get a signature matching the one generated by zboxcli for that function. Mystery solved, closing. :mage:

shaktals commented 3 years ago

Actually, I can't close this :laughing: But please go ahead.

stewartie4 commented 3 years ago

I knew it was bound to be something like that Glad you got it sorted 👍🏻 I'm going to make sure that our API documentation calls this out, but I think it does