
O que o relay da SSP pode e não pode ver
A SSP é uma carteira de dois dispositivos. Sua extensão de navegador guarda uma chave, seu telefone guarda a outra, e nenhum dos dois move fundos sozinho. Mas esses dois dispositivos precisam conversar, e fazem isso por um servidor que nós operamos, chamado relay.
Esse servidor é o lugar óbvio para fazer uma pergunta desconfortável: se tudo passa por uma infraestrutura operada pela empresa da carteira, o que exatamente essa empresa vê?
É uma pergunta justa e merece uma resposta específica em vez de uma tranquilizadora. Então aqui está o que há de fato no código.
O relay não pode assinar nada
Comecemos pela parte que mais importa.
O relay nunca recebe uma chave privada. Nem cifrada, nem dividida, em forma alguma. A chave da sua carteira fica na extensão do navegador e a chave do aplicativo fica no seu telefone; as únicas coisas que atravessam a rede são chaves públicas, dados não assinados e assinaturas que já foram feitas nos seus dispositivos.
Isso não é um compromisso de política, é um compromisso estrutural. O multisig dois-de-dois exige as duas assinaturas para mover fundos, e o relay não possui nenhuma das duas chaves. Um relay completamente malicioso — o nosso, comprometido, ou substituído por um atacante — continua incapaz de produzir uma transação válida, porque produzi-la exige segredos que nunca lhe foram enviados.
Essa é a garantia. Tudo abaixo trata do que o relay de fato manipula, um conjunto mais estreito, mas genuinamente não vazio.
O que passa por ali, e por quanto tempo
O relay guarda quatro tipos de registro. Dois deles se apagam sozinhos.
Dados de sincronização, quando você pareia seus dois dispositivos. Carregam a cadeia, sua identidade de carteira, a chave pública estendida do aplicativo, a identidade WK resultante, os nonces públicos, o endereço gerado e o xpub de recuperação com a sua assinatura.
Dados de ação, quando você está assinando algo. Carregam a cadeia, o caminho de derivação, sua identidade WK, o tipo de ação, a carga em si e os UTXOs pertinentes.
Ambas as coleções têm no MongoDB um índice TTL fixado em expireAfterSeconds: 900. Quinze minutos. O banco apaga o registro aconteça o que acontecer — não é uma rotina de limpeza que alguém precisa lembrar de rodar, e não é uma promessa numa política de privacidade. É um índice, imposto pelo próprio banco.
Tokens de notificação push, para que seu telefone possa ser acordado quando houver algo a aprovar. Esses persistem, porque um token que expirasse a cada quinze minutos seria inútil.
O xpub de recuperação, um por identidade, sem expiração alguma. Isso é deliberado e o código diz: ele existe para que a carteira possa buscá-lo quando precisar, e não apenas nas breves janelas em que os dois aplicativos estejam acordados.
A parte sobre a qual devemos ser francos
Olhe de novo aquela carga de sincronização. Ela contém uma chave pública estendida.
Um xpub não é uma chave de gasto e não pode autorizar uma transação. Mas não é coisa nenhuma. A partir do xpub de uma conta dá para derivar todo endereço que aquela conta um dia usará, o que significa que quem o tiver pode observar todo o saldo e o histórico de transações daquela cadeia. É acesso de leitura à sua vida financeira naquela conta — exatamente a ligação que a privacidade on-chain consiste em evitar.
A carga de ação é igualmente concreta. Enquanto você assina, o relay manipula a transação não assinada: para onde o dinheiro vai, quanto, e a partir de quais saídas.
Então o resumo honesto não é «o relay não vê nada». É:
O relay não pode gastar seu dinheiro, e por quinze minutos de cada vez ele consegue ver o que você está fazendo com ele.
A janela de quinze minutos é a mitigação, e é significativa: ela limita quanto histórico pode se acumular num só lugar. Mas durante essa janela os dados estão lá, e preferimos dizer isso com clareza a deixar «não custodial» fazer um trabalho retórico que não conquistou.
O princípio de projeto que vale emprestar
Há um comentário no serviço de recuperação que capta a arquitetura melhor que qualquer diagrama:
a carteira verifica essa assinatura contra a chave pública de identidade que ela mesma deriva, de modo que este armazenamento não é confiável.
O xpub de recuperação é guardado junto de uma assinatura destacada que a SSP Key fez sobre ele. Quando a carteira o busca, ela deriva de forma independente a chave pública de identidade e confere a assinatura por si. Se o relay devolvesse um xpub diferente — por comprometimento, por uma falha, ou por substituição deliberada —, a assinatura não verificaria e a carteira o rejeitaria.
O relay é tratado como um cano não confiável pelo software que depende dele. Essa é a maneira certa de construir sobre infraestrutura que você mesmo opera, porque significa que seu próprio servidor estar errado não vira problema dos seus usuários. É também o padrão a procurar ao avaliar qualquer carteira: não «eles prometem se comportar?», mas «o que acontece se o servidor deles se comportar mal?».
O que um relay hostil poderia de fato fazer
Vale ser concreto sobre o modelo de ameaça real.
Ele poderia observar. Dentro da janela TTL, seu xpub e sua transação pendente. Isso é exposição de privacidade, não risco de roubo.
Ele poderia censurar. Recusar-se a passar mensagens entre seus dispositivos, o que impediria você de assinar novas transações pelo caminho normal. Irritante e perturbador — e não é o mesmo que perder algo. Suas chaves continuam suas, seus fundos continuam na cadeia, e caminhos de recuperação existem justamente porque o relay pode não estar lá.
Ele poderia mentir, e falhar na maior parte. Substituir um xpub de recuperação é derrotado pela conferência de assinatura descrita acima. É por isso que essa verificação importa.
Ele não pode assinar. Sem chave, sem assinatura, sem transação.
O pior caso realista é vigilância e interrupção, não perda. Essa é uma posição bem melhor que a de um serviço custodial, onde o pior caso equivalente é o dinheiro ter sumido. Não é o mesmo que «ninguém consegue ver nada», e confundir as duas coisas é como as pessoas acabam com um retrato falso da própria privacidade.
O que você pode fazer quanto às partes visíveis
Entenda o que o pareamento expõe. Sincronizar uma cadeia significa que um xpub daquela cadeia transita pelo relay. Esse é o custo de o projeto de dois dispositivos funcionar.
Lembre que a janela é curta, não nula. Quinze minutos por ação é um limite, não uma ausência.
Trate o xpub de recuperação como permanente. Ele é guardado sem expiração por projeto, e é material de chave pública com uma assinatura verificável anexa — mas é duradouro, e você deve saber disso em vez de descobrir.
Julgue a arquitetura, não a garantia. A pergunta útil sobre o servidor de qualquer carteira não é se a empresa promete discrição. É se o software perceberia que o servidor mentiu. O nosso confere assinaturas em vez de confiar em respostas, e você pode ler isso no código em vez de acreditar na nossa palavra.
O que mais gostaríamos que fosse entendido é o formato da troca. Uma carteira de dois dispositivos precisa de um canal de coordenação, e um canal de coordenação é um lugar onde metadados se acumulam. Nós limitamos isso com expiração imposta pelo banco de dados e projetamos os clientes para desconfiar do servidor — mas a versão honesta é que o relay vê coisas reais, brevemente, e nenhuma arquitetura cuidadosa faz esse número ser zero.


