Adicionar ao Chrome

Como funciona

Uma visão técnica para quem avalia segurança. Tudo aqui pode ser conferido no código-fonte — inclusive as partes menos favoráveis, que declaramos em vez de omitir.

Arquitetura

Não há backend. A extensão é uma extensão do Chrome em Manifest V3 que gera códigos TOTP/HOTP localmente com OTPAuth. Não operamos servidores, não mantemos contas e não existe canal pelo qual os dados do usuário possam chegar até nós.

Como não há servidor, também não há material de chave do lado do servidor, nem custódia de chaves, nem qualquer caminho de recuperação sob nosso controle. Se alguém esquece a senha e perde o código de recuperação, não temos como ajudar — é proposital.

Criptografia

A proteção por senha é opcional e vem desativada. Com ela ativada:

Cifra
AES-256-GCM, IV aleatório de 96 bits por registro e por reescrita
Derivação de chave
PBKDF2-HMAC-SHA256, 600.000 iterações, sal aleatório de 128 bits (orientação da OWASP)
Chave mestra
256 bits, de crypto.getRandomValues, gerada uma única vez; a senha apenas a encapsula
Impressões digitais
HMAC-SHA256 sob uma subchave derivada por HKDF, usada para mesclar registros entre dispositivos
Armazenamento da chave destravada
chrome.storage.session — só em memória, nunca gravada em disco, apagada ao fechar o navegador e inalcançável por content scripts
Bloqueio automático
A cada abertura / após 5, 15 ou 60 minutos de inatividade / até o navegador fechar
Implementação
Apenas WebCrypto. Nenhuma primitiva é feita à mão e nenhuma biblioteca de criptografia é embutida.

Por que dois níveis de chave

Os dados nunca são cifrados diretamente com uma chave derivada da senha. Uma chave mestra aleatória cifra os registros; a saída do PBKDF2 apenas encapsula essa chave mestra. Duas consequências decorrem daí, e as duas importam:

  • Trocar a senha reescreve 32 bytes em vez de recifrar cada registro, cada backup e cada exportação. É justamente nessa reescrita em massa que sistemas de armazenamento perdem dados.
  • Um código de recuperação de 160 bits pode encapsular a mesma chave mestra de forma independente, então uma senha esquecida tem conserto. O código é exibido uma vez, precisa ser digitado de volta para confirmação e é renovado a cada uso. Nada é gravado em disco até o usuário confirmá-lo.

O que é cifrado e o que não é

Com a proteção por senha ativada, todo o registro da conta é cifrado, exceto seu identificador e sua impressão digital — inclusive o nome do serviço, de modo que um perfil roubado não revela em quais serviços o usuário tem conta. Ao ativar, a extensão cifra os registros, verifica-os decifrando e comparando e só então remove todas as cópias em texto claro: armazenamento local do navegador, sincronização e os sete instantâneos rotativos de backup.

Dito sem rodeios, porque pesa na sua avaliação:

  • Com a proteção por senha desativada, as contas ficam armazenadas sem criptografia e, se o Chrome Sync estiver ligado, replicadas pela própria conta Google do usuário. Nunca chegam a nós, mas ficam com o Google. A sincronização pode ser desligada, o que também remove o que já estiver lá.
  • O histórico de uso por site — qual conta é usada em qual domínio — fica armazenado localmente e não é coberto pelo cofre enquanto está sendo coletado. Ativar a proteção por senha o apaga; ele também pode ser desligado separadamente.

Modelo de ameaças

Protege contra

  • Um diretório de perfil do navegador roubado ou copiado
  • Malware infostealer que exfiltra dados do navegador em massa
  • Acesso físico a uma máquina deixada sem supervisão
  • Registros de contas chegando ao Google via Chrome Sync
  • Um arquivo de backup perdido ou roubado (exportação protegida por senha)

Não protege contra

  • Malware rodando como o usuário enquanto o cofre está destravado
  • Um keylogger capturando a senha durante a digitação
  • Um navegador ou sistema operacional comprometido
  • O comprometimento dos serviços de terceiros a que os códigos pertencem

Em resumo: isto protege dados em repouso. Não defende, nem tem como defender, um dispositivo que já esteja sob controle de um atacante durante o uso.

Permissões

O manifesto declara exatamente duas permissões e nenhuma permissão de host:

storage
Contas e configurações no armazenamento local, a chave destravada no de sessão e a cópia opcional de sincronização
activeTab
Lê o nome de host da aba ativa para destacar a conta correspondente e captura a aba quando o usuário escaneia um QR code da tela

Não há content scripts, nenhuma permissão tabs, cookies ou webRequest e nenhum recurso acessível pela web. A extensão não consegue ler nem alterar o conteúdo de página alguma.

Câmera

A leitura de QR pela câmera roda em uma página da extensão aberta numa aba, não no popup — um popup é destruído ao perder o foco, que é exatamente o que um pedido de permissão faz. Para isso não é preciso nenhuma permissão no manifesto: usa-se o pedido de câmera padrão do navegador, concedido por origem da extensão e revogável nas configurações do site, e ele nunca aparece antes de o usuário abrir o leitor. O vídeo é decodificado localmente e nunca é transmitido nem armazenado.

Tráfego de rede de saída

Em uso normal a extensão não faz nenhuma requisição automática, e o Manifest V3 proíbe código remoto. Todas as conexões que ela pode fazer:

HostQuandoLeva dados do usuário?
worldtimeapi.org
timeapi.io
Verificação de desvio do relógio, em cache, falha silenciosamente. Com o relógio desajustado o TOTP quebra.Não
authenticator.shPágina de boas-vindas na instalação; página de feedback na desinstalação ou na avaliação.Não (logs comuns de servidor web)

Nenhuma fonte, script, folha de estilo ou imagem é carregada de hosts de terceiros. Tudo o que a interface precisa para ser renderizada vem dentro do pacote.

Como verificar o que publicamos

Nada do que está acima precisa ser aceito como fé. A extensão é de código aberto e cada versão é reproduzível:

  1. Baixe o .crx publicado na Chrome Web Store e descompacte-o
  2. Faça checkout da tag git correspondente
  3. Rode npm ci && npm run build no Node 20 LTS
  4. Compare o dist/ resultante com o pacote descompactado

A cada release no GitHub publicamos um SHA-256 de cada arquivo do dist/ produzido, como SHA256SUMS-v<version>.txt e no formato sha256sum, de modo que o passo 4 vira uma única execução de sha256sum -c. As diferenças devem se limitar à ordem dos arquivos dentro dos arquivos compactados e a espaços na saída minificada entre versões de patch do Node.

As dependências de execução são propositalmente poucas — OTPAuth, React, jsQR, Zustand, Framer Motion e Lucide — fixadas por um lockfile versionado. Um SBOM CycloneDX está disponível mediante solicitação.

Ver o código-fonte

O que não temos

Somos um fornecedor pequeno e independente. Se algum dos itens abaixo for requisito obrigatório no seu processo, é melhor saber agora do que três semanas depois de iniciada a avaliação:

  • Sem certificação SOC 2, ISO 27001 ou equivalente
  • Nenhum teste de intrusão externo contratado até hoje
  • Sem programa pago de bug bounty

O que oferecemos em troca é transparência total do código, uma build verificável, uma superfície mínima de permissões e nenhuma infraestrutura de servidor que pudesse guardar seus dados.

Como falar conosco

Relatos de vulnerabilidade e dúvidas de segurança: security@authenticator.sh. Nossa política de divulgação, escopo, prazos de resposta e termos de safe harbour estão na página de política de segurança; o que é armazenado e o que sai do dispositivo está descrito na política de privacidade.

Temos prazer em responder a um questionário escrito de avaliação de fornecedores ou percorrer o código junto com uma equipe de segurança.

Para qualquer assunto que não seja de segurança — instalação, recuperação de conta, dúvidas de cobrança em uma implantação — veja o suporte. Por favor, não envie relatos de vulnerabilidade para lá: aquela caixa não é tratada como confidencial.