Utilidades

QR Code por dentro: Reed–Solomon, Pix, vCard e Wi-Fi

Quase todo mundo pensa no QR Code como uma imagem mágica. Ele é, na verdade, duas coisas empilhadas. Embaixo está uma camada física: uma matriz de quadradinhos com correção de erro Reed–Solomon, a mesma matemática que faz um CD tocar com arranhões. Em cima está uma camada de texto: uma string comum que segue uma convenção, e é essa convenção, não o desenho, que decide se o código abre um site, conecta ao Wi-Fi ou inicia um pagamento Pix. Separar as duas camadas explica quase tudo o que parece misterioso: por que um QR com logotipo no meio ainda funciona, por que o Pix "copia e cola" é o mesmo dado do QR, e por que mudar um centavo do valor muda o código inteiro. Este guia abre as duas camadas com exemplos reais, monta um BR Code do Pix campo a campo, calcula o CRC-16 à mão e mostra onde mora o golpe do QR trocado. Gere qualquer um dos formatos no [gerador de QR Code](tool:qr-code) enquanto lê.

J-Kit16 min de leituraIntermediário
  • QR Code
  • Pix
  • vCard
  • Wi-Fi
  • CRC

Resumo rápido

  • Um QR Code tem duas camadas: a física (matriz com correção Reed–Solomon, versões 1–40, níveis L/M/Q/H) e a de payload (o texto e seu prefixo).
  • O logo no meio funciona porque o nível H recupera cerca de 30% dos dados; grande demais, ele estoura a margem e o código quebra.
  • O Pix "copia e cola" e o QR de pagamento são o mesmo BR Code EMV: campos TLV terminados por um CRC-16 no campo 63.
  • O CRC-16 do Pix usa o polinômio 0x1021 e valor inicial 0xFFFF (CRC-16/CCITT-FALSE), calculado sobre a string inteira incluindo "6304".

As duas camadas de um QR Code

Um QR Code (definido pela norma ISO/IEC 18004) é uma matriz de módulos claros e escuros. A norma padroniza a camada física: os padrões de posicionamento nos três cantos, os padrões de alinhamento e de tempo que sincronizam a leitura, a "zona de silêncio" branca ao redor, e, o mais importante, a correção de erro Reed–Solomon que permite ler o código mesmo danificado. Nada disso depende do que está escrito: a matriz é o envelope. Dentro do envelope vai a segunda camada, o payload, que é só uma string de texto. Do ponto de vista de quem usa, o QR é uma caixa de texto: você coloca uma string e o leitor a devolve intacta.

Não existe "QR de Wi-Fi" ou "QR de Pix" no nível do código, existe um texto que segue uma convenção, e o aplicativo do celular decide o que fazer ao reconhecer o prefixo. Se o texto começa com "https://", o navegador abre; se começa com "WIFI:", o sistema oferece conectar à rede; se é um bloco "BEGIN:VCARD", a agenda pergunta se você quer salvar o contato. Por isso o gerador de QR Code não tem mágica por trás de cada tipo: ele só monta a string certa e a embrulha na matriz. É essa densidade que separa o QR (bidimensional, centenas a milhares de caracteres) de um código de barras tradicional, que é unidimensional e guarda só um número curto.

Módulo
Cada quadradinho preto ou branco. É a menor unidade da matriz; a leitura converte módulos em bits.
Versão
O tamanho da matriz, de 1 (21×21 módulos) a 40 (177×177). Cada versão acima soma 4 módulos por lado.
Correção de erro (Reed–Solomon)
Módulos extras de redundância que reconstroem dados perdidos por sujeira, risco ou um logo por cima.
Máscara
Um dos 8 padrões aplicados sobre os dados para evitar manchas grandes que confundem o leitor.
Payload
A string codificada dentro do código, o conteúdo que a convenção de prefixo faz o app interpretar.
40versões, de 21×21 a 177×177 módulos
4níveis de correção de erro (L/M/Q/H)
2.953 bytescapacidade máxima (versão 40, nível L)
  1. 1994A Denso Wave cria o QR Code

    Masahiro Hara, na fabricante japonesa Denso Wave, projeta o código para rastrear peças automotivas, daí a leitura rápida e omnidirecional.

  2. Junho de 2000Vira norma ISO/IEC 18004

    O QR Code é aprovado como norma internacional. A Denso Wave abre mão de cobrar pela patente, o que dispara a adoção mundial.

  3. 2015 / 2024Edições revisadas da norma

    A ISO/IEC 18004 é atualizada (edições de 2015 e 2024), mas a estrutura de versões e os quatro níveis de correção seguem os mesmos.

  4. 16 de novembro de 2020O Pix entra em operação

    O Banco Central lança o Pix, e o QR de pagamento no padrão BR Code (EMV) vira parte do cotidiano brasileiro.

A camada física: correção de erro, versão e máscara

Parte dos módulos de um QR não guarda o seu texto: guarda redundância. O código usa Reed–Solomon, uma família de correção de erro que trata os dados como coeficientes de um polinômio e adiciona "códigos de verificação" capazes de reconstruir símbolos perdidos. Você escolhe quanta redundância quer entre quatro níveis. Quanto maior o nível, mais dano o código tolera, e mais módulos ele gasta para os mesmos dados, ficando mais denso. Os percentuais abaixo são a fração de dados que o código consegue recuperar se estiverem corrompidos ou cobertos.

Os quatro níveis de correção de erro do QR Code (ISO/IEC 18004).
NívelRecuperação aprox.Quando usar
L (baixo)~7%Impressão limpa e grande; espremer o máximo de dados.
M (médio)~15%Padrão para uso geral (é o padrão do gerador).
Q (quartil)~25%Etiquetas pequenas; logo discreto.
H (alto)~30%Logo grande no centro; ambiente hostil.

A escolha do nível interage com o tamanho. Mais correção significa mais códigos de verificação; para caber tudo, o código sobe de versão e ganha módulos. A capacidade máxima cai à medida que o nível sobe, como mostra o gráfico para a maior versão (40, com 177×177 módulos). Repare que ir de L para H corta a capacidade em mais da metade: é o preço da resistência a dano.

L (~7%)7.089
M (~15%)5.596
Q (~25%)3.993
H (~30%)3.057
Capacidade máxima em modo numérico (dígitos) na versão 40, por nível de correção de erro. Fonte: Denso Wave / ISO/IEC 18004.
Ver os dados
CategoriaValor
L (~7%)7.089
M (~15%)5.596
Q (~25%)3.993
H (~30%)3.057

Antes de virar imagem, os dados passam por um mascaramento. O codificador testa oito máscaras, padrões que invertem certos módulos segundo uma regra, e escolhe a que tem a menor penalidade, uma pontuação que castiga manchas grandes de uma só cor, listras e padrões que imitam os marcadores de posição. Sem isso, um texto azarado poderia gerar uma matriz que o leitor confunde. É por isso que dois QR do mesmo texto, gerados por softwares diferentes, podem ter aparência distinta: escolheram máscaras diferentes, mas decodificam o mesmo conteúdo.

Por que um QR com logotipo no meio ainda funciona

O logo cobre parte dos módulos, exatamente como um risco ou uma mancha. A correção Reed–Solomon reconstrói o que ficou escondido, desde que o dano fique dentro da margem do nível escolhido. No nível H, cerca de 30% dos dados podem sumir e o código ainda lê, por isso um logo central discreto convive bem com H.

A conta tem limite. Se o logo é grande demais, o buraco ultrapassa a margem de recuperação e não há redundância suficiente para reconstruir os dados: o código quebra. A regra prática é manter o logo pequeno e subir o nível de correção, o próprio gerador recomenda Q ou H quando o logo passa de cerca de um quinto da largura.

Máscaras e a "zona de silêncio"

Além da máscara, todo QR precisa de uma borda branca ao redor, a zona de silêncio, de pelo menos quatro módulos. Ela separa o código do que houver em volta para o leitor achar os limites. Cortar essa margem para o código "caber" num espaço apertado é a causa nº 1 de QR que não escaneia, mesmo com a matriz perfeita.

A camada de payload: as convenções de conteúdo

A tabela reúne as convenções mais usadas. Quase todas reaproveitam esquemas de URI que já existem na web (mailto:, tel:, sms:, geo:), o QR não inventou nada, só empacotou o texto num quadrado escaneável. A coluna de especificação mostra que cada "tipo" tem uma fonte: uma RFC, uma norma ou uma referência de facto.

Formatos de payload reconhecidos pelos leitores e sua especificação.
TipoPrefixo / esquemaExemploEspecificação
Linkhttps://https://jkit.toolsRFC 3986 (URI)
E-mailmailto:mailto:[email protected]?subject=OláRFC 6068
Telefonetel:tel:+5511998877665RFC 3966
SMSsms:sms:+5511998877665?body=OiRFC 5724
Localizaçãogeo:geo:-23.5505,-46.6333RFC 5870
Wi-FiWIFI:WIFI:T:WPA;S:CafeGuest;P:Bemvindo2026;;ZXing (de facto)
ContatoBEGIN:VCARDver seção Wi-Fi e vCardRFC 6350 (vCard 4.0)
Contato (compacto)MECARD:MECARD:N:Doe,Jane;TEL:+5511...;;NTT DoCoMo (de facto)
EventoBEGIN:VEVENTagenda um compromissoRFC 5545 (iCalendar)
Pix000201...00020126... (copia e cola)EMV MPM / BR Code (BCB)
Texto puro(sem prefixo)Mesa 12, chame o garçom

Gere qualquer um desses formatos abaixo. A ferramenta monta a string, aplica o nível de correção e devolve a imagem, tudo no navegador, sem enviar seu conteúdo a lugar nenhum. Para salvar o resultado com nitidez, vale entender os formatos de imagem para a web: um QR deve sair em PNG ou SVG, nunca em JPEG, cuja compressão borra as bordas dos módulos.

Escolha o tipo, preencha os campos e veja a string virar matriz. Nível de correção e logo ficam nas opções.Abrir a ferramenta em página inteira

Wi-Fi e vCard, com o escape na prática

O formato de Wi-Fi é um dos mais úteis: coloque a rede num QR e o visitante entra sem digitar a senha. A sintaxe não é uma norma ISO, é a convenção do projeto ZXing, que virou o padrão de facto seguido por praticamente todos os leitores. Os campos são T (tipo de segurança: WPA, WEP ou nopass), S (o SSID) e P (a senha), terminados por dois pontos-e-vírgula. Um exemplo direto:

WIFI:T:WPA;S:CafeGuest;P:Bemvindo2026;;
Wi-Fi WPA com SSID "CafeGuest" e senha "Bemvindo2026".

O detalhe que quebra muita gente é o escape. Como ponto-e-vírgula separa os campos, um SSID ou senha que contenha os caracteres especiais barra invertida, ponto-e-vírgula, vírgula, aspas ou dois-pontos precisa escapá-los com uma barra invertida na frente, a mesma regra do MECARD, segundo o ZXing. Este é o primeiro exemplo trabalhado do guia:

Rede:  Rede;Café      →  Rede\;Café
Senha: sen:ha,123      →  sen\:ha\,123

WIFI:T:WPA;S:Rede\;Café;P:sen\:ha\,123;;
Exemplo trabalhado 1: o ";" e o ":" viram "\;" e "\:"; a "," vira "\,". Sem o escape, o leitor cortaria o SSID em "Rede".

O cartão de contato usa o padrão vCard (RFC 6350, versão 4.0). Cada linha é um campo: FN é o nome de exibição, N separa sobrenome e nome, ORG a organização, TEL o telefone. Vale um aviso de compatibilidade: a RFC 6350 tornou obsoleta a RFC 2426 (vCard 3.0), mas muitos aparelhos e apps de contatos ainda leem melhor a versão 3.0. Se um vCard 4.0 abrir torto em algum celular antigo, gerar a versão 3.0 costuma resolver. Veja um vCard 4.0 completo:

BEGIN:VCARD
VERSION:4.0
FN:Jane Doe
N:Doe;Jane;;;
ORG:Example Studio
TITLE:Product Designer
TEL;VALUE=uri:tel:+5511998877665
EMAIL:[email protected]
URL:https://jkit.tools
END:VCARD
vCard 4.0: um contato completo em texto, uma linha por campo.

Pix: o BR Code campo a campo e o CRC-16

O QR de pagamento Pix segue o BR Code, a implementação brasileira do padrão EMV® QR Code Merchant-Presented Mode (MPM), definida pelo Banco Central no arranjo Pix. A grande sacada é que esse texto é o próprio "Pix copia e cola": quando você copia o código, copia exatamente a string que estaria dentro do QR. Os dois são intercambiáveis porque são o mesmo dado. O BR Code não é texto livre: é uma sequência de campos no formato TLV, identificador (ID) de 2 dígitos, tamanho (length) de 2 dígitos e valor,, terminada por uma verificação CRC-16 no campo 63.

O segundo exemplo trabalhado do guia é um Pix estático completo, com uma chave de e-mail fictícia. Cada linha abaixo é um campo TLV; a indentação em 26 e 62 mostra os subcampos aninhados. Leia como ID, tamanho e valor:

00 02 01                      Payload Format Indicator
26 38                         Merchant Account Information
   00 14 br.gov.bcb.pix       GUI do arranjo Pix
   01 16 [email protected]     chave Pix (e-mail)
52 04 0000                    Merchant Category Code (MCC)
53 03 986                     moeda: 986 = BRL (ISO 4217)
54 05 25.00                   valor da transação (opcional)
58 02 BR                      país (ISO 3166-1)
59 13 FULANO DE TAL           nome do recebedor
60 09 SAO PAULO               cidade do recebedor
62 07                         Additional Data Field
   05 03 ***                  txid (identificador da cobrança)
63 04 674F                    CRC-16 (verificacao final)
Exemplo trabalhado 2: um BR Code Pix estático desmontado campo a campo (ID / tamanho / valor).

A string contínua, sem espaços, fica assim, e é ela, exatamente, que o app lê:

00020126380014br.gov.bcb.pix0116joao@exemplo.com520400005303986540525.005802BR5913FULANO DE TAL6009SAO PAULO62070503***6304674F
O mesmo Pix como "copia e cola". Os últimos quatro dígitos (674F) são o CRC.

O campo 63 fecha o código com um CRC-16 na variante CCITT-FALSE. Ele não é uma assinatura de segurança, é um dígito verificador, como o que fecha um CPF ou um CNPJ (veja o guia de validação de CPF e CNPJ): serve para o app detectar um caractere trocado antes de tentar pagar. O detalhe que engana: o CRC é calculado sobre a string inteira já incluindo o ID e o tamanho do próprio campo 63, ou seja, incluindo os quatro caracteres "6304", mas antes do valor de quatro dígitos. A fórmula parte de um polinômio gerador:

G(x) = x¹⁶ + x¹² + x⁵ + 1 = 0x1021
G(x)
polinômio gerador que define o algoritmo
0x1021
a forma hexadecimal do polinômio (x¹⁶ implícito)
0xFFFF
valor inicial do registrador de 16 bits
O polinômio gerador do CRC-16/CCITT. Os parâmetros do Pix: init 0xFFFF, sem reflexão de bits, xorout 0x0000.
  1. Inicialize o registradorComece com um registrador de 16 bits valendo 0xFFFF (65.535).
  2. Percorra cada bytePara cada caractere da string (do "00..." até e incluindo "6304"), faça o XOR do byte deslocado 8 bits à esquerda no registrador.
  3. Oito deslocamentos por byteRepita 8 vezes: se o bit mais alto (0x8000) estiver ligado, desloque à esquerda e faça XOR com 0x1021; senão, só desloque. Mantenha só 16 bits.
  4. Sem reflexão, sem xoroutNão há reflexão de bits na entrada nem na saída, e o xorout é 0x0000, o resultado é o próprio registrador.
  5. Escreva em hexadecimalFormate em 4 dígitos hexadecimais maiúsculos. Para o exemplo acima, o resultado é 674F. Para conferir o algoritmo, a string "123456789" precisa dar 0x29B1, é o vetor de teste oficial do CRC-16/CCITT-FALSE.

Como o CRC depende de todo o resto, mudar um centavo do valor muda o código inteiro, não dá para editar um BR Code na mão sem recalcular a verificação. Para saber a qual instituição pertence uma chave ou um ISPB, use a lista de participantes do Pix.

Estático vs. dinâmico e o risco do "quishing"

QR estático

  • O dado final está gravado no código.
  • Não muda depois de impresso e não rastreia scans.
  • Funciona para sempre, sem servidor no meio.

QR dinâmico

  • Guarda uma URL curta de redirecionamento.
  • O destino pode ser trocado e os scans, contados.
  • Depende do serviço de redirecionamento continuar no ar.

O gerador de QR Code monta códigos estáticos: o conteúdo (link, Wi-Fi, vCard, Pix) fica todo dentro da imagem, sem intermediários, o que é ideal para privacidade e durabilidade. Prefira o dinâmico só quando precisar mesmo trocar o destino depois ou medir cliques, e, nesse caso, lembre que o código morre se o encurtador sair do ar, e que cada scan passa por um servidor que registra data, hora e, muitas vezes, sua localização aproximada (a mesma pegada de metadados que suas fotos deixam, tema do guia de metadados EXIF).

Quishing: o phishing que chega por QR

Quishing (QR + phishing) explora o fato de que o olho humano não lê um QR. Você não vê o destino antes de escanear, então um código pode levar a um site falso que imita seu banco ou pede login. Num QR dinâmico, a URL visível é só a do encurtador, o destino real fica escondido atrás do redirecionamento.

Defesa prática: leia a prévia da URL que o leitor mostra antes de abrir, desconfie de códigos colados em locais públicos e nunca digite senha numa página aberta por QR sem conferir o domínio. Para pagamento, a regra da seção anterior vale sempre: confira nome e instituição do recebedor na tela do banco.

Perguntas frequentes

O Pix copia e cola é diferente do QR Code Pix?
Não. Os dois são o mesmo BR Code: o "copia e cola" é o texto do código, e o QR é esse texto desenhado numa matriz. Copiar o código ou escanear o QR leva à mesma cobrança, porque são exatamente a mesma string, terminada pelo CRC no campo 63.
Como o CRC do Pix é calculado?
É um CRC-16 na variante CCITT-FALSE: polinômio 0x1021, valor inicial 0xFFFF, sem reflexão de bits e xorout 0x0000. Ele é calculado sobre toda a string, incluindo os caracteres "6304" (o ID e o tamanho do próprio campo do CRC), e escrito em 4 dígitos hexadecimais maiúsculos. Um bom teste do seu código: a string "123456789" precisa resultar em 0x29B1.
Qual nível de correção de erros devo usar?
M para a maioria dos casos, é o padrão do gerador. Suba para Q ou H se colocar um logotipo no centro ou se o código for impresso pequeno ou exposto a desgaste. L só quando precisar espremer o máximo de dados num código limpo e grande. Lembre que subir o nível reduz a capacidade máxima em caracteres.
Por que um QR com logo no meio ainda funciona?
Porque a correção Reed–Solomon reconstrói os módulos escondidos pelo logo, do mesmo jeito que reconstrói um risco. No nível H, cerca de 30% dos dados podem sumir e o código ainda lê. O limite é o tamanho do logo: se ele cobrir mais do que a margem de recuperação, não há redundância suficiente e o código quebra.
Quanta informação cabe num QR Code?
No máximo teórico (versão 40, nível L), cabem cerca de 7.089 dígitos, 4.296 caracteres alfanuméricos ou 2.953 bytes. Na prática, use bem menos: quanto mais dados, mais denso e mais difícil de escanear fica o código. Por isso um QR quase nunca guarda uma imagem ou arquivo, guarda uma URL curta que aponta para o conteúdo hospedado.
Como faço um QR que conecta ao Wi-Fi?
Gere um código com o texto no formato WIFI:T:WPA;S:nome-da-rede;P:senha;;, informando o tipo de segurança, o SSID e a senha. Se o nome ou a senha tiverem ponto-e-vírgula, dois-pontos, vírgula, aspas ou barra invertida, escape cada um com uma barra invertida na frente. O gerador de QR Code monta e escapa isso automaticamente a partir dos campos.

Um QR Code é duas camadas: uma matriz com correção Reed–Solomon (versões 1–40, níveis L/M/Q/H, que explicam o logo no meio) e um texto padronizado por cima. Cada formato é só uma convenção de prefixo, WIFI:, mailto:, BEGIN:VCARD, e o Pix é o BR Code EMV, campos TLV fechados por um CRC-16 (0x1021, init 0xFFFF) no campo 63. Entendendo isso, você gera o código certo, calcula o CRC e reconhece um QR trocado antes de pagar.

Fontes e referências

  1. ISO/IEC 18004, QR Code bar code symbology specification
  2. Denso Wave, Capacidade de informação e versões do QR Code
  3. Banco Central do Brasil, Manual do BR Code
  4. Banco Central do Brasil, Manual de Padrões para Iniciação do Pix
  5. EMVCo, EMV QR Code Specification (Merchant-Presented Mode)
  6. RFC 6350, vCard Format Specification
  7. ZXing, Barcode Contents (formato Wi-Fi, referência de facto)