AlterAntiX
Voltar ao blog
Técnico11 min de leitura

Canvas e WebGL Fingerprint: Como Funciona e Por Que Ruído Aleatório Entrega

Ruído aleatório no canvas parece esconder, mas sem seed consistente ele vira uma assinatura própria — mais identificável que não mascarar nada. Este artigo explica como canvas e WebGL fingerprint funcionam de verdade e por que coerência importa mais que aleatoriedade.

Ruído no canvas é a configuração mais recomendada do nicho e uma das mais mal entendidas. Ligado sem seed estável, ele não esconde um dispositivo — publica um novo a cada carregamento de página, coisa que computador nenhum faz. Aqui está como canvas e WebGL fingerprint funcionam de verdade, e por que coerência vale mais que aleatoriedade numa conta de trabalho.

O que canvas e WebGL fingerprint realmente medem

Nenhuma das duas técnicas lê algo sobre você. As duas pedem ao navegador que desenhe uma coisa e depois olham exatamente como aquilo saiu. A premissa é que instruções idênticas de desenho produzem pixels sutilmente diferentes em máquinas diferentes, porque o resultado passa por uma GPU específica, uma versão de driver específica, um rasterizador de fonte específico e um caminho de composição específico do sistema operacional. Mesmas instruções, hardware diferente, pixels diferentes.

O que torna isso valioso para quem rastreia não é a unicidade sozinha — é a estabilidade. Cookie se apaga; hash de canvas não, porque ele não está guardado em lugar nenhum. Ele é recalculado a partir da sua máquina toda vez que alguém pede, e num computador que não mudou volta idêntico por anos. Essa combinação, razoavelmente único e extremamente estável, é o motivo de o canvas ter sobrevivido a todas as ondas de restrição a cookie desde que foi documentado.

Os dois sinais moram na camada de navegador da pilha de identificação — a parte que o JavaScript consegue ler e, por consequência, a parte que o JavaScript também consegue reescrever. Isso importa para o resto do artigo, e é por isso que a camada de rede citada no fim se comporta de um jeito tão diferente. Nosso guia de fingerprint percorre camada por camada se você quiser o mapa inteiro antes.

Como o navegador transforma um desenho em identificador

O mecanismo é curto o suficiente para descrever inteiro. Um script cria um elemento de canvas que nunca aparece na tela, desenha nele um conteúdo fixo — em geral uma linha de texto numa fonte nomeada, às vezes com gradiente, emoji ou curva, porque isso exercita mais caminhos de renderização — e depois chama um método de leitura: toDataURL, toBlob ou getImageData. Esses métodos devolvem os pixels crus. O script gera um hash deles e guarda o hash.

Nada disso é exótico, e é justamente esse o problema de quem tenta se defender. Não há pedido de permissão, não há artefato visível e não há atraso perceptível. Também não dá para simplesmente bloquear: esses mesmos três métodos são o que aplicação legítima usa para exportar um gráfico, recortar um avatar ou gerar uma miniatura. Um navegador que os recusasse quebraria boa parte da web moderna.

A variação capturada é real e vem principalmente de três lugares: como o rasterizador de fonte desenha borda de glifo e suavização, como a GPU trata gradiente e alisamento de curva, e quais fontes existem no sistema. Dois computadores com a mesma versão de sistema, a mesma versão de navegador e o mesmo modelo de GPU tendem a concordar. Troque o driver, instale um pacote de fontes ou saia de uma GPU integrada para uma dedicada, e o hash muda.

O que o WebGL acrescenta por cima

O WebGL contribui com duas coisas muito diferentes, e tratar as duas como uma só é a origem da maior parte da confusão desse nicho.

A primeira é a imagem: uma cena 3D renderizada e lida de volta, com hash calculado igualzinho ao do canvas. É um sinal mais forte que o canvas 2D porque uma parcela maior do pipeline gráfico participa do resultado.

A segunda são os metadados: strings descritivas que a API entrega de graça. As duas que importam são o vendor e o renderer não mascarados, e o renderer em especial é notavelmente falante. Uma máquina Windows real devolve algo como uma string ANGLE nomeando o modelo da GPU e o backend Direct3D. Uma máquina Linux devolve uma string OpenGL. Um Mac devolve uma string da Apple citando Metal. O renderer não descreve apenas uma placa de vídeo — descreve a pilha gráfica, e a pilha gráfica descreve o sistema operacional.

Por que a string do renderer é um cruzamento, não só um valor
Um perfil cujo user agent diz Windows enquanto o renderer de WebGL descreve uma pilha OpenGL respondeu a mesma pergunta duas vezes com respostas diferentes. Máquina real nenhuma faz isso. É essa a checagem que pega a maior parte do spoofing entre sistemas operacionais, e ela custa ao detector uma comparação de string.

Ruído aleatório no canvas protege ou expõe?

Expõe, do jeito que costuma ser feito. Vale acompanhar o raciocínio devagar, porque a intuição aponta para o lado errado.

Um usuário real tem um hash de canvas. É o mesmo na segunda-feira e o mesmo em março. Ele sobrevive a atualização de navegador e só muda quando algo material muda na máquina — atualização de driver, monitor novo, instalação de fonte. Uma plataforma que já viu a sua conta cinquenta vezes viu esse mesmo hash cinquenta vezes, e essa constância é uma das razões pelas quais ela confia na sessão.

Agora acrescente ruído aleatório por chamada. O hash fica diferente a cada carregamento. Não diferente de um jeito que esconde o dispositivo — diferente de um jeito que diz que o dispositivo é impossível. A plataforma não está procurando um hash específico, está olhando o histórico de hashes daquela conta, e uma conta cujo dispositivo mudou de identidade quarenta vezes na semana é mais interessante que uma que ela nunca conseguiu identificar. A aleatoriedade não removeu o sinal; trocou um sinal chato por um sinal alarmante.

Existe um segundo modo de falha, mais técnico e mais fácil de provar. Implementação de ruído precisa modificar pixel, e modificar pixel no lugar errado deixa evidência. O caso clássico é o pixel transparente: um teste cria um canvas de um por um com alfa zero e lê de volta os quatro canais. Navegador real devolve zero, zero, zero, zero. Uma rotina de ruído ingênua, que varre o buffer e mexe no canal vermelho, devolve um no vermelho de um pixel totalmente transparente — valor que não ocorre naturalmente. A gente conhece bem essa falha porque a nossa própria implementação de ruído a tinha, e foi exatamente esse teste que pegou antes de ir para produção. A lição não é que o nosso código era ruim; é que a superfície para esse erro é grande, e toda ferramenta que injeta ruído está exposta a ele.

O ponto contra o consenso, dito sem rodeio
Diante de uma plataforma que guarda o histórico da sua conta, hash de canvas instável é um sinal pior do que um hash estável que identifica a sua máquina. Instabilidade não é anonimato. É anomalia, e anomalia é justamente o que sistema de risco existe para achar.

Por que ruído sem seed consistente vira uma assinatura própria

Pense no que a plataforma consegue montar com três visitas. Com hash estável, ela registra um valor e segue a vida. Com ruído aleatório, registra três valores diferentes vindos da mesma conta logada, na mesma conexão, com minutos de diferença. Esse padrão não é só suspeito; é mensurável. Distribuição de mudança ao longo do tempo é um atributo como qualquer outro, e um dispositivo cuja identidade de renderização tem variância que hardware físico nenhum produziria se destaca exatamente na população em que você queria se misturar.

A correção não é abandonar o ruído, é torná-lo determinístico. Se o ruído sai de uma seed fixa por perfil, o hash fica diferente dos outros perfis e idêntico a si mesmo entre sessões — um dispositivo distinto, estável e crível. É a diferença entre um disfarce e um holofote piscando. Na nossa implementação a seed é um valor hexadecimal de trinta e dois caracteres, gerado uma vez na criação do perfil e guardado com ele, de modo que um perfil com ruído ligado produz o mesmo hash modificado a cada abertura.

A diferença entre mascarar e ser coerente

Mascarar pergunta: o site consegue ler o valor real? Coerência pergunta: tudo o que o site lê descreve a mesma máquina plausível? São objetivos diferentes, e só um deles sobrevive ao contato com um sistema de risco moderno.

AbordagemO que ela otimizaComo ela falha
Mascaramento agressivoEsconder o valor real a qualquer custoProduz valores impossíveis ou instáveis que dispositivo real nenhum reporta
Nenhuma proteçãoSer perfeitamente consistenteTodo perfil da mesma máquina devolve o mesmo hash, então todos são o mesmo dispositivo
CoerênciaUma máquina plausível diferente por perfil, estável no tempoExige que o perfil inteiro concorde — user agent, WebGL, fontes, tela, fuso, TLS

Coerência é mais exigente porque restringe todos os valores ao mesmo tempo. Resolução de tela tem que ser uma que monitor real reporta. Lista de fontes tem que combinar com o sistema que o perfil diz usar. Vendor e renderer de GPU precisam ser da mesma família — máquina nenhuma jamais reportou vendor Intel com renderer NVIDIA, e qualquer validador confere isso em uma linha. Memória de dispositivo tem que ser um dos valores que a API pode expor. Dá mais trabalho do que apertar um botão de mascarar, e é a única abordagem que fica mais convincente conforme o detector melhora.

O que o Brave faz, e por que não é o seu objetivo

Uma objeção justa: o Brave aleatoriza o canvas de propósito, e o Brave não é ingênuo. Verdade — e os detalhes é que sustentam o argumento. Eles chamam a técnica de farbling, e os valores aleatorizados saem de uma seed que é por sessão, por site e por área de armazenamento, então um mesmo site vê um valor consistente dentro da sessão enquanto dois sites diferentes veem valores diferentes.

O alvo daquele desenho é impedir que sites diferentes liguem um visitante anônimo. Para isso funciona. Só que ele torna o navegador visível como Brave e, de propósito, entrega a um mesmo site uma identidade nova na sessão seguinte — exatamente o comportamento que você não quer numa conta que uma única plataforma conhece há oito meses. Mesma técnica, objetivo oposto. Copiar a técnica sem o objetivo é como se acaba com uma configuração certa para navegador de privacidade e errada para perfil de trabalho.

Como o AlterAntiX trata canvas e WebGL

Nossos padrões seguem o argumento acima, e são incomuns o bastante nesse mercado para valer dizer com todas as letras.

  • Ruído de imagem em canvas e WebGL vem desligado. Perfil novo não encosta nos pixels desenhados. A seed é gerada e guardada para a opção existir, mas o perfil só ganha hash modificado quando alguém liga isso de propósito.
  • O modo de metadados de WebGL vem em "real". O vendor e o renderer que saem são os que a GPU de verdade reporta. Spoofing entre sistemas operacionais em perfil de desktop é o alarme mais alto que existe, então o padrão seguro é não falsificar.
  • Perfis móveis são a exceção deliberada. Um perfil de iPhone ou Android precisa sobrescrever as strings de GPU mesmo no modo real, porque a resposta honesta num host de desktop seria uma GPU de desktop sob um user agent de celular — uma contradição pior que o spoof.
  • Quando uma GPU é gerada, vendor e renderer vêm da mesma família. O gerador escolhe o renderer dentro da lista que casa com o vendor já sorteado, então vendor Intel nunca sai acompanhado de renderer NVIDIA.
  • Ruído, quando ligado, é semeado por perfil e estável. Mesmo perfil, mesmo hash modificado, abertura após abertura — e pixels transparentes são pulados, então o teste do pixel transparente continua devolvendo o que um navegador real devolve.

Nada disso torna um perfil invisível, e não é essa a intenção. Isso torna cada perfil uma máquina diferente, estável e plausível, que é a propriedade que de fato se sustenta ao longo de meses de uso.

Rode o teste em você mesmo

Não acredite em nada disso na palavra de ninguém, inclusive na nossa. Abra o verificador de fingerprint no navegador ou perfil que você usa para trabalhar e leia três coisas.

  • O hash de canvas, duas vezes. Carregue a página, anote o valor, feche o perfil, abra de novo e carregue outra vez. Valor igual significa dispositivo estável. Valor novo toda vez significa que a ferramenta que você usa está aleatorizando por chamada.
  • O vendor e o renderer de WebGL contra a plataforma declarada. User agent de Windows tem que vir com pilha gráfica de Windows. Se o renderer cita a pilha de outro sistema, você tem uma contradição para resolver antes de qualquer outra coisa.
  • Esses mesmos dois valores em dois perfis seus. Se dois perfis da mesma máquina devolvem hashes de canvas idênticos e strings de renderer idênticas, eles são um dispositivo com dois nomes, e separação de proxy nenhuma muda isso.

A camada do navegador é só metade do quadro. Um perfil pode passar em toda checagem de canvas e WebGL e ainda se contradizer uma camada abaixo, no handshake TLS que sai antes de qualquer JavaScript rodar — esse é o problema do JA3 e JA4, e é a razão de a gente tratar as duas camadas como um trabalho só. O AlterAntiX é download gratuito para desktop se você quiser comparar um perfil montado assim com o que você roda hoje.

Leve isto daqui
  • Canvas e WebGL identificam pelo jeito como a sua máquina desenha, não por algo guardado — apagar cookie não afeta nenhum dos dois.
  • A string do renderer de WebGL descreve a pilha gráfica, que descreve o sistema operacional. É cruzamento, não só valor.
  • Ruído aleatório por chamada cria uma instabilidade que dispositivo real não tem. Em conta de trabalho isso é sinal pior que o hash escondido.
  • Ruído determinístico com seed por perfil é aceitável. O problema é aleatoriedade sem seed.
  • O Brave aleatoriza de propósito com outro objetivo: desligar sites entre si, não manter identidade estável de trabalho.
  • Verifique com duas cargas num perfil e uma carga em dois perfis. Estável dentro do perfil, diferente entre perfis.

Perguntas frequentes

Ligar o ruído de canvas é sempre errado?

Não é sempre errado, é errado por padrão. Ruído protege contra correlação entre sites que nunca se falam, e é por isso que navegadores de privacidade usam. Mas em conta de trabalho o objetivo é o oposto: você quer que a mesma plataforma reconheça o mesmo dispositivo estável em todo acesso. Nesse cenário, hash que muda é sinal, não proteção.

Por que dois perfis com o mesmo hardware devolvem o mesmo hash de canvas?

Porque o hash sai do desenho renderizado, e o desenho depende de GPU, driver, sistema operacional e da pilha de fontes — não do perfil. Se você quer hashes diferentes por perfil sem ligar ruído, o caminho é variar o que de fato muda o render: a fonte instalada declarada, a resolução, o pixel ratio e o par vendor/renderer, sempre dentro de combinações que existem em hardware real.

O que é pior: ruído ligado ou nenhuma proteção?

Depende de para quem você está olhando. Contra rede de publicidade que correlaciona milhares de sites, ruído ajuda. Contra uma única plataforma que guarda o histórico da sua conta, ruído mal feito é pior que nada, porque cria instabilidade que usuário real nunca tem e ainda pode deixar rastro detectável no próprio desenho.

Falsificar vendor e renderer do WebGL é seguro?

Só quando a string escolhida é compatível com o resto do perfil. Dizer que a GPU é Apple num perfil Windows, ou anunciar vendor Intel com renderer NVIDIA, é uma combinação que nunca existiu em máquina real — o cruzamento é trivial e o custo é alto. Por isso, em perfil de desktop, passar a GPU real é normalmente a escolha mais segura.

Como sei se o meu perfil está estável?

Abra o verificador de fingerprint duas vezes no mesmo perfil, com um reinício entre elas, e compare o hash de canvas e o par vendor/renderer. Se mudaram sem você ter mudado nada, o perfil está instável. Se ficaram iguais e são coerentes com o sistema declarado, está do jeito que precisa estar.

O AlterAntiX liga ruído de canvas por padrão?

Não. Perfis novos são criados com o ruído de imagem de canvas e WebGL desligado, e com o modo de WebGL em "real", passando a GPU verdadeira. O ruído continua disponível para quem quiser ligar, com seed fixa por perfil, mas não é o padrão — e a razão está explicada no artigo.

Fingerprint e TLS alinhados, de verdade

O AlterAntiX casa o fingerprint do navegador com o TLS na mesma versão de Chrome. Baixe e teste você mesmo.

Baixar o AlterAntiX