mazieres The documentation is not ready yet. Hopefully, I will publish all source codes and docs in a week or so.

The flow is quite simple.

  1. A user invokes some action on the third-party website (a wallet, DEX interface, inflation pool etc). Let's say, he wants to create an offer.
  2. The website prepares the requested transaction and it's XDR representation in base64 format.
  3. The website initiates the intent (see intent list in the project description) using js module that provides an interface for all supported intents.
  4. The interface module opens a new pop-up window pointing to id.stellar.expert. All intent parameters are serialized and transmitted in a form of GET parameters. So the full URL will look like https://id.stellar.expert/confirm?intent=sign_tx&network=testnet&txXdr=AAAAALPZeTF82....
  5. Signer application reads parameters from the URL and asks the user for a confirmation.
  6. The user chooses a keypair from the list of stored accounts (or adds a new one) and confirms the action.
  7. The signer app signs the transaction the same way any other wallet do it.
  8. The signed transaction is serialized into XDR as TransactionEnvelope and transmitted back to the opener site in base64 encoding via the built-in browser postMessage mechanism.
  9. The third-party website receives a signed transaction envelope and may choose either to submit it to the network or store somewhere in case if the tx needs more signatures or if it has time bounds set.

Intent confirmation dialog always contains extended request information, including intent description (like "Sign transaction"), initiator website ("origin: example.com"), risk level ("high", "medium", or "low"), information about personal data disclosure (only for personal_info intent), and safety status ("safe" or "potentially unsafe"). Intent-specific details allow a user to review the request before confirmation. For instance, a dialog with sing_tx intent displays full transaction information including all meaningful properties and the list of operations in a human-friendly format adapted for the ordinary users.

There are 4 main groups of intents:

  1. Request transaction signing. The calling app receives a signed transaction envelope in XDR format.
  2. Request information. The app may request a user's personal info (email, avatar), Stellar account public key, or Stellar account secret key (required only in rare cases, maybe we should disable this intent at all).
  3. Request specific action. Currently two actions available: "vote for inflation pool" and "establish trustline". The signer app prepares and submits the transaction to the network without returning transaction envelope XDR to the initiator website. It is done to simplify such standard actions; the initiator website does not need JS SDK or any other custom logic.
  4. Request cryptographic signature of the arbitrary data. The website may request a crypto signature to verify a keypair ownership (authentication, secure messages exchange etc).

If SDF adopted this, we would probably a SEP that is specific enough to allow independent implementations.

Absolutely agree, I'll prepare detailed documentation.

It seems you are relying on informal domain separation for signed messages--basically only sign authentication messages that don't look like transactions. This is not robust to upgrades. Hence, as a first step to integrating with the Stellar ecosystem, you should request a dedicated value of EnvelopeType as a pull request on Stellar-ledger-entries.x

I'm afraid, here you lost me... StellarExpertID is built on top of the existing SDK and it utilizes only the existing standard data formats. It's just a key storage with a simplistic interface allowing other web apps to request predefined actions. I can't see a need for the underlying XDR formats modifications. Everything is already working, we just need a trusted hosting and controlled source codes modification via pool requests. It won't require any code changes for existing SDF-maintained projects.

    OrbitLens Now I'm a bit perplex. You said you didn't want to multiply standards but I can tell your transaction request is neither using cosmic link protocol nor sep-0007. It's nearly using it, but there's a few details that doesn't seems to bring anything except making it different. You're considering making it into another SEP. Then I wonder what's the point of SEP if each one is doing its own?

      OrbitLens According to <https://stellar.github.io/js-stellar-sdk/Transaction.html>, it is the hash of the buffer you're mentioning that is actually signed, so if you sign the hash of input message, and if any binary value may be passed, it is exploitable.

      Once again, when it is about login/authentication (automatic signing) I would prevent any kind of text input as it may have legal value in the future.

        MisterTicot It's my implementation, I designed it 7 months ago, when CosmicLink was not announced yet, and SEP-0007 was not defined. As I mentioned earlier, the application will support CosmicLink format. I spent last month fixing StellarExpert, so I had no time to properly clean up the code and implement the latest specs. If you are going to create your own implementation based on my open-source project and it will be better in terms of usability, I will gradually switch to your project, ditching my codebase.

        I'm going to update GET params mapping to match your notation (for example, xdr instead of txXdr). I do like the format you proposed, the only thing which seems completely wrong to me is a callback logic. If the browser follows redirects, the initiator application will lose its current state. For example, you prepared a transaction on, say, super-cool-trading-bot.io, then you are redirecting the user to cosmic.link?xdr=...&url=super-cool-trading-bot.io. In this case, a developer of super-cool-trading-bot.io has to save current application state either in URL or in localStorage in order to restore it once the transaction is signed.

        My implementation works transparently. You just invoke the intent which returns a standard promise. Once the promise is resolved, the application receives the result, and it does not lose the current state.

          MisterTicot You are absolutely right,

          sign(...keypairs) {
              let txHash = this.hash();
              let newSigs = each(keypairs, kp => {
                let sig = kp.signDecorated(txHash);
                this.signatures.push(sig);
              });
            }

          In this situation keypair.sign(keypair.publicKey() + input_message) looks like a better alternative to double-hashing to me.

          Once again, when it is about login/authentication (automatic signing) I would prevent any kind of text input as it may have legal value in the future.

          Legal implications definitely should be considered. The signing itself is very simple and robust way to confirm the identity or secret key ownership, so I don't want to give up on it so easily.

            OrbitLens

            Legal implications definitely should be considered. The signing itself is very simple and robust way to confirm the identity or secret key ownership, so I don't want to give up on it so easily.

            You are absolutely right. This is precisely the reason why they start to be considered a legal proof of identity/ownership by administrations.

            Using it as a login/authentication means is great: it is clearly something we want to do. It is done right only if it doesn't collide with legal use cases that we'll need to support as well at some point (contract signing).

            For login a number big enough to prevent collision appended to the site domain is enough: you don't need to accept any abritrary data and you can specify the number to be a certain length that is not 256. This also have the benefit that external service would more likely use the feature in a proper way.

            keypair.sign(keypair.publicKey() + message)

            This works as long as you enforce message to be non-empty (or the DKIF weakening attack is possible again).

            Maybe

            keypair.sign(domain + message)

            Would do better. It also greatly reduce chances of collision, because no cross-domain collision could happen anymore. This imply that requester website let the document.referer field set. I'm not sure if it can be handled properly by installed software/applications, though.

              MisterTicot keypair.sign(keypair.publicKey() + message)

              This works as long as you enforce message to be non-empty (or the DKIF weakening attack is possible again).

              Maybe

              keypair.sign(domain + message)

              Would do better. It also greatly reduce chances of collision, because no cross-domain collision could happen anymore. This imply that requester website let the document.referer field set. I'm not sure if it can be handled properly by installed software/applications, though.

              Message signing isn't only done for specific domains.

              MisterTicot Once again, when it is about login/authentication (automatic signing) I would prevent any kind of text input as it may have legal value in the future.

              What do you mean by this?

                dzham

                There's a use case of blockchain that is signing legal contracts and storing signatures on on-chains. Voting can also be implemented as signing a specific piece of data. If your application automatically sign arbitrary messages I can abuse it. This is why I think automatical signing should be restricted to meaningless numbers.

                Message signing isn't only done for specific domains.

                Can you please elaborate on that?

                  MisterTicot Can you please elaborate on that?

                  Message signing can be use for absolutely anything. I don't see why you'd want to restrict that.
                  I'm using is for applications that don't come from a specific domain, e.g.

                  MisterTicot This is why I think automatical signing should be restricted to meaningless numbers.

                  How do you differentiate meaningless numbers from meaningful numbers?
                  If I give you a number I want you to sign, it definitely has meaning to me

                    dzham

                    How do you differentiate meaningless numbers from meaningful numbers?
                    If I give you a number I want you to sign, it definitely has meaning to me

                    Not necessarily. Basically I can differentiate 2 use cases:

                    • Signing for the purpose of login/authentification. What you're actually signing doesn't matter in itself. What matters is to prevent collision to ensure that old signatures can't be re-used by illegitimate party. Here, you wouldn't display the data you're signing because it is likely cryptic and meaningless. What you would ask to user is his agreement to authenticate himself to a given service. Here, you could make use automatic signing (such as "automatically log me in").
                    • Signing for the purpose of accepting a contract, claiming authorship, voting and so on. What you sign is what matters. Collision doesn't, in the meaning that you could very sign several time the same statement (typically "I can legally buy securities in my country."). Here, you must display what is about to be signed to the user. What you ask for is his agreement about the data being signed regardless of which service did issue it. This kind of data should never be signed automatically or without user consent.

                    As you can see both use case are symmetrically opposed so I think it would be better handled by two separate interfaces. One should ensure there's no collision between them to prevent abuse.

                    It is still not clear to me which use cases you're trying to cover right now. Could you please give me example of cases were you would sign messages unrelated to a specific domain?

                    15 days later

                    Update 2018-08-31

                    • Publicly released stable development version. Check the repository here.
                    • Improved security: secret (request secret key) intent removed.
                    • New pay intent added.
                    • SEP-0007 support added.
                    • Fixed potential vulnerability with transaction hash signing via sign_msg intent.

                    I faced some problems implementing SEP-0007 standard. Maybe someone knows other SEP-0007 signer open-source implementations?

                    OrbitLens Hi,

                    I totally missed this answer.

                    I think you're right about callback: I need to re-work that part. I really focused on the wallet-side functionality, like multisig support and such. Now I need to focus on non-wallet side stuff, like methods to build and edit transaction and callbacks.

                    I'll have to take a look at how you did that, for sure.

                      MisterTicot Sure, feel free to fork. The more developers adopt the same signing schema, the better. It will be a giant step toward more secure key management.

                        11 days later