StellarGuard.me

Announcing StellarGuard.me, an app that secures your precious XLM by using Stellar's multisignatures and two factor authentication.

StellarGuard is currently available for testing using Stellar's testnet at: https://test.stellarguard.me and will be available for the public net by March 15.

Project Motivation and Goals

Every time I enter my secret key to sign a transaction I get a sense of dread that it might be intercepted or stolen by a hacker and all of my XLM would be gone. After the Blackwallet hack, it became clear to me that there are so many different attack vectors on the web that there needed to be a way to keep your XLM safe even if your computer or wallet was compromised. Thankfully, Stellar multisignatures can help make that possible, but you still need a safe and secure way to handle the 2nd signature. That's where StellarGuard comes in.

StellarGuard was built with 3 driving principles in mind:

  1. Your XLM should be safe even if your computer is hacked and your secret key is stolen.
  2. Your XLM should be safe even if StellarGuard is hacked and it's secret keys are stolen. The only way you should ever be able to lose your XLM is if someone gets your secret key AND StellarGuard's.
  3. StellarGuard should be able to work with other wallets, including paper wallets. Its primary goal is not to be a wallet itself, but to add an additional layer of protection.

How it works

  1. Sign up for a StellarGuard account
  2. Add a StellarGuard public key as an additional signer to your Stellar Account.
  3. Submit your half-signed transactions directly to StellarGuard.
  4. Enter your authorization code (emailed to you, or authenticator app).
  5. StellarGuard signs the transaction and submits it to horizon.

Two Factor Authorization

StellarGuard currently supports two methods for authorizing transactions.

  1. Email: An authorization code is emailed to you when you submit a transaction.
  2. Authenticator: A rotating passcode from a supported authenticator app must be entered to authorize a transaction.

Screenshots

Home Page
Dashboard
New Transaction
Authorize Transaction

Work still to be done

  1. Make it easier to deactivate StellarGuard (currently you must build a transaction manually to remove the StellarGuard signer) - DONE
  2. Optionally allow you to build and sign transactions in the app itself (client side only) so you don't have to be copy/pasting XDRs around
  3. Wallet Integrations - contact Stellar wallet developers to see if they'd be interested in integrating StellarGuard. It's a simple API call to submit the transaction to StellarGuard instead of to Horizon.
  4. UI/UX improvements. Looking for feedback on this. If anyone has suggestions for improvements please let me know!
  5. Allow you to toggle authorization modes for an account. Right now once you enable authenticator it always requires it.
  6. Allow you to authorize via SMS codes
  7. Get it live on production/public network - DONE

Feedback and suggestions would be GREATLY appreciated.

Cool! This was the first thing I tried myself when multi-sig was added to Stellar

sacarlson How common is this? Is it typically unsigned transactions that are in the QR code -- since my app requires that you send it a signed transaction? And are there examples out there of wallets or apps that generate these QRs already?

    I test to ues my temp account on testnet.
    After I created transaction and submit XDR then error as below detail. It's show blank screen.
    There is no detail of pending or not complete transaction at main screen.

    https://test.stellarguard.me/transactions/1

    65ed3ccc18e0a6174aa03922462f051a.js:719 TypeError: e.value is not a function
    at e.get (65ed3ccc18e0a6174aa03922462f051a.js:2815)
    at un (65ed3ccc18e0a6174aa03922462f051a.js:746)
    at e.computeValue (65ed3ccc18e0a6174aa03922462f051a.js:746)
    at e.trackAndCompute (65ed3ccc18e0a6174aa03922462f051a.js:746)
    at e.get (65ed3ccc18e0a6174aa03922462f051a.js:746)
    at e.<anonymous> (65ed3ccc18e0a6174aa03922462f051a.js:746)
    at e.get (65ed3ccc18e0a6174aa03922462f051a.js:746)
    at t.value (65ed3ccc18e0a6174aa03922462f051a.js:2740)
    at Object.W [as allowStateChanges] (65ed3ccc18e0a6174aa03922462f051a.js:746)
    at 65ed3ccc18e0a6174aa03922462f051a.js:748
    at un (65ed3ccc18e0a6174aa03922462f051a.js:746)
    at e.track (65ed3ccc18e0a6174aa03922462f051a.js:746)
    at u (65ed3ccc18e0a6174aa03922462f051a.js:748)
    at t.render (65ed3ccc18e0a6174aa03922462f051a.js:748)
    at i (65ed3ccc18e0a6174aa03922462f051a.js:719)
    at beginWork (65ed3ccc18e0a6174aa03922462f051a.js:719)
    i @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    l @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    x @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    k @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    batchedUpdates @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    ut @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    gn @ 65ed3ccc18e0a6174aa03922462f051a.js:746
    xn @ 65ed3ccc18e0a6174aa03922462f051a.js:746
    Xt @ 65ed3ccc18e0a6174aa03922462f051a.js:746
    G @ 65ed3ccc18e0a6174aa03922462f051a.js:746
    N @ 65ed3ccc18e0a6174aa03922462f051a.js:746
    n @ 65ed3ccc18e0a6174aa03922462f051a.js:746
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:2843
    L @ 65ed3ccc18e0a6174aa03922462f051a.js:670
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:670
    t.(anonymous function) @ 65ed3ccc18e0a6174aa03922462f051a.js:670
    n @ 65ed3ccc18e0a6174aa03922462f051a.js:2843
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:2843
    Promise resolved (async)
    n @ 65ed3ccc18e0a6174aa03922462f051a.js:2843
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:2843
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:2843
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:2843
    N @ 65ed3ccc18e0a6174aa03922462f051a.js:746
    n @ 65ed3ccc18e0a6174aa03922462f051a.js:746
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:2742
    L @ 65ed3ccc18e0a6174aa03922462f051a.js:670
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:670
    t.(anonymous function) @ 65ed3ccc18e0a6174aa03922462f051a.js:670
    n @ 65ed3ccc18e0a6174aa03922462f051a.js:2742
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:2742
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:2742
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:2742
    F.i @ 65ed3ccc18e0a6174aa03922462f051a.js:748
    commitLifeCycles @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    t @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    x @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    k @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    m @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    h @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    updateContainer @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    unbatchedUpdates @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    no @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    render @ 65ed3ccc18e0a6174aa03922462f051a.js:719
    require.2../polyfills @ 65ed3ccc18e0a6174aa03922462f051a.js:2849
    t @ 65ed3ccc18e0a6174aa03922462f051a.js:1
    require.484 @ 65ed3ccc18e0a6174aa03922462f051a.js:1
    (anonymous) @ 65ed3ccc18e0a6174aa03922462f051a.js:1

      StellarGuard
      Well the qr-code "transaction envelope" can be sent signed or unsigned. my_wallet is a prototype example that both reads and writes this format of "transaction envelope" qr-code that it can send signed or unsigned and also accepts and generates other qr-code operations and formats. Also there is stargazer that accepts some parts of this qr-code standard that include payments with a branch of stargazer that also accepts the escrowed payment version.

      But at present this extension of "transaction envelope" or any of the qr-code formats are not really fully supported or accepted as standard. It requires other programmers and users to find value in them to make use of them and tweak the ideas of standards we now have or don't yet have.

      @StellarGuard

      I like your idea.

      Looks like we could both benefit working together.

      I offer a way to issue transactions as links with cosmic link protocol and to sign them using Stellar Authenticator.

      You could issue transaction to be signed as URL & it would be safely handled by my platform.

      I could include native support for your service in Stellar Authenticator as an optional security measure.

      I designed those tools as an answer to webwallet hacks aswell.

      More info:
      https://galactictalk.org/d/1130-stellar-authenticator-sign-transactions-securely-phone-app-web-app

      The last link in my presentation will give you a complete idea of the design.

      Edit: I'll make the first release next week for testing purposes.

        PitchayasakSenachai Thanks for finding that -- it was an issue with how I was displaying transactions with memo text that I didn't catch locally. I've pushed a fix just now (as well as a new logo and color scheme ? ).

        You've also inspired me to look into React error boundaries a bit more so a simple error like this doesn't take out the whole page.

        MisterTicot Looking forward to trying it out. If it makes sense to integrate (mutually beneficial) I'm very open to external integrations. I've had another request now to add support for this service as a whitelabeled service, but I think I'm pretty far away from supporting that. If there is more interest I'll move it up my priority list though.

          StellarGuard

          Very nice.
          Well I think at this time we both have a lot to do so I propose we talk about it when things calm down a bit ?
          Is it good for you?

          5 days later

          Awesome work. I like that your tool allow pasting the XDR, so it can be used to sign any kind of transaction.

          Just to make sure I understand it correctly, you change all the thresholds to 20, the master key weight to 10, your server signing key weight is 10, an optional backup signing key can also be added with weight 10, and you put your donation address as a signer with weight 1 too, right?

          Do your server accept only this configuration, or could someone manually set the signers and weights in any way they want, keeping your signing key with weight 10?

          Edit: Do you plan on making it open source?

            5 days later

            matheusb-comp Sorry I missed this!

            You're correct about the signer weights. 20 thresholds, master + account-specific signing key to 10, and static key to 1.

            The static key with weight 1 (currently the donation address... but doesn't have to be -- I just generated the vanity address with "GUARD" and was happily surprised that it also contained a "ME" near the end so I figured I'd use it for both) - is meant to be used as an indicator for 3rd-party wallet integration that the account has StellarGuard enabled -- it's not actually required to function.

            You can set up the signer configuration in any way you want as long as the StellarGuard key is present (unique key per user).

            I do eventually plan on eventually open sourcing it, but I've got lots to clean up before I do. Also need to consider the likelihood that someone would just copy it completely. Depending on how well received it is I may introduce paid plans with additional features so I'd like to build up some user base first to have a competitive advantage before just anyone could copy it.

            20 days later

            StellarGuard now has direct integration with Stargazer, allowing you to submit transactions with Stargazer that you authorize with StellarGuard (StellarGuard listens for Stargazer signing requests and then creates a corresponding StellarGuard request).

            Check out: https://stellarguard.me/supported-wallets

            If you're a wallet developer and are interested in integrating with StellarGuard, let me know here or email developers@stellarguard.me. There's also a JS SDK for easier integration: https://github.com/stellarguard/stellarguard-js-sdk

            6 days later

            @StellarGuard Correct me If i'am wrong. Stargazer is a mobile wallet right ? How does StellarGuard protected the private key in anyway ?
            To be able to send lumens I need to firstly import my wallet by entering my wallet secretKey INSIDE the app. Bam my private key is compromised already in case the devs are malicious.

            Is StellarGaurd in that scenario only useful to avoid people that got in possession of the user's phone to avoid spending xlm ? If So isn't this a bit redundant since the phone has a PIN lock + (probably the app) has a PIN lock as well) ?

              CrptoCraze

              It protects you be requiring two signatures instead of just one. Second signature is done by StellarGuard, if-and-only-if you're able to pass the 2FA.

              CrptoCraze I'm glad you asked! Im actually writing a blog post about how it all works and why it is useful, even if you are already using a mobile wallet or a wallet with security features. It is also clear that I need a better explanation on the home page as well, so thanks for that.

              As @dzham mentioned, StellarGuard sets up multisig on your Stellar account (this is a Stellar protocol feature, not a StellarGuard feature). Transactions then require you to have both signatures in order to be considered valid - your own secret key and another key that StellarGuard generates just for your account. So let’s imagine a scenario where you import your secret key into a compromised wallet (or you get a virus on your computer or phone and it steals it): the attacker only has one of the keys necessary to make a transaction, the other key is safely locked in StellarGuard — the attacker can submit a transaction but wont be able to authorize it without also knowing your StellarGuard credentials AND having access to your two factor auth code on your phone.

              So you start seeing transaction requests that you didnt make in StellarGuard, you know your key is compromised and you can move your lumens to a new safe account. StellarGuard!