Todos os posts

10 min de leitura

Onde a CardanoWall guarda suas chaves no navegador

No navegador, a CardanoWall mantém as chaves desbloqueadas na memória de sessão e grava apenas o texto cifrado do cofre no IndexedDB — nunca Identity Seeds em texto claro nem chaves privadas.

Quando você desbloqueia a CardanoWall no navegador, a semente desbloqueada e as chaves privadas derivadas dela vivem na memória de sessão — memória comum da aplicação, que desaparece quando você bloqueia, sai ou fecha a aba. O armazenamento persistente do navegador (IndexedDB, sessionStorage) guarda apenas o texto cifrado do cofre e metadados não secretos. Identity Seeds em texto claro e chaves privadas derivadas nunca são gravados ali.

Essa distinção é o ponto central. O navegador precisa manter material de chave para assinar e decifrar localmente — é assim que a criptografia funciona, afinal. A pergunta de segurança nunca é "o navegador pode tocar nas chaves?" — ele tem de tocar. A pergunta é onde essas chaves vivem e o que é gravado em disco. O modelo web da CardanoWall foi construído para que o que sobrevive a um recarregamento seja texto cifrado, não segredos.

O que o navegador precisa enquanto uma identidade está desbloqueada?

Ele precisa do material de chave privada para o trabalho que você está de fato fazendo — e de nada mais duradouro do que a própria sessão.

Depois que você desbloqueia uma identidade, a aplicação pode precisar de:

  • assinar um registro Label 309;
  • decifrar um registro selado endereçado a você;
  • tentar decifrar registros selados que chegam, para encontrar os destinados à sua caixa de entrada;
  • recifrar o cofre depois que você adiciona ou remove uma passkey;
  • revelar sua semente quando você pede explicitamente para vê-la;
  • reconstruir caches locais cifrados.

Nada disso é possível só com chaves públicas. Cada operação precisa de material privado derivado do seu Identity Seed. O design mantém esse material na memória de sessão e o limpa ao bloquear ou sair — da melhor forma possível, pelos motivos que veremos abaixo.

O que é memória de sessão aqui?

Memória de sessão é a memória temporária da aplicação, dentro do próprio processo, que a aplicação descarta quando a sessão de desbloqueio termina.

No app de navegador da CardanoWall, a semente viva e as chaves derivadas dela ficam fora do estado comum da interface, em mapas de memória internos. O estado reativo da interface guarda apenas fatos não secretos: qual identidade está desbloqueada, quando foi desbloqueada, quais metadados de cadastro de passkey estão na tela durante a configuração. Os bytes secretos nunca entram nesse estado reativo.

Essa separação importa porque o estado comum da interface é a parte de um app com mais chance de ser inspecionada, serializada, persistida ou passada acidentalmente para um componente que a registra em log. Material secreto merece uma superfície menor e deliberadamente enumerada. Todo lugar do app que pode entregar bytes secretos — o closure de assinatura, as chaves de decifração, a saída de emergência para revelar a semente, o caminho de reconstrução do cofre — está listado em um único arquivo, e cada um retorna uma cópia defensiva em vez do buffer vivo.

O navegador ainda mantém os segredos enquanto você está desbloqueado. Eles simplesmente não são tratados como dados comuns do app.

O que é gravado no IndexedDB?

O texto cifrado do cofre — os mesmos bytes que o servidor armazena, não as sementes dentro deles.

O IndexedDB é usado como cache local do seu cofre de identidade cifrado: uma linha por conta, contendo exatamente o texto cifrado com age que o servidor mantém. Guardar isso em cache permite que o app se reidrate depois de um recarregamento a partir de um único toque na passkey, sem nova ida ao servidor para buscar o cofre de novo.

Um atacante que apenas leia esse banco de dados local vê os bytes cifrados do cofre endereçados às suas passkeys — não sementes em texto claro. O cache continua sendo dado sensível do serviço, e o app o apaga ao sair, ao excluir a conta e ao alterar passkeys. Mas ele não é a identidade em si; é uma caixa trancada cujas únicas chaves vivem dentro dos seus autenticadores. (Para saber como essa caixa é selada, veja como a CardanoWall armazena sua identidade e como as passkeys protegem seu cofre de identidade.)

Essas gravações são totalmente suprimidas no modo de computador público e quando você opta por não lembrar o dispositivo.

O que vai para o sessionStorage?

Apenas metadados de cadastro não secretos — nunca material de chave.

Durante a criação da identidade, o app espelha os metadados de cadastro da passkey para o sessionStorage, para que um recarregamento acidental no meio da configuração não apague o estado visível. Esses metadados são não secretos por construção: IDs de credencial, chaves públicas, transportes, flags de tipo de dispositivo e de backup, e fatos semelhantes com os quais um atacante não ganha nada.

O que é explicitamente mantido fora do sessionStorage:

  • Identity Seeds;
  • chaves privadas derivadas;
  • saídas da WebAuthn PRF (função pseudoaleatória) — os segredos que uma passkey devolve para desbloquear o cofre;
  • texto claro do cofre;
  • conteúdo selado já decifrado.

A linha é simples. A continuidade da interface pode persistir através de um recarregamento; os segredos da identidade não devem.

O que nunca pertence ao armazenamento do navegador, de forma alguma?

Material de identidade em texto claro — em qualquer armazenamento.

Estes ficam fora do localStorage, do sessionStorage, do IndexedDB, dos cookies, dos logs e do estado comum do app:

  • o Identity Seed;
  • chaves privadas de assinatura Ed25519;
  • chaves privadas de recebimento X25519;
  • segredos de recebimento híbridos pós-quânticos (a semente por trás do endereço opcional age1pqc...);
  • saídas da WebAuthn PRF;
  • texto claro do cofre;
  • conteúdo selado já decifrado, a menos que você explicitamente o salve em um cache local cifrado, com controle claro sobre ele.

O raciocínio é o mesmo que percorre todo o design: quanto mais lugares um segredo é gravado, mais difícil fica raciocinar sobre como apagá-lo e maior é a superfície que um comprometimento pode ler.

O que é o modo de computador público?

É o modo explícito de dispositivo compartilhado: enquanto ele está ativo, nada relacionado à identidade é gravado no armazenamento do navegador.

Ative-o e o app pula todo caminho de persistência relacionado à identidade — sem cofre de PIN, sem cache do cofre no IndexedDB, sem fixação de versão, sem espelho de cadastro no sessionStorage. As chaves desbloqueadas vivem apenas na memória de sessão, sobrevivendo à navegação dentro do app naquela aba, mas morrendo ao fechar a aba ou recarregar. O próprio botão de alternância é apenas em memória, de propósito: persistir "estou em um computador público" seria por si só uma gravação no armazenamento do navegador, e uma máquina compartilhada deve sempre reabrir no padrão seguro de perguntar de novo. Use-o em um computador de biblioteca, um laptop emprestado, uma máquina de conferência, um quiosque de redação — qualquer coisa que você não controle.

O que ele não faz é tornar seguro um dispositivo não confiável. Se a máquina já estiver comprometida enquanto você digita uma semente ou desbloqueia uma identidade, ela ainda pode observar os segredos na memória. O modo reduz o que fica para trás depois que você sai; ele não derrota malware local ativo. O modo de computador público cobre o fluxo completo.

O que significa zeroização em JavaScript?

Significa sobrescrever os arrays de bytes secretos — preenchê-los com zeros — assim que o app termina de usá-los.

A CardanoWall zeroiza seus buffers de chave Uint8Array quando uma identidade é bloqueada ou você sai, em vez de esperar e torcer para que o coletor de lixo os recupere. Isso é boa higiene e vale a pena fazer.

Mas o JavaScript não é um ambiente endurecido para o manuseio de segredos, e é honesto dizer isso. Strings são imutáveis, então um segredo que em algum momento virou string não pode ser apagado no lugar. O momento da coleta de lixo não está sob o controle do app. Engines podem copiar memória internamente. Ferramentas de desenvolvedor, extensões e uma origem comprometida mudam o modelo de risco por completo.

Então a zeroização aqui é uma medida de melhor esforço, não um apagamento garantido. Ela encolhe de forma significativa a janela em que uma cópia perdida permanece; não promete que os bytes sumiram de todos os lugares.

E se a página for comprometida enquanto está desbloqueada?

Então a identidade corre risco real — esta é a fronteira mais difícil de qualquer criptografia baseada em navegador.

Uma extensão de navegador maliciosa com acesso ao conteúdo da página, um dispositivo comprometido ou uma falha grave de cross-site scripting (XSS) rodando durante uma sessão desbloqueada pode conseguir ler segredos da memória, ou fazer o app assinar ou decifrar coisas que você não pretendia. Nenhum app web consegue eliminar isso por completo: um código que chega pela rede e em seguida manipula chaves fica exposto a qualquer outra coisa rodando naquela mesma origem.

A CardanoWall se apoia em defesa em profundidade para encolher a janela: uma Content Security Policy estrita que confina os scripts à própria origem do app — sem scripts inline, sem eval e sem nenhum script de terceiros carregado — somada a cabeçalhos de segurança aplicados a cada resposta na borda, a uma superfície de segredos deliberadamente pequena, à ausência de persistência em texto claro e a desbloqueio e decifração apenas por ação explícita do usuário — nunca automaticamente ao focar a aba. Essas medidas reduzem as chances e o raio de impacto. Elas não tornam inofensivo um script malicioso dentro de uma origem desbloqueada; isso continua sendo a ameaça de maior impacto que o modelo de navegador aceita.

Para suas identidades mais sensíveis, a resposta certa é tirar o material de chave da superfície web compartilhada. Mantenha-as em um dispositivo dedicado e confiável, e prefira um fluxo em que o segredo nunca toque um navegador — a CLI em automação, ou a CardanoWall Desktop, que mantém suas chaves em um núcleo Rust local em vez de uma origem web. (Para o princípio mais amplo, veja por que as chaves nunca saem do dispositivo.)

O que você deve realmente fazer?

Use o modelo de navegador de forma deliberada e ajuste as precauções à sensibilidade do trabalho.

Para o uso do dia a dia:

  • salve seu Identity Seed em um lugar seguro — ele é o backup de verdade;
  • adicione uma passkey para o desbloqueio diário;
  • bloqueie ou saia quando terminar;
  • use "lembrar este dispositivo" apenas em máquinas em que você confia;
  • mantenha seu navegador e seu sistema operacional atualizados;
  • evite extensões de navegador de alto risco;
  • ative o modo de computador público em qualquer dispositivo compartilhado.

Para o trabalho sensível, acrescente:

  • um perfil de navegador dedicado ou, melhor ainda, um dispositivo dedicado;
  • nenhum desbloqueio em máquinas emprestadas;
  • uma chave de segurança de hardware como fator de desbloqueio;
  • separação entre identidades de alto risco e identidades comuns;
  • cuidado com registros selados — um destinatário que consegue decifrar também pode vazar o texto claro depois.

A versão curta

O app de navegador da CardanoWall precisa de chaves privadas enquanto uma identidade está desbloqueada, então as mantém na memória de sessão em vez de no armazenamento persistente. O IndexedDB guarda em cache apenas o texto cifrado do cofre; o sessionStorage guarda apenas metadados de configuração não secretos. O Identity Seed e as chaves privadas nunca são gravados como dados comuns de navegador.

O modelo de cofre hospedado e o modelo de armazenamento no navegador reforçam um ao outro: o servidor guarda texto cifrado que não consegue decifrar, e o navegador se esforça para não deixar a semente para trás. Nenhuma das duas afirmações é uma garantia contra um dispositivo que já está comprometido — e ser claro sobre esse limite faz parte de levá-lo a sério. Para o quadro completo do que o serviço pode e não pode observar, veja o que a CardanoWall pode ver.

securitybrowser-securityidentity