Public data in Gun can be read by anyone. They may not have a full copy of the database, but if someone knows your public key they can request everything under your account. This is by design and makes account migration much easier if someone needs to reset their password.
Private data in Gun can also be read by anyone, but the difference is that it's encrypted. It should only be possible for users who you've shared data with to decrypt your messages. RSStream doesn't create much encrypted user data yet, but it does support a mechanism for encrypted data recovery.
The recovery method built into the application is to listen for public key changes on accounts you already follow. This is possible because account codes don't change. If someone you know needs a password reset and creates a new public key, you know that they've lost effectively all the encrypted data on their account. What you're able to do as a contact is re-share your copy of any data you previously encrypted for them. This is done automatically because RSStream knows what data was previously shared and now has their new public key with which to encrypt the same data. If all users do this they will effectively restore all previous conversations.
Here's what the code looks like for that:
const updateAccount = (account, accountCode) => {
if (!account) return
let check = {
pub: account.pub,
alias: account.alias,
name: account.name,
ref: account.ref,
host: account.host,
}
// Check this account against the users list of contacts.
const contacts = user.get("public").get("contacts")
contacts.once(async c => {
if (c) delete c._
let found = false
for (const contactCode of Object.keys(c ?? {})) {
if (contactCode !== accountCode) continue
found = true
const contact = await contacts.get(contactCode).then()
if (contact.pub === check.pub) break
// If the public key has changed for this contact then store their
// new account details and re-share encrypted data with them to
// help restore their account.
contacts.get(contactCode).put(check, ack => {
if (ack.err) console.error(ack.err)
})
gun
.user(contact.pub)
.get("epub")
.once(oldEPub => {
if (!oldEPub) {
console.error("User not found for old public key")
return
}
gun
.user(check.pub)
.get("epub")
.once(epub => {
if (!epub) {
console.error("User not found for new public key")
return
}
const shared = user.get("shared").get(contactCode)
shared.once(async s => {
if (!s) return
delete s._
const oldSecret = await Gun.SEA.secret(oldEPub, user._.sea)
const secret = await Gun.SEA.secret(epub, user._.sea)
for (const key of Object.keys(s)) {
if (!key) continue
const oldEnc = await shared.get(key).then()
let data = await Gun.SEA.decrypt(oldEnc, oldSecret)
let enc = await Gun.SEA.encrypt(data, secret)
shared.get(key).put(enc, ack => {
if (ack.err) console.error(ack.err)
})
}
})
})
})
break
}
// Add the new contact if we referred them.
if (!found && account.ref === code) {
contacts.get(accountCode).put(check, ack => {
if (ack.err) console.error(ack.err)
})
}
})
}
// Listen for account changes to add new contacts, update existing contacts.
gun.user(pub).get("accounts").map().on(updateAccount)
Why email?
If you've locked yourself out of an account, there's no way to fix the state of a distributed database that would allow you to log in again. Luckily data recovery is still possible and starts by providing your email address when you create an account.
Email provides a way to verify ownership of your account code. Any verification method that is external to Gun would be fine, but email is the easiest to set up. Your email address was associated with your account code when your account was created. I shared some server code in an earlier post that stores your account data, but the actual code looks more like this:
The first line in the function shows that your email address is encrypted when stored in Gun, it can only be accessed via the host account on the server. The validation code also needs to be encrypted, otherwise we couldn't prove that the validation request came from an email that was sent to you, since anyone would be able to create the link from data available in Gun.
Once your email is validated, if you ever need to reset your password then RSStream can send you a reset code. The reset code is stored under your account code in the host's account data, which also has your previous public key. Now when you follow the password reset link in an email, a new account will be created in Gun but the application has enough information to associate the old and new accounts. There is public data associated with your account that is not encrypted, that can also be copied over just by knowing your old and new public keys. What about private data though, is that lost along with your old account? Next we need to look at encrypted user data.
Encrypted user data
Private data in Gun can also be read by anyone, but the difference is that it's encrypted. It should only be possible for users who you've shared data with to decrypt your messages. RSStream doesn't create much encrypted user data yet, but it does support a mechanism for encrypted data recovery.
The recovery method built into the application is to listen for public key changes on accounts you already follow. This is possible because account codes don't change. If someone you know needs a password reset and creates a new public key, you know that they've lost effectively all the encrypted data on their account. What you're able to do as a contact is re-share your copy of any data you previously encrypted for them. This is done automatically because RSStream knows what data was previously shared and now has their new public key with which to encrypt the same data. If all users do this they will effectively restore all previous conversations.
Here's what the code looks like for that:
Why email?
Email provides a way to verify ownership of your account code. Any verification method that is external to Gun would be fine, but email is the easiest to set up. Your email address was associated with your account code when your account was created. I shared some server code in an earlier post that stores your account data, but the actual code looks more like this:
The first line in the function shows that your email address is encrypted when stored in Gun, it can only be accessed via the host account on the server. The validation code also needs to be encrypted, otherwise we couldn't prove that the validation request came from an email that was sent to you, since anyone would be able to create the link from data available in Gun.
Once your email is validated, if you ever need to reset your password then RSStream can send you a reset code. The reset code is stored under your account code in the host's account data, which also has your previous public key. Now when you follow the password reset link in an email, a new account will be created in Gun but the application has enough information to associate the old and new accounts. There is public data associated with your account that is not encrypted, that can also be copied over just by knowing your old and new public keys. What about private data though, is that lost along with your old account? Next we need to look at encrypted user data.