Non-custodial wallet with NO private key, Libra’s vision

TL;DR: Zengo releases a Proof-of-Concept of the first Threshold Signatures wallet for Facebook’s Libra testnet

The first ever Threshold Signatures Libra transaction (source:

Unless you live under a rock, you already know about Facebook’s ambitious entrance into the cryptocurrency industry. Facebook recently announced Libra, “A simple global currency and financial infrastructure that empowers billions of people.” 

Libra is a cryptocurrency and is Facebook’s attempt to create digital money. Once something is digital, it can be easily sent over the Internet and transacted in seconds.

Facebook plans to integrate Libra within its products (e.g. WhatsApp), thus allowing money to be sent as easy and frictionless as any other type of digital data,  such as sending texts, pictures, or videos.

Libra in WhatsApp (source:

However, in order for Libra to make digital money mainstream, Libra must solve cryptocurrency’s biggest challenge: how to manage the private key?

First, Facebook is providing its own “custodial” wallet Calibra. Calibra provides a convenient option for private key management, but users must relinquish sole control of their assets and go through a full KYC (government ID based registration). What if Libra wanted to provide a non-custodial option? Would that be possible? Would 2 billion users be able to deal with “seeds,” “backups,” mnemonic phrases, and advanced security? 

The question has already been asked repeatedly and the answer matters.

The private key management problem

Private keys enable users to sign their cryptocurrency transactions — Libra is not any different in that perspective. We tested this by using Libra’s demo wallet source code

The code implements a simple wallet which interacts with the Libra testnet (a test blockchain network) for sending and receiving test money. 

The wallet creates a private key and backs it up on the computer’s hard drive as a list of 24 words (AKA mnemonic) as seen in the picture below. 

Libra wallet generates a mnemonic to represent private key

Until recently, users had to choose the lesser of two evils between the following private key management options:

Option A: Users can choose to take full control and responsibility for their private key. With this option, users must keep their private key secret to avoid theft and at the same time highly available to avoid loss.

This leads to complex and imperfect solutions such as the previously mentioned mnemonic phrase which users must write down and protect to back up their wallet. Clearly, this kind of solution is relevant only for relatively technical users and not suitable for the mass adoption of crypto.

Option B: Alternatively, users can give their keys to a custodial service and outsource all the complexity associated with private keys. This is why most people leave their funds on exchanges. However, with this option, users lose all control over their funds as the service (if it gets hacked or goes rogue), is able to unilaterally spend its users’ funds.

To read more about this dilemma, please see our TechCrunch OpEd.

Since Libra’s mission is to serve “billions of people,” they simply cannot let their end users handle the private key. Therefore, they had to choose the second option and create a fully custodial solution: Calibra

Zengo and Threshold Signatures Scheme (TSS)

We at Zengo believe that there is another and much better way to manage private keys. 

We believe that there is a way that is both secure and friendly enough to hide the complexity of the private key and make it suitable for mass adoption. 

With TSS there is no private key, while still being non-custodial

To do so we are using a Threshold Signatures Scheme (TSS). TSS removes the burden of the single atomic private key and splits the responsibility between multiple parties. 

Each of the parties generates its own secret and uses this secret to distributively sign a transaction without revealing the secret to the other parties. (For a high-level overview of TSS please refer to our blog post)

A few weeks ago we released our mobile app: Zengo. By distributing the secret between the user’s device and the Zengo server, Zengo relieves users from the burden of managing their own private key while ensuring that the server cannot unilaterally spend the user’s money. (you can read more about the solution and security here). With this approach, we can provide a non-custodial wallet but with a “custodial-grade” approach. 

Our wallet already supports TSS for Bitcoin and Ethereum (more coming soon!!) and we have made some open source Proof of Concept (PoC) implementations for Binance, Zilliqa, and Tezos cryptocurrencies. 

We are now adding Libra to this list, by developing and releasing an open source project to add TSS support to Libra.

Introducing Libra with TSS 

For this Proof-of-Concept (PoC) project we used our open source implementation of TSS for EdDSA signatures. We had created an open-source TSS wrapper for EdDSA for the specific case of two parties comprised of a client and a server. It should be noted though, that we have support for multiple parties for EdDSA including a generic MPC (secure Multi-Party Computation) network layer. We plan to extend this solution in the future.

Two party EdDSA key generation and signing (source

We have invested a lot of resources into implementing TSS and making it compatible and reusable for different kinds of blockchains and signatures algorithms. This compatibility allows us to rapidly onboard and add TSS support to new blockchains. For example, we used this code to create the Tezos TSS PoC.

It should be noted that the concept of TSS is not strange to Libra, as the blockchain may use it internally by the validators as part of the consensus process. In our implementation, we introduce TSS in the transaction signing level, making it available to users too. 

We were happy to find out that Libra code is implemented in Rust, which is our favorite language for hard core cryptography, and allowed us to easily integrate our TSS cryptographic code with the Libra code. The PoC Rust code is open source and publicly available.

To add TSS support we need to remove the notion of a seed. (You can see there is no more client.mnemonic file). Instead, we consider a client and a server, each generates its own share. The server acts merely as the co-signer in the two-party signing protocol, and the client component already exists within Libra Core’s code base. We used our EdDSA client-server API to plug it into the two components.

  • Generation: First we set up a server which acts as the co-signer in the two-party signing protocol.
Launching the co-signing server

Next, we modified Libra Core’s client code so it would call our EdDSA client API to generate a share by interaction with the server.

Modified client code for two-party key generation

At the end of the two-party key generation protocol, the client and the server both possess an aggregated public key, which can be seen as their shared public key from which a Libra address is derived.

  • Signing: We modified the client’s code so it will call the two-party sign API, which again interacts with the server.
    Most of the code would be simply converting the different data types so that they will match Libra Core’s API:
Modified client code for two-party key generation

The whole process can be seen in the video below. The upper side of the video shows the server process and the lower side shows the client code. The usage of the client is exactly the same, but you can see the server involved when addresses are generated and transactions are signed.

Libra TSS demo (source)


In this experiment, we made it possible to send/receive Libras over the testnet using TSS. Obviously, this experiment is only based on a testnet and we will have to explore further once Libra makes its mainnet available. Additionally, there is no user interface in this PoC and it goes without saying that a proper UI is required for a usable product.  

Calibra seems like a great option for a custodial first approach. We expect non-custodial solutions to follow suit and offer more alternatives to Libra users.

All in all, it took us only a few days to add TSS support to Libra. The experiment successfully demonstrated how our generic TSS infrastructure can be applied to a new blockchain. We plan to keep adding support for more assets to Zengo.