Skip to content
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

TonConnect 2.0 #8

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

TonConnect 2.0 #8

wants to merge 1 commit into from

Conversation

oleganza
Copy link
Contributor

@oleganza oleganza commented Aug 3, 2022

This is a draft of 📄TON Connect 2.0 specification.

Key features:

  • Support for both serverless dapps and centralized services.
  • Authenticating apps via TON DNS.
  • Separate requests for the initial connect and offchain action authorization.
  • Integrated transaction signing request with arbitrary payload and stateInit.
  • Support for push notifications to deliver authorization requests.

TODO:

  • Review the suggested "app" vs "service" distinction.
  • Add tonconnect:// schema for generic URL.
  • Add section on non-inline requests (for compact QR codes).
  • Alternatively, add binary encoding to save space for QR codes.
  • Clarify how to validate return urls and wallet address via TON.DNS for dapps.
  • Clarify how to handle connecting with dapps without TON.DNS verification.
  • Add rejection replies to make UX more convenient in happycase when the user is online and cancels operation in the wallet gracefully. (The app should still be prepared to not receive any response.)
  • Specify how to automatically set up a session in the embedded widget after connecting to the external site.

@andreypfau
Copy link

Why using HMAC-SHA256 keys? It seems to me that this is not the ton-way, in which ed25519 keys are used everywhere

@oleganza
Copy link
Contributor Author

oleganza commented Aug 3, 2022

@andreypfau HMAC-SHA256 is a KDF — to derive secret keys from the common seed. For asymmetric crypto we use classic Ed25519 with NaCl API.

@andreypfau
Copy link

@andreypfau HMAC-SHA256 is a KDF — to derive secret keys from the common seed. For asymmetric crypto we use classic Ed25519 with NaCl API.

Ok I see, but in TON mnemonics uses pbkdf2Sha512 KDF function, it's confused me 🤔

Copy link

@AntonMeep AntonMeep left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All in all, I am sure that wording and used terminology will be improved to make standard easier to understand.
However, used cryptography primitives are much weaker than those used by the wallets, while still operating on the same sensitive data - the 24-word mnemonic phrase. I cannot think of any good reason to do that, this just shouldn't be done.

256-bit secret key used for authentication purposes. This key may be stored separately from the [Wallet Seed](#wallet-seed) with more convenient protection mode.

```
RootConnectKey = HMAC-SHA256(key: "TonConnect.Root", data: WalletSeed)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inadequate security compared to what wallets currently use for these purposes (HMAC_SHA512). Not only does this make it easier to compromise this exact use case, it brings even those more secure solutions down with it.
I see no reason to use anything less than HMAC-SHA512 here, and would love to know for what purpose was this done.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @AntonMeep. For the decentralized app use-case (where no service is involved), why do we need to create a new key? For this use-case TON already has a PK we use to sign external transactions through our wallet contract. Why should we use a different PK for the connect?!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another key hierarchy is needed for authentication to the service (i.e. separate usage from signing txs). Those are separate keys derived per-service. Their root is also separate by one derivation away from the wallet key in order to be able to store it under separate security policy. E.g. your wallet key is available with 2FA and a call to a friend, while the login key might be available with a simple biometric check.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe require this separate key only for the service flow? and let the app flow continue with the regular PK the user is using?

First, a 256-bit _client secret_ is derived from the [Root Connect Key](#root-connect-key) and [App Public Key](#app-keypair)

```
ClientSecret = HMAC-SHA256(key: AppPk, data: RootConnectKey)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, but over 100,000 times worse.
To derive secret key wallets utilize PBKDF2-SHA512 with 100,000 iterations which, while honestly not perfect, will make it considerably more difficult to brute-force and get access to users exact mnemonic phrase, or wallet seed as it called here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PBKDF overhead in ton-mnemonic is unnecessary unless you split the key in 2-of-3 shard. This is a pretty standard KDF application here.

See my extended comment here: #8 (comment)

}
```

`body` is encoded through `NaCl.crypto_sign` using `pk`’s corresponding private key and JSON encoding of the [ConnectRequestBody](#ConnectRequestBody). Wallet unpacks body and checks signature using the `NaCl.crypto_sign_open` function.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not going to nitpick how it's not necessarily encoding but rather signing of a message, but I will point out that storing JSON object in base64 in another JSON object is obnoxious.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, we'll try to move over to TL for precision and sanity.


**App** is a software that runs on behalf of the user and does not rely on a dedicated backend server for accessing users’ data.

**Service** is a software that runs on behalf of its operator, stores users’ data and regulates access to the data.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I understand what is meant by this distinction but wording could be a bit better, I would suggest not using general terms app and service, but something more specific. Custodial vs Non-Custodial used in the next chapter seems more appropriate to me

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I intentionally went on with this radical approach to see the reaction from reviewers.

Custodial/non-custodial is a orthogonal to this issue because even centralized services may be non-custodial. The distinction that matters to TonConnect and the wallets is between (a) the software runs on behalf of the user and does not have its own secure identity, and (b) has its own identity and runs on someone else's machine. In case of (a) we don't have to prove anything in either direction, but have to employ identity indirectly through smart contracts. In case of (b) we have well-defined 3rd party to send responses to.

We may clarify the terms as "standalone app" and a "server", maybe?

Copy link

@talkol talkol Aug 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually like the wording a lot. I think @oleganza did a great job here. The distinction between the two use-cases is indeed radical. Developers who read the standard need a very very good reason to write a service. The majority of them should write an app. Most teams in the TON ecosystem are going to be anonymous and not very trustworthy, so we should not encourage them to hold any positions that require trust.

I would actually even add this to this section. Something like: "As a developer, if you're unsure whether you need to implement an app or a service, try your best to implement an app. Services add the burden and responsibility of trust and when possible should be avoided."


Decentralized apps may use `sha256("wallet")` key for the smart contract address.
When the wallet receives request to sign a message to a smart contract with a given **.ton** name, a valid and up-to-date DNS record would be used to authenticate that contract address with that name.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way in the standard for an app to use the raw contract address without a DNS record?

I can see several reasons this would make sense:

  1. Owning a DNS record means that the average developer will have some wallet that keeps the NFT of the domain ownership. Wouldn't this encourage them to create a centralized failure point? This admin wallet will be able to replace the contract address at any point and steal money from users. The amount of education we will need to convince the average developer to move this domain NFT to the zero address and thus revoke control over it, will be insane. I think we need a solution that by default is trustless and does not encourage centralization.

  2. There are cases where factories deploy smart contracts per user. For example in Balancer V1 on Ethereum if I remember correctly, users had to deploy a proxy contract and then access the protocol through it. The same happens with a project called https://fodl.finance. To reach isolation between borrowing accounts, this project deploys a smart contract per user. When the app deploys a new contract per user, how should the DNS angle be handled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think at present stage the connect flow should work even in unauthenticated situation (without TON DNS), and when we figure out how to make DNS usable in all deployment scenarios we can slowly phase out non-authenticated uses similar to how web-browsers steer towards https.

Re: 1. In any app deployment there is a PKI burden. When you build a server you need a TLS certificate and safeguard the keys. If you do PGP you need to make your pubkey known and counter-signed by known parties. TON DNS is a convenient feature for the users and a formalized burden for developer. Developer may choose to not use TON DNS, but then they are on their own to distribute the identity of their app or contract.

TON DNS is kinda cool because it's built on the native on-chain tech and we can imagine a decentralized version of the owner for it. E.g. your DAO/dapp contract could be made an owner of a DNS record and renewals could be done through a separate message that anyone can sent thus ensuring that the name remains attached as long as anyone among the users cares.

2: That's an interesting use-case, thanks for pointing it out! Is it possible to know whether a contract was created by another contract and could not be deployed externally (if that matters)? If so, we could support parent-child relationship similar to hierarchy of CAs in Web PKI: the parent contract has a .ton name, while children are authenticated through it by association.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure there's a PKI burden on app deployment. Our common practice is to use a temporary new PK for the deployment and dispose of it after deployment. The burden is only when this PK holds power beyond the deployment and should be managed onwards. Our deployment PK's are useless after the deploy so there's no point in keeping them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not being clear. I mean, you have to deal with some PKs anyway, so TON DNS does not bring anything new here. If you want it to be very decentralized you need to attach your dapp's name to some contract that no one can control, but anyone can pay up for DNS through it to keep it alive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for sub-contracts I suggest adding sub-level DNS records for them (or have them be such records). E.g. if you have a mydex.ton with separate entry points for USDTON and EURTON pairs, you may have usdton.mydex.ton for the first one and eurton.mydex.ton for the second one.

Copy link

@talkol talkol Sep 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, but this part of the proposal is broken. Requiring TON DNS will break the standard and make it incompatible with many dapp use-cases. TON DNS is relevant primarily for the service use-case. It's not appropriate at all for the app use-case. If you enforce the TON DNS requirement, you will prevent many dapps from being able to use TonConnect.

  1. In the dapp use-case, there should be no PK to deal with. There is no entity to hold any PK. You have a few smart contracts and an open source client that anyone can run. Adding a PK where non should exist adds unnecessary complexity. Ethereum for example doesn't require dapps to deal with any PK and the dapp-wallet flow there is fine.

  2. I'm trying to write a blog post to onboard new developers to TON (this is part 1, part 2, part 3 should be about a simple web client for the dapp). I can't imagine sending learning developers who are trying to get a taste of TON to register during the tutorial at TON DNS, an action that is a hassle, takes a week for the auction and costs money, just so they can implement the simplest client to interact with their tutorial smart contract.

  3. Let's say I'm implementing a DEX and I decided to have a separate smart contract instance (and separate address) per liquidity pair. There are 50,000 such contracts for pairs deployed on Uniswap for example. Let's say I don't want to go through a router contract and I want my users to interact with these 50,000 smart contract instances directly. Why would you force me the hassle of setting up 50,000 TON DNS subdomains? It makes no sense and it adds no security.

  4. Let's say the smart contract I'm implementing follows the sharded contract model like the Jetton contract. Meaning every user has a separate contract instance deployed (like on Jetton - the contract jetton-wallet). I want the dapp client to be able to send messages to these child smart contracts directly. Where am I supposed to register all the TON DNS names for these children?

  5. The common case in my eyes will be like on Binance Smart Chain or Polygon, many shitty dapps that developers deploy and most of them are not very trustworthy. If you require all of them to register a TON DNS name, I guarantee that 99% of them will end up holding the NFT of the domain on their own centralized wallet. They're not going to give it up (transfer to the zero address) and you're setting them up for failure. Because by controlling the DNS record, they could replace the contract address without their users' consent and effectively steal all the money. You need to understand that it's our role as designers to create a standard of operation where making users vulnerable is not the default but the exception. We don't need to make it easy for developers to make mistakes and create super dangerous apps by accident.

Decentralized apps may use `sha256("wallet")` key for the smart contract address.
When the wallet receives request to sign a message to a smart contract with a given **.ton** name, a valid and up-to-date DNS record would be used to authenticate that contract address with that name.

**TODO:** callback/return URLs should also be specified in the TON DNS to permit their verification for dapps that cannot sign their own requests.
Copy link

@talkol talkol Aug 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another question about (decentralized) apps. What if the app has multiple smart contracts that should be interacted with. What's the recommended best practice in this case to support multiple contract addresses? Add a subdomain for each of them and a sha256("wallet") key under each subdomain? I didn't dig into the DNS standard yet so I'm not sure how easy this is to do. If this is the case, this should be explained here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have multiple entry points to your dapp that don't need separate branding, then enumerating addresses would be sufficient, i think. We could think of a chained list of addresses similar to TIP64. Except that we could fit up to 3 addresses per cell instead of 1 as in TIP64.

2. User scans the QR or clicks the button.
3. Wallet shows confirmation dialog that shows the wallet address communicated to the app.
4. Wallet stores app’s web address (if provided) in the list of connected services.
5. Wallet sends/redirects the user back to the app with the reply: [ConnectResponse](#ConnectResponse) containing its address and optional push URL.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand something. In the chat group we had a very very long conversation about this redirect. How does this redirect happens? In most mobile app use-cases, it's very difficult and fragile to redirect back to the native app that asked to connect.

Consider that the user is talking to a bot through Telegram messenger. The bot shows the frontend for the app right inside Telegram Messenger. We want in the end of the connect action to send the user back to the Telegram native app. The same if the user is browsing to a TON app through Instagram native app. How can the app frontend know what's the correct return URL? It depends on the browser where it was opened from.

The only consistent way to achieve a smooth UX in this case was to poll on an AJAX endpoint from the app frontend until the user is connected. We discussed this in length. Where did this flow disappear?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oleganza we're trying to implement a DEX mobile client (web app) based on this standard and we need the AJAX polling method so the flow is seamless. Can you confirm this AJAX polling method is supported by the standard?

6. Wallet sends/redirects the user back to the app/service with the reply.
7. App/service publishes the transaction.


Copy link

@talkol talkol Aug 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're missing a workflow for an offchain signature without any service in existence.

This workflow exists on Ethereum and has proven quite useful: https://web3js.readthedocs.io/en/v1.2.11/web3-eth.html?#sign

For example, when my bank did due diligence over my Ethereum wallet addresses, it requested that I sign a message with my details to prove ownership of these wallet addresses. There are also DAOs that allow you to cast votes through a similar mechanism, you vote by signing a JSON of your vote.

These use cases can run fully client side and do not require a centralized backend to be involved. We should support them.

Copy link

@talkol talkol Sep 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another flow that must be supported under this use-case is to be able to easily verify this signature from a FunC contract. So the full flow will be: End-user uses their mobile app wallet to sign a short cell off-chain, the client code gets a signature back. This signature is sent later (possibly by a different party) to a FunC smart contract. The contract can verify the signature and be convinced that the address (public key?) of the end-user is indeed the one who signed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we probably should adopt BoC-safe prefix pioneered by Tonhub: https://github.com/ton-foundation/specs/blob/main/specs/wtf-0002.md

A few thoughts:

  1. Ideally we have one format for custom signature, and if we want to be TVM-compatible, that should be through BoC/TL-B instead of TL.
  2. We need secure domain separation, possibly tied to TON.DNS, or to a pubkey of the recipient with encryption and stuff. For fully offchain use we already have "AuthRequest" flow that's tied to a proof of ownership of the address. It is interactive/ephemeral, though.

Copy link
Contributor Author

@oleganza oleganza Sep 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we probably should adopt BoC-safe prefix pioneered by Tonhub: https://github.com/ton-foundation/specs/blob/main/specs/wtf-0002.md

A few thoughts:

  1. Ideally we have one format for custom signature, and if we want to be TVM-compatible, that should be through BoC/TL-B instead of TL.
  2. We need secure domain separation, possibly tied to TON.DNS, or to a pubkey of the recipient with encryption and stuff.
  3. For fully offchain use we already have "AuthRequest" flow that's tied to a proof of ownership of the address. It is interactive/ephemeral, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@talkol isn't on-chain authentication (for voting/administration) through internal msg superior to signature checks? This way you move out costs of sig checks to the individual wallets and have uniform "sender address" as authentication mechanism. Then you enable implementation of some policies through those addresses. E.g. one of the voters might be a multisig contract, or a thing with some ACLs or timelocks.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oleganza on-chain authentication is impossible for certain use-cases and adding the off-chain flexibility is important. One big reason is gas. Some use-cases require gas-less operations since users are not willing to pay for them, even a few cents. One popular example is snapshot.org, getting DAO participants to vote is so difficult, that if each one of them had to pay something to vote, participation would drop by 50%.

I would be very careful designing a standard that limits developers from doing certain things. I don't think we can predict what developers of future apps will require or not. Off-chain signatures are a basic requirement that is available everywhere.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For fully offchain use we already have "AuthRequest"

From what I understand, AuthRequest requires a service to be involved, meaning an entity that holds a private key. The use-cases I want to support do not permit any service to be part of the flow.

A good example is signing something and sending the bank as proof for them to check manually. Example on Ethereum. Why would I want a third-party service provider to be involved with something like this?

@@ -0,0 +1,533 @@
# TON Connect 2

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General feedback - this standard fails to address the most pressing issues we currently have in the ecosystem. People are trying to implement simple dapps that exist in other ecosystems like a Uniswap-like DEX. Before we go adding elaborate support for services, we should see that we have a decent support for this very simple use-case.

I don't see how the standard supports a simple DEX. A DEX is an app. It shouldn't have a backend. As a DEX developer, what do you suppose I do?

  1. How can I connect a user and return the user to the browser that they came from on mobile (when this browser is possibly some native app)?

  2. How am I supposed to handle the RPC endpoint? is it hardcoded in the app frontend? We agreed that this solution was horrible.

@oleganza
Copy link
Contributor Author

oleganza commented Aug 9, 2022

I should probably clarify that the well-established security level is 100 bits which is usually rounded to 128 bits, anything above is completely unnecessary and wasteful. This roughly means "attacker must do an order of 2^128 operations to undo the algorithm".

Unfortunately, the realm of cryptography is full of misconceptions and cargo cultism that does not help explaining design decisions. So let me explain some rationale for various cryptographic decisions w.r.t. key lengths for the benefit of all the readers.

Symmetric crypto

There are several versions of the AES block cipher: 128, 192 and 256 bit. Provided the key is unique and unpredictable the above rule dictates that we use 128-bit key for maximum performance when encrypting things. Funny thing, there was a reduced-round attack on AES-256, but not on AES-128.

Why would you use 256-bit block cipher then? Turns out, if you build a hash function (e.g. Salsa20 is used both for encryption and KDF, as Keccak/SHA3/SHAKE do), you now have to worry about collisions and birthday paradoxes. Such collisions take O(sqrt(N)) amount of work, so for this to be 128 bits-secure, N must be squared, therefore N=256 bits. That's why popular hash functions have 256-bit output. (Other people who would suggest using 256-bit cipher for encryption are paranoid military bureaucrats who feel like doubling things is always good. See also story behind SHA3 vs SHAKE.)

512-bit and XOFs (variable-output hash functions, such as SHAKE-128/256) are needed for key derivation and producing key streams. This has little to do with the above discussion as the key length that matters is not the output, but the input to these functions. See, for instance, how 512-bit output is split into two 256-bit halves in Ed25519 protocol at the start of the signing procedure.

Asymmetric crypto

Why do elliptic curve private keys are ≈256-bit? The best known (non-quantum) attack on EC pubkeys is Pollard's Rho algorithm that exploits birthday paradox and therefore has complexity O(sqrt(N)) where N is the order of the group, and requires twice as long keys to counter this. Ed25519 has N=2^252 which yields ≈126 bits of security that's close enough to the gold standard. 126 bits is as good as 128 bits, but then your keys fit into 32 bytes and you get an ultra-fast Edwards curve under the hood thanks to a cofactor 8.

Why does Ed25519 pass message+privkey and nonce commitment through SHA512 to generate 512-bit nonce & challenge? This is because we need to mod-reduce nonce and challenge scalars to group's order (≈2^252) and reducing 256-bit number would introduce non-negligible bias in the process. Reducing 512-bit integer would make such bias negligible.

Nonces

Sometimes you don't even need 128 bits of security. Consider that widely deployed Salsa20 (NaCl) uses 64-bit nonce. Why? Because the role of the nonce is to ensure that user's messages differ before the encryption to prevent related-message attacks. 64 bits is enough to make sure the user will never accidentally repeat the nonce by choosing it honestly at random over the lifetime of the sender/receiver pair.

TON passphrases

Given all of the above you might wonder why did TON use 24-word phrases (>256 bits of entropy) instead of a more traditional 12-word phrases (>128 bits)? Mind you, birthday attacks are irrelevant here since bruteforcing wallet keys through pubkeys requires sqrt(2^256) work, while bruteforcing from the 12-word passphrase requires 2^128 work, both are the same.

I did not participate in the design of TON, so I could only speculate as to what was the rationale. My best guess is that 24-word phrase could be sharded into a 2-of-3 configuration where missing 8 words give 88 bits of entropy. To improve this, PBKDF with 100K iterations is used which adds another 16.6 bits of work, yielding 104 bits of work to get from guessing words to a private key. Note that <80 bits is generally considered broken, while anything above 100 bits is considered impractical to attack; 128 is just a nice round number.

If you do not use 2-of-3 sharding, a 128-bit passphrase (12 words) and a single round of hashing into a private key scalar is completely adequate for the purpose of keeping your own funds secure (finding birthday collisions here is irrelevant because there are zero protocols that use passphrases as plaintext documents and pubkeys as hashes).

@@ -0,0 +1,533 @@
# TON Connect 2

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering the following necessary flows for a dapp -

  1. Get wallet address
  2. Send TXN
  3. Sign arbitrary data using wallet's keypair

With respect to these flows, the proposition is missing a way of communicating back the ConnectResponse to the dapp, whether it's on desktop, a mobile webview or a mobile browser. The only viable solution I'm familiar with is a server (that should be open sourced and replaceable) that exposes an endpoint, polled by the dapp until the user approves the connection request. (Same goes for flows 2-3).

In addition, flow 3 doesn't currently support dapps because of the app keypair and dns requirement (comments on that below)


### User identification

To minimize cross-service tracking, TON Connect uses distinct cryptographic identities for each service.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the trackable user property we're trying to hide from the service? I understand that the wallet address will be returned to it by the ConnectResponse in any case.

Decentralized apps authenticate users within smart contracts using message sender addresses.
The UI (“offchain logic”) runs on behalf of the user, so there is no need for a dedicated “sign in” scheme.

Centralized apps run on the servers and may store user data. They may use “sign in” functionality to authenticate the user, where instead of username/password pair we use cryptographic keypair derived from the wallet secret seed.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Sign in" essentially means proving ownership of a certain identity (web2 - email address or phone number, web3 - a wallet address).

Perhaps we can achieve the same by signing a proof of wallet ownership for the service/dapp, instead of creating another keypair?


### ConnectResponse

ConnectResponse contains [response body](#ConnectResponseBody) encrypted towards [App Public Key](#app-keypair) using `NaCl.crypto_box`:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the response body need to be encrypted?

}
],
"push": {
"url": "https://api.example.com/...",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an endpoint that is capable of creating push notifications for the wallet app? Who is the owner of this backend?

```
{
"type": "v2-tx-resp",
"tx-boc": Base64(Tx-BoC)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should consider a case where the user rejects the txn in the wallet app, so perhaps a "status" field could be helpful here


Apps are authenticated using [TON DNS](https://ton.org/docs/#/web3/dns) protocol.

Decentralized apps may use `sha256("wallet")` key for the smart contract address.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: shouldn't this be sha256("appname") - it identifies the app, not the wallet, correct?


### AuthResponse

AuthResponse contains [response body](#AuthResponseBody) encrypted towards [App Public Key](#app-keypair) using `NaCl.crypto_box`:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this flow mandates an app keypair, it forces the app to store the private key somewhere. This means that the app cannot be fully open-sourced and be decentralized.

Open sourced dapps should also be capable of requesting such offline signatures, so at the very least the encryption should be optional.

{
"protocol": "ton-auth",
"v2": {
"body": (base64-encoded signed AuthRequestBody),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By signed, do we mean encrypted? or is the signature transmitted alongside the transparent body?

"v2": {
"body": (base64-encoded signed AuthRequestBody),
"pk": (base64-encoded public key),
"dns": "example.ton",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be made optional in case the app does not own a dns name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants