-
Notifications
You must be signed in to change notification settings - Fork 163
TON proof updates #342
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev-14
Are you sure you want to change the base?
TON proof updates #342
Conversation
- VerifyProof verifies only proof, not payload. VerifyProofWithPayload to check with payload - Payload generation and check functions
ton/wallet/proof.go
Outdated
h := hmac.New(sha256.New, []byte(secret)) | ||
h.Write(payload) | ||
payload = h.Sum(payload) | ||
return hex.EncodeToString(payload[:32]), nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets increase random size to 24 bytes and keep whole hash, not only 16 bytes, it costs us almost nothing, but looks more secure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or we can add half of domain hash (16 bytes) to payload before hashing, for example, to additionally bound to domain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your comments! I agree that keeping all hash is more secure, so let's do it)
The random bytes in the payload ensure uniqueness, but they don’t improve cryptographic security, which comes from hmac and its secret. Increasing the random bytes won’t make payload more secure, but ok, let's enlarge it 16 bytes to make random nonce more distributed
As for domain, it could be useful in complex systems with multiple domains, but in a single-domain system it doesn’t add much value. Plus, we then check the domain in VerifyProof
So checking the full hash is very reasonable, but increasing random bytes or adding domain may not actually increase security. Should I add a commit to check the full hash and enlarge random bytes to 16?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While hashing only 16 bytes we can get only 2^128 unique hashes (so it is almost same as keeping 16 bytes of hash), but when we increasing payload to 32 bytes we could get up to 2^256 unique hashes, and full hash security is utilized.
So i think lets increase random size and check full hash
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation, it's really so. I'll fix it)
1. Its very hard to know what exactly payload was sent
ton/wallet/proof.go
In the current implementation, when verifying TON proof, you need to remember the exact payload your server sent to the user. In practice, this can be very difficult or impossible
A better approach to verify that the payload was sent by your server is to sign the payload. This way, you can easily verify its origin without having to remember it exactly (similar to JWT)
Proposed Solution
The solution involves introducing two functions:
GeneratePayload
andCheckPayload
, and simplifyVerifyProof
Additionally, we can provide a new function,
VerifyProofWithPayload
, which accepts a custompayloadVerifier
function to handle the payload verification logic:Remove the payload check from VerifyProof, as it is unrelated to the core verification logic:
2. Optimize getting a public key
When verifying a signature, we need to retrieve the public key. There are two possible ways:
stateInit
(already provided in the request)Currently, the implementation prioritizes fetching the public key via an API request and falls back to parsing it from
stateInit
only if the API request fails. However, parsing the key from stateInit is much faster and more reliable since it avoids making an external requestIt will be more optimized to make the vice versa approach: firstly, try to parse the key from
stateInit
, as it's faster, and generally, we have it. And only if it fails, try to get the public key from the request, as it is longer and less reliable: