I’ve been thinking about a ( hypothetical ) blockchain that uses a Turing complete STARK system such as risc0 for smart contracts, but I’ve been a little bit stuck on understanding how to encrypt token balances if I were to make a token smart contract.

Then I read about this great post on the forum:

That was a great intro to the idea, but it looked like I still couldn’t have a transaction submitted by John update the encrypted balance of Jane’s wallet, without having the encryption key. ( It seems I could do multiplication if Jane shared m with John, but not addition, which would require sharing both m and g with John, allowing him to decrypt the balance, which defeats the point. )

“Homomorphic” was a new word for me, though, that turned out useful in searches! I found this library which uses the Paillier scheme which has separate encryption and decryption keys, allowing John to encrypt a value with Jane’s encryption key, and add his value to Jane’s encrypted balance, while never revealing the end total of Jane’s balance. Combine that with a risc0 proof that the token program was executed un-modified, and I think I have what I need to allow token transfers to be executed un-trustedly on a client machine, before submitting the resultant changes to the wallet balances to the blockchain.

Does anybody know of any reason Paillier wouldn’t be suitable for this kind of use-case?

I’m very new to a lot of this, so I don’t know what I don’t know yet, if you know what I mean. In other words, I’m not sure if there are questions to ask that I don’t even know I should ask yet, so I figured I’d post here and see if anybody had any thoughts!

In Paillier encryption the public key is n = pq: the product of two large primes, just like in RSA. And just like in RSA, the secret key can be found if you know p and q. The point is that everybody’s secret key is different, and therefore so is their public key. And so an encryption under John’s public key will not be compatible with an encryption under Jane’s public key.

You can get around this obstacle, but the point is that it’s an obstacle you do not need to have if you switch to another encryption (or indeed: commitment) scheme. Here’s what you would need to do to solve it:

John splits his balance-ciphertext into two parts, the outbound and the change, and provides a zero-knowledge proof that the two parts sum to the original balance, and that neither part is negative.

John then encrypts the outbound coins under Jane’s public key, and adds a zero-knowledge proof of correct encryption.

Jane (and the rest of the network) can homomorphically add the incoming payment ciphertext to Jane’s balance ciphertext.

Hi @zicklag
Great to know you liked the article. In my suggestion, I would not advise you to use plain Homomorphic encryption due to two reasons. First, you would be very limited in terms of the types of computations you can perform, only + and *. No -, / or % operator would be available. Second, you would be on your own in terms of security, since no one does it like you intend to.

I would suggest looking into zk-proofs (which also uses Homomorphic encryption btw). Zk will give you general computation ability, and you will be able to selectively hide/unhide whatever info you want.

Please note ZK will only enable you to build secure smart contracts, but not help you with encrypting token balances on-chain. For that, you will need asymmetric encryption (IES).
This is a problem we are working on btw at Electron Labs.