Segurança · Em detalhe

O ciclo de vida criptográfico completo

Um passo a passo preciso do que acontece com os seus dados em cada etapa — com as primitivas, os parâmetros e as fronteiras de confiança explicados. Cada etapa começa com um resumo em linguagem simples, para que você leia no nível de detalhe que preferir.

Etapa 01 · Criptografia

O seu segredo é selado no seu dispositivo

Em termos simples: o embaralhamento acontece no seu navegador, antes de qualquer envio. O que recebemos já é ilegível.

Quando você aperta Criptografar, o navegador obtém uma nova chave de conteúdo de 256 bits do WebCrypto CSPRNG e criptografa os seus dados com AES-256-GCM. O GCM é autenticado: cada bloco leva uma etiqueta de 128 bits, então qualquer adulteração posterior é detectada em vez de ser descriptografada silenciosamente.

Textos e arquivos são tratados da mesma forma — ambos viram um único bloco binário opaco, preenchido até um tamanho padrão para que uma senha curta e um arquivo pequeno pareçam iguais. O texto legível nunca passa pela rede e nunca sai da memória da aba.

CifraAES-256-GCM, blocos de 64 KiB
Chave de conteúdo256 bits, nova a cada segredo
Nonceprefixo aleatório de 7 bytes + contador
Etiqueta de autenticação128 bits por bloco
PreenchimentoPadmé, mínimo de 64 KiB

Etapa 02 · Guarda da chave

A chave fica escondida no link, não nos nossos servidores

Em termos simples: a parte do link depois do # contém a chave — e os navegadores nunca enviam essa parte a nenhum servidor.

O seu link carrega uma semente aleatória de 256 bits no fragmento da URL — tudo o que vem depois do #. Pela especificação de URL, o navegador remove o fragmento e nunca o inclui na requisição enviada aos nossos servidores. A partir dessa semente, o navegador deriva, com HKDF, um valor de busca para encontrar o segredo e a chave que desembrulha a chave de conteúdo. O servidor só vê um hash do valor de busca.

O navegador do destinatário lê a semente do fragmento e faz a mesma derivação localmente. É isso que “conhecimento zero” significa aqui: ter o texto cifrado, por si só, não serve para nada sem o link.

Local da chaveFragmento da URL #
Enviada ao servidor?nunca
Semente32 bytes aleatórios, base64url
DerivaçãoHKDF-SHA-256
O servidor guardaapenas SHA-256(busca)

Etapa 03 · Senha opcional

Uma segunda trava que só pessoas têm

Em termos simples: adicione uma senha e nem quem tem o link completo consegue abrir o segredo sem ela.

Se você define uma senha, ela é reforçada com o Argon2id — uma função de derivação de chave que exige muita memória — e combinada com a semente para formar a chave que embrulha a chave de conteúdo. A senha em si nunca é transmitida nem armazenada; só você e o destinatário a conhecem. As tentativas erradas são repetidas no navegador do destinatário, com dados que ele já tem, então o servidor não consegue contá-las.

A exigência de memória torna caros os ataques de adivinhação offline em grande escala, mesmo com GPUs e ASICs. Envie a senha por um canal diferente do link, e os dois fatores nunca se encontram num mesmo lugar. O módulo Argon2 é baixado em toda criação e revelação, então a rede não consegue saber quais segredos usam senha.

KDFArgon2id
Salt128 bits aleatórios
EmbrulhoAES-256-GCM, IV de 96 bits

Etapa 04 · Trânsito & armazenamento

Só texto cifrado sai do seu dispositivo

Em termos simples: guardamos uma caixa trancada e um horário de expiração. Nada mais — nenhum texto legível, nenhuma chave, nenhum registro sobre você.

O bloco é enviado por TLS e armazenado em repouso como texto cifrado, junto com credenciais em hash, o seu tempo de vida e um horário de expiração arredondado. De propósito, não guardamos identidade do remetente, destinatário, log de IPs, horário de criação nem histórico de acessos. Não existe sistema de contas para ligar um segredo a uma pessoa. O limite de requisições funciona sobre um HMAC do endereço, com um salt que é trocado periodicamente, então nada de antes de uma troca pode ser ligado a nada de depois.

Como o objeto armazenado não tem sentido sem a semente no fragmento, uma invasão do servidor ou uma ordem judicial só rende bytes opacos e hashes que não podem ser revertidos em nada.

Em trânsitoTLS
Em repousotexto cifrado + chaves em hash + expiração
Logsnenhum por segredo

Etapa 05 · Recuperação & destruição

A primeira leitura vence — depois tudo é apagado

Em termos simples: abrir um link de uso único entrega a caixa uma vez e apaga a cópia do servidor. Ou destrua você mesmo, quando quiser.

Nada é buscado quando a página de revelação carrega: a requisição só sai com um clique ou tecla de verdade, então verificadores de links e pré-visualizações de chat não conseguem consumir um segredo. Num segredo de uso único, o servidor reivindica a linha numa única atualização condicional — exatamente uma requisição vence — e o segredo conta como consumido a partir desse momento. O mesmo navegador pode baixar de novo durante 15 minutos se a conexão cair; ninguém mais pode, e uma reivindicação não confirmada é destruída, nunca desfeita. Segredos com prazo são uma leitura simples até expirarem.

Todo segredo tem também um link de destruição privado. Abri-lo não destrói nada por si só; confirmar apaga o texto cifrado imediatamente — antes que qualquer destinatário possa lê-lo.

Uso únicoreivindicação atômica, depois destruído
Janela para baixar de novo15 min, só o mesmo cliente
Expiração15 min – 14 dias
Controle do criadorlink de destruição

Modelo de ameaças

O que o shhnote vê e o que não vê

A versão honesta. Veja exatamente onde fica a fronteira de confiança.

Nunca sai do seu dispositivo

O que não conseguimos ver

O seu texto legível · a chave de conteúdo e a semente · a sua senha · se uma senha foi definida · quem criou ou abriu um segredo · quando ele foi criado · logs de acesso por IP. Nada disso é transmitido ou guardado.

Armazenado nos nossos servidores

O que de fato guardamos

Um bloco criptografado que não conseguimos abrir · a sua faixa de tamanho após o preenchimento · hashes de sentido único dos valores que o seu navegador usa para encontrá-lo ou destruí-lo · se é de uso único ou com prazo · um horário de expiração arredondado. Tudo isso é inútil sem a semente no seu link.

Bom saber

As ressalvas honestas

Qualquer pessoa com o link completo (e a senha, se houver) pode ler um segredo de uso único — trate o link como o próprio segredo. Depois que um segredo é exibido, a página sobrescreve o que puder quando você sai, mas o JavaScript não consegue garantir isso; feche a aba quando terminar. Um navegador controlado por automação que injeta interações reais pode abrir um segredo de uso único como uma pessoa faria — o destinatário então não encontra nada, que é o resultado honesto. Apagar um segredo remove o registro; restos criptografados podem permanecer em journals, no espaço livre do disco ou em backups até serem sobrescritos, como texto cifrado sem chave. Segredos grandes guardados fora do banco de dados carregam o horário em que o arquivo foi gravado. E, como em qualquer aplicativo web, você confia no código entregue ao seu navegador — é por isso que o shhnote é de código aberto e pode ser hospedado por conta própria.

Especificação criptográfica

Todas as primitivas, num só lugar

Criptografia

AES-256-GCM

Criptografia simétrica autenticada em blocos de 64 KiB. Uma chave de 256 bits mais uma etiqueta de integridade por bloco, de modo que qualquer adulteração ou truncamento é detectado — e não apenas fica ilegível.

Derivação de chave

HKDF · Argon2id

Chaves e identificadores vêm da semente por meio de HKDF-SHA-256. As senhas opcionais são reforçadas com uma KDF que exige muita memória, o que torna a força bruta offline lenta e cara, mesmo com hardware dedicado.

Aleatoriedade

WebCrypto CSPRNG

Sementes, chaves, salts e nonces vêm do gerador criptograficamente seguro do navegador. Nunca Math.random(), nunca previsíveis.

Guarda da chave

Fragmento da URL #

A semente vai depois do # no seu link. Os navegadores nunca transmitem o fragmento, então ela nunca chega aos nossos servidores.

Em trânsito

TLS

Só texto cifrado sai do seu dispositivo, transportado por TLS moderno. O que recebemos é um bloco opaco que não conseguimos abrir.

Em repouso

Texto cifrado + hashes

Guardamos um bloco criptografado, hashes de sentido único das suas credenciais e uma expiração arredondada — nenhum texto legível, nenhuma chave, nenhum metadado de remetente ou destinatário.

Perguntas técnicas

Para quem se preocupa com segurança

Como a garantia de uso único é mantida contra condições de corrida?

A revelação executa uma única atualização condicional que muda a linha de “ativa” para “reivindicada”. Duas requisições simultâneas não podem ter sucesso ao mesmo tempo; a segunda encontra um registro já reivindicado e recebe a mesma resposta “nenhum segredo encontrado” que qualquer outra pessoa. A reivindicação nunca é desfeita: se o download se perder, quem tem o token da reivindicação baixa de novo dentro da janela; caso contrário, o segredo é destruído sem ser lido.

Por que o fragmento da URL e não um parâmetro de consulta?

Os parâmetros de consulta são enviados ao servidor e acabam em logs de acesso, proxies e ferramentas de análise. O fragmento (depois do #) é definido pela especificação de URL para ficar no lado do cliente — o navegador nunca o coloca na requisição HTTP. Essa propriedade é a base de todo o design de conhecimento zero. Depois de uma revelação, a página também remove o fragmento da barra de endereço e do histórico.

O que impede os verificadores de links de destruírem segredos de uso único antes da hora?

A página de visualização é o mesmo documento estático para todos os segredos e não busca nada ao carregar. A requisição só é enviada com um clique ou tecla confiável — um click() por script ou um envio de formulário não contam. Os verificadores automáticos (segurança de e-mail, pré-visualizações de chat, antivírus) só carregam essa estrutura estática.

Posso verificar ou hospedar isto eu mesmo?

Sim. Todo o código-fonte é público sob a licença AGPLv3, o protocolo está descrito numa especificação com vetores de conformidade que qualquer implementação pode usar para se testar, e há um guia de hospedagem própria. Você pode auditar a criptografia no lado do cliente e rodar a sua própria instância, para que a fronteira de confiança seja inteiramente sua.

Algo é registrado para prevenir abusos?

Não guardamos logs de acesso por segredo nem histórico de IPs. O limite de requisições usa um hash com chave do endereço, com um salt que é trocado periodicamente e, a cada troca, zera todos os contadores. As denúncias de abuso são contadas por dia; não há registro de qual segredo foi denunciado.

Dicas para compartilhar com segurança

  • Envie a senha por um meio diferente do link, por exemplo o link por e-mail e a senha por telefone.
  • Escolha a expiração mais curta que funcione para você.
  • Use um segredo de uso único para senhas e outras informações que devem ser lidas exatamente uma vez.

Relatar uma vulnerabilidade

Se você acha que encontrou um problema de segurança neste site, escreva para [email protected] e conte-nos de forma privada antes de contar a qualquer outra pessoa. Inclua o que você encontrou e como reproduzir.

Nós vamos:

  • responder em até 5 dias úteis;
  • manter você informado enquanto corrigimos;
  • dar o crédito a você quando publicarmos a correção, se quiser.

Durante os testes, não acesse dados de outras pessoas, não perturbe o serviço e não rode varreduras automatizadas que o sobrecarreguem.

Vulnerabilidades no próprio software shhnote: veja a política de segurança do projeto.

Criar um segredo Ver o código no GitHub

Experimente — leva dez segundos

Escreva algo secreto, receba o seu link de uso único e veja-o desaparecer.

Criar um segredo