StealthNote
NoirCon 2 Berlin 2025 · June 2025 · 15:14
Aztec engineer Saleel Pichen breaks down StealthNote, an app that lets users post anonymously while proving they belong to an organization. He explains how zero-knowledge proofs make that possible without revealing identity and walks through the privacy technology underneath. The session was a technical keynote at NoirCon 2.
Speakers
Topics
From NoirCon 2 Berlin 2025, hosted by Aztec Network.
Transcript
[Music] Hi. Um, yeah, I'm Salil. I work at ESTC and uh, today I'm going to talk about Stealth Node. It's it's an application where you can send anonymous messages but by proving you are part of a company. So you can post as uh someone from Google or someone from Aztec. Um and you don't reveal your name or any personal details but you still prove you belong to this company.
Yeah. Um it's not like a it's it's like there is a project called team blind. It's like a zk version of that and it's not like a unique idea I came up with. Um but yeah, I think like this is a good app in No. So yeah um what you can do is you can send um anonymous messages without revealing your personal information and it works by proving that you have a company Google account uh without revealing your details. So you need your company needs to have be using Google workspace uh for you to do this for you to use the application. Um and what we are doing is we are in ZK we are proving that you own a Google account from the company
domain. Um and then don't reveal any personal details but just reveal the domain and then you can post messages. Um yeah we'll we'll start with the demo. Yeah. Um so this is the application you can you can open stealth node.xyz and try it yourself. So these are the messages posted by others and like here I'm like signing in with my Google uh with my Aztec email and in in the browser it's generating a proof that I own this Google account. So it's it's not sent to any server. It's it it all happens in the browser and it it takes
like 20 seconds to generate the proof and yeah it's done now and then uh you can you can send any message. So it's like Twitter but then uh instead of your username it's like someone from astic labs. Uh you also have this verify option to verify the messages sent by other people. So you you're not trusting any server. You can you can verify all the messages uh in the application. So it works using something called JWT. Uh so when you sign in with Google uh they return something called JWT. It's like a authentication token um which is like a signature on your account details. So in
the payload you have the name the email um all this data and then you have a signature from Google saying that uh this this data is attested by Google. So um people use JWTs like like web two applications use JWTs to verify users. So when you sign in with Google to to some web two apps they can they can identify and verify your email and that's basically how you create accounts. Um so like if if you share this JWT you are basically proving that you have a valid Google account with company email but uh we don't want to do just this because you have to share the whole payload which also includes your
name. So there is no privacy. Um so what we do is we we verify this JWT in ZK. So we have a ZK circute that verifies the JWT is valid which is basically a RSA signature verification and then we extract the email from the payload and just extract the domain from the email and and like make that public. So all the information in the payload remains private. Only the domain is made public right. Um but we also want to bind our message to the proof. So in JWD we have
something called nons. So uh when you send people to the sign in with Google flow you can you can set some random value as nons and in the JWT payload they include that. So if you if you set hash of the message as announce then you you can basically prove that this message was also sent by the same account who who has this um who who owns this um JWT like you you're proving that you send a message. Um yeah so if you if you do that um then like we we have to generate a new new proof for um every message. So like for for each message you'll have to sign in
with Google and then wait 20 seconds to generate the proof. So to avoid that we have something we use a trick like like we we just generate some fmoral keys like some temporary uh key and then save that to the local storage and then you you sign this public key with Google. So you are so basically in your JWT you are attesting to a random public key and then you use this key to sign any number of messages. So um yeah so one one one proof and like any number of messages.
Uh the problem with this is that all the messages that's um signed by one one furl key will be linked can be linked and like um the solution to that is like to give users the option when they want to change the change the key. So in sales node you have this option like you can get a new identity any time and then yeah your previous messages are no long no longer linkable to the new identity. Okay. So another problem is um like Google can deanonymize you u through the non. So we are sending your public key um to Google and then they know which
message was sent by which public key and basically Google can figure that out like which person sent the message and then they can also work with your um organization to deanonymize. Um so um I mean the yeah one little trick there is to uh instead of like setting hash I mean the nons uh emerald key you hash it with a salt and then set that as the nons like this is this is what you do in the zk circuit. you are you give like the JWT header and payload um and the JWT pup key and signature and then in the circuit you are verifying the JWT
which is basically you hash the payload and uh header and then you do a RSA verification on on the um on the message hash. So you're you're proving the JWT is valid and then um you extract the nons and you prove it's the hash of your public key and assault and in the last step um you're you're like the domain is a public input. So you're basically prove that uh the domain of your email field is same. So um yeah, you're you're basically creating a proof that there is a valid JWT and um that's that has an email theme where the domain is uh what you
say it is. So domain is public. Okay. So uh the the flow is like so first time like when when a new user come um in the browser they are generating a new key and um they do the oath flow sign in with Google uh Google will return the JWT you create the proof and uh send it to a server. So the server will verify the Z proof and then save the public key to a database for for that domain.
Um and then later when the user is posting a message they are um signing the message with their key pair they are like temporary key pair and then they will send the message the signature and their public key to the server. Um server will verify the message signature. So this is this is just like um EDSS signature. They will verify the signature and then they also make sure the public key is previously registered. So um by that step they are like verifying the user user is from the same domain and then they will uh the server will save the message to the database.
Um later when like other people come to the website they can verify all the messages. Uh what happens at that time is um they query the server for the message um the signature I mean the server will send them the message signature and public key. So you first verify the message signature then you verify the zigg proof and then you you make you like make sure the public key in both matches. So yeah you're you're verifying the message is signed by a public key and that public key as part of a JWT signed by Google. So effectively proving it's someone from that company uh who who made the message.
Yeah. Um some trust assumptions. Um yeah on the server there is only one assumption on on the liveness. Uh yeah server cannot create any message uh like on behalf of other company because like in in the browser all like all the messages are verifiable. So they cannot forge messages. Uh so the only assumption is nonliness. They can censor data like it's a database basically. They can remove data. You can replace it with IPFS or a blockchain. Uh yeah so it's uh it's like that and there is also trust assumption on Google basically Google is signing issuing the JWT so we are trusting them they are
issuing it correctly they can issue any JWT pretending to like for any domain they want um so yeah we have some trust element on Google here um yeah and uh some problems um yeah there are some edge cases when your anonymity can be broken. Uh so one is like if you are the only person from the company who use the app and send a message then Google and your organization can work together maybe to find who that person is if it's only one person. Um there is a solution to it.
It's like yeah you don't use sign in with Google. You use some other techniques like ZK email to prove you are part of the company. Um yeah I I'll talk more on that. Um but yeah one other issue is uh JWT key rotation. So the key that Google used to sign JWT they get changed like every 3 or 4 weeks. So messages before like 1 month ago like before 1 month it's you cannot verify them because you no longer have the public key for um like for for these deliveries.
Yeah. Um, so yeah, signing like proing your product is like it's like the first version like but like the whole application is genuine. You can do the same with any kind of proofs. Um yeah like uh pro prove your uh part of organization using emails or you post also using emails. You can prove that you're following a city or whatever with also like you can and then you can like basically just like any source.
Yeah. So I like the I have like a new version of this where um you can choose to not use Google but use email to prove that you you belong to some company and like it works with ZK email. So like emails also have signatures um like all emails are signed by a protocol and Z emails. So like verifying you have a email and you extract the document just like ID and you proving um so your information I have
so like you come in last two weeks uh the lobby to prove your profile by using email. So let's say you got an email from your friends, you can just download that and then you um uh you know Google the only uh it's still fine. No one can find you.
Um yeah uh so yeah hopefully in two weeks. Um yeah uh that's it if you have any questions. Okay. So how do you prevent your play attack? Yeah that's why we have this we use this props. Um so any time you generate like when you send someone to Google it is a hash of your property.
So in the security [Music] [Applause] People next [Music] [Applause]