I don't know how Zencash works. For all I know they store all the data in cleartext. But I'm going to explain how this can be done securely to some extent, but with fundamental flaws nonetheless.
The fundamental tool here is a key derivation function. A key derivation $F(P,L)$ calculates a value from a secret key $P$ and a public label $L$ such that:
- It is unfeasible to calculate any part of $P$ even if you happen to know the value of $F(P,L)$ for many values $L$.
- It is unfeasible to calculate any part of $F(P,L)$ without knowing $P$, even if you happen to know the value of $F(P,L')$ for many $L' \ne L$.
The following protocol allows a site to store some data without being able to decrypt it, using your passphrase as the sole input.
- You enter your passphrase $P$ on the web page. The browser does not send the passphrase to the server.
- The browser calculates both $A = F(P, \mathtt{"address"})$ and $K = F(P, \mathtt{"encryption"})$.
- The browser sends $A$ to the server. The server uses $A$ to retrieve an encrypted blob of data and sends this encrypted blob to the browser.
- The browser uses $K$ to decrypt the data.
The server is not able to decrypt the data in this scenario. Note that you need to trust that the Javascript code sent by the server is doing the right thing. If the server is compromised, it could start sending new Javsscript code that does send the passphrase to the server.
The fundamental flaw with this approach is that someone can easily steal money by guessing someone's passphrase. This is inherent in using a passphrase as the sole identification method: it permits a mass untargeted attack. If you can guess anybody's passphrase, you can retrieve their data. You don't need to know who they are: just keep guessing potential passphrases until you find one with a non-empty wallet.
Reasonable systems that use a passphrase to secure something always include a salt in the label for the key derivation. The salt is unique per passphrase. It does not need to be secret, but when you come back to the site, you'd need to re-use the same salt. With a salt, it is not possible to carry out mass untargeted attacks. If the attacker guesses that squeamish ossifrage
is a likely passphrase, they still need to try it out with every possible salt value.
For completeness, note that when deriving a key from a passphrase, in addition to using a salt, it is necessary to apply a stretching mechanism to make the computation slower. This is the same problem as password hashing. In fact, password hashing and password-based key derivation are very close cryptographic problems.
If, instead of a human-chosen passphrase, the derivation was based on a sufficiently long randomly generated string, then the protocol above would be secure. The problem with human-chosen passphrases is that they have very little entropy: it's relatively easy to enumerate all likely passphrases. This is compounded by the fact that in this scenario, the attacker only cares about the weakest passphrases, they're generally not trying to attack a particular user who may have been extra careful to pick a strong passphrase. But even a user who chooses, say, a passphrase made of 4 random words from a dictionary of 100,000 (which includes some pretty obscure words) has only reached 66 bits of entropy, whereas the standard minimum size for a random string used as a secret is 128 bits and for a financial application 256 bits would be preferred. And if the passphrase which is a grammatical sentence, the amount of entropy is vastly reduced.