Encrypt content before sending transactions
Opened this issue · 2 comments
Feature description
Currently all content in the transactions are not encrypted and public. Although the system is censorship resistance, it still enable trace of content delivery which link back to a certain user. As Mooncake
holds the private key of the user, the content can be first encrypted and then put inside the tx message before broadcasting. The user sign the encrypted message rather than the original content. The content in the tx can be decrypted by Mooncake
using the corresponding users's public key when the users load the data. The content being encrypted should be a salted string instead of the plain content so that other users can't decrypt it using users public key as they don't know the secret salt.
One scenario this feature can benefit is as below.
- User posted a post
- User regrets and deletes it
- User's post and deletion are all hidden in the txs where you can't trace from the
Mooncake
or on chain.
Implementation proposal
Mooncake
holds a secret salt. This can be the original value of the hashedsubspace
or another piece of random string. It acts like theapp_id
andsecret
of a Facebook app.- Every time a user posts a content, the content is salted with the
secret
and encrypted. Then the post message holds thisencryptedSaltedContent
and broadcast.
saltedContent = secret + content
encryptedSaltedContent = encrypt(saltedContent, privKey)
djuno
should still store theencryptedSaltedContent
to keep itself as the chain parser.- When
Mooncake
displays the content, it decrypts with poster's pubkey and remove thesecret
content = remove( secret, decrypt( encryptedSaltedContent, pubkey ) )
The secret should only be available in the binary build of the Mooncake
, it should not be stored on GitHub
. This should be purely done during build time.
Comments about the feature description
Although the system is censorship resistance, it still enable trace of content delivery which link back to a certain user.
What do you mean by that? All accounts are public, so what does "trace of content delivery" mean here?
Comments about the implementation proposal
I think the implementation you proposed is not fully correct.
If we only used asymmetric encryption, the sailt wouldn't do much about the privacy:
let saltedContent = secret + content
let encryptedContent = encrypt(saltedContent, privKey)
If we only do this, then everyone would be able to access the saltedContent
by doing:
let saltedContent = decrypt(encryptedContent, pubKey)
Then, since this would be a plain text, they could simply remove the secret
by guessing which value it has (this can be done easily by comparing different unencrypted post contents).
The best way would be to use both a symmetric and asymmetric encryption methods:
// When sending
let aesEncrypted = AES256.Encrypt(postContent, secret)
let pubEncrypted = RSA.Encrypt(aesEncrypted, privKey)
// When receiving
let pubDecrypted = RSA.Decrypt(pubEncrypted, pubKey)
let aesDecrypted = AES256.Decrypt(pubDecrypted, secret)
At this point tho, the RSA encryption would just be a useless overhead, since all the Mooncake installations would already know the secret
value. So, this can be easily simplified as:
// When sending
let aesEncrypted = AES256.Encrypt(postContent, secret)
// When receiving
let aesDecrypted = AES256.Decrypt(pubDecrypted, secret)
Problems with this feature
As far as I see it, implementing this feature would lead to some problems:
- If the
secret
present inside Mooncake gets lost, then all the content would become unreadable. - If an attacker decompiles the application and reads the
secret
leaking it, it would make the whole system useless. - The length of the post should definitely be lower than 500 characters, since encrypting it with a salt results in a cyphertext being longer than the input.
Conclusions
I personally don't think this feature is necessary, also because I do not understand what it achieves more than we have right now.
Implementing it would only mean making Mooncake slower (encryption and decryption on mobile devices is a computationally intensive task). I think the advantages/disadvantages trade-off is too low.
The goal is to hide the content in the transactions so that only Mooncake can reveal content inside the state where other public users can't trace back by only accessing the transactions.
I believe in performance-wise it won't be an issue. There are packages utilizing the smartphone hardware for encryption/decryption.
https://pub.dev/packages/cryptography
https://pub.dev/packages/kms
From the Apple's iOS Security Guide, the process of AES processes should be pretty fast (I couldn't related information on Android though.).
https://www.apple.com/in/business/docs/site/iOS_Security_Guide.pdf
Possibility of losing the key and reverse engineering of the app are at a high risk. After some studies, I agree the trade-off is not worth taking at this stage. Let's put this aside first. We keep Mooncake as fully open for now as it should be. We can come back to this issue after we gather more feedback in the future.