Resumo

  • O README do Barry indica ::/0 como recurso IPv6 padrão de uma âncora de confiança, enquanto a issue 7 relata a rejeição dessa mesma grafia em campos de certificado e ROA.
  • No código fixado, dois-pontos e barra são permitidos depois que um token sem aspas começa; porém, o primeiro caractere só pode ser alfanumérico, $ ou . Assim, 0::/0 vira token e ::/0 falha antes do parser de IP.
  • A RFC 4291 admite ::/0, e a RFC 5952 o estabelece como representação canônica. 0::/0 tem o mesmo significado, mas não é a saída com compressão máxima.
  • As fontes não mostram objeto inválido, veredito de relying party, impacto em produção nem mudança de rota. A medida útil é uma tabela de conformidade do lexer ao DER, com a etapa terminal registrada.

Um zero que muda a entrada, não a rede

A diferença inteira cabe em um caractere:

::/0
0::/0

As duas formas representam o endereço IPv6 de 128 bits todo zerado com comprimento de prefixo zero. Portanto, selecionam o espaço IPv6 inteiro. Mesmo assim, a issue 7 do repositório LACNIC/barry relata caminhos diferentes no programa: a forma canônica encontra um caractere inesperado; a forma iniciada por um dígito funciona como contorno.

O limite é relevante porque o Barry gera material RPKI, inclusive material propositalmente incorreto para testar validadores. Um teste negativo só pode receber esse nome depois que uma entrada positiva legítima foi convertida em valor semântico e em bytes identificáveis. Se o idioma do descritor não cria sequer o token, a falha ainda não pertence ao certificado, ao ROA ou ao relying party. Nenhum deles recebeu algo para decidir.

A melhor leitura institucional é simples. Os metadados do repositório descrevem um gerador pequeno, não um serviço operacional. O README preso ao commit analisado chama o projeto e a especificação de Repository Descriptor de trabalhos em andamento e avisa que mudanças incompatíveis podem ocorrer antes da versão 1.0. As listas capturadas de releases e tags estavam vazias. Uma issue pública com exemplo pequeno é uma forma adequada de expor o limite de um protótipo, não prova de dano.

A reprodução e o rastro não têm os mesmos bytes

A issue foi aberta em 28 de agosto de 2026. No corte de 6 de setembro, continuava aberta, sem rótulos, comentários ou atualização posterior. A associação do autor registrada pelo GitHub é NONE. Não há resposta de mantenedor confirmando reprodução, causa ou correção.

O relato coloca ::/0 em dois locais do descritor: a extensão de recursos IP de um certificado de CA e ipAddrBlocks em um ROA. Também oferece 0::/0 como solução provisória. Há, contudo, uma diferença interna que precisa permanecer visível. O descritor exibido usa ::/0 nos dois campos; já o rastro colado imprime primeiro um valor alterado para 0::/0 e, depois, para no primeiro : de outro campo com Unexpected character: : (0x3a).

Isso não invalida o relato. Apenas limita a atribuição. O rastro mostra diretamente uma falha diante de dois-pontos no início. O autor diz que a forma canônica falha nos dois campos. O material público não demonstra de maneira independente dois casos idênticos, byte a byte, em uma única execução. Um recibo de conformidade deve guardar os bytes exatos e o hash justamente porque copiar o contorno para um campo pode mudar o ensaio sem deixar marca.

O rastro tampouco mostra um certificado ou ROA malformado, um repositório publicado ou uma decisão de validador. Não sustenta alteração de rota nem envolvimento do RPKI de produção da LACNIC. Esses eventos ficam depois do limite observado.

A regra do primeiro caractere explica a assimetria

A leitura do código foi fixada no commit 994a598321336baf1767f0fbfb460ed96c29fe4f, de 1º de setembro. Seu assunto implementa authorityCertIssuer no AKI e não afirma resolver a issue 7. O histórico recente de commits determina o ponto de observação, mas não permite atribuir o comportamento a uma mudança específica.

No src/rpki_tree.c, next_token inicia uma string sem aspas somente se o primeiro caractere for alfanumérico, $ ou . Dois-pontos não entra nessa lista. O fluxo cai em try_emoji e um : comum termina como caractere inesperado.

Depois que uma string começou, a regra é mais ampla. Dois-pontos e barra podem permanecer dentro dela, porque a continuação exclui principalmente espaços e separadores estruturais. O zero inicial de 0::/0 não faz uma biblioteca IPv6 aceitar outra rede. Ele satisfaz a porta de entrada; o restante passa a fazer parte do token já aberto.

O próprio README torna a divergência concreta. Ele mostra 2001:db8::/64, que começa por algarismo hexadecimal e atravessa a porta inicial. Também lista ::/0 como recurso IPv6 padrão da âncora de confiança. Portanto, dizer que o programa “aceita IPv6 comprimido” seria impreciso: a compressão depois de um algarismo e a compressão no primeiro caractere percorrem ramos léxicos diferentes.

O componente que entende o prefixo vem depois. Em src/field.c, parse_ip_node separa o texto em /, identifica IPv6 pelos dois-pontos, chama inet_pton e lê o comprimento. A grafia recusada não chega ali. Não é correto atribuir o erro ao inet_pton, ao comprimento do prefixo ou à vinculação de campo.

A forma canônica deve estar no caminho comum

A RFC 4291 permite usar :: para comprimir grupos consecutivos em zero e apresenta :: como o endereço IPv6 todo zerado. A notação de prefixo combina qualquer forma legítima de endereço com / e um comprimento. Assim, ::/0 é entrada IPv6 válida.

A RFC 5952 separa aceitação e emissão. Implementações devem aceitar as formas legítimas da RFC 4291; ao produzir texto, devem usar representação canônica e compressão máxima. 0::/0 conserva a mesma família, valor e comprimento, mas mantém um grupo zero que a saída canônica eliminaria.

Uma verificação local e limitada com IPAddr, do Ruby, normalizou ::/0, 0::/0, 0000::/0 e o endereço zero escrito por inteiro para o mesmo valor e intervalo. Essa verificação não executou o Barry e não supera as RFCs. Ela apenas reforça que o objeto da investigação é a fronteira lexical, não uma suposta diferença semântica.

Na camada de objeto, a RFC 3779 codifica recursos IP como BIT STRING em DER. O bloco que abrange todos os endereços, com prefixo de comprimento zero, torna-se 03 01 00. A grafia do descritor não sobrevive como propriedade do certificado ou ROA. Quando a entrada para no lexer, não existe DER para um relying party aceitar ou rejeitar.

Uma tabela pequena preserva a cadeia de decisão

Não é preciso começar com uma promessa geral de suporte. Cada linha de uma tabela versionada pode registrar os bytes exatos do descritor e seu hash, o campo alvo, o resultado da tokenização, a família/valor/comprimento normalizados, a grafia canônica, o commit do parser e do gerador e, se a construção ocorreu, o hash do objeto.

A etapa terminal deve vir de uma lista estável: descriptor-tokenize, prefix-parse, field-bind, object-build, DER-encode ou RP-validate. Isso impede que uma recusa no gerador seja contada como falha do validador. O invariante central é curto: parse(format(parse(input))) preserva a mesma tupla. Formas legítimas equivalentes devem convergir para o mesmo valor DER quando a geração termina.

Esse instrumento não certifica o Barry nem descreve todo o IPv6. Ele responde a uma pergunta local e auditável: quais bytes entraram, qual valor foi entendido, qual objeto foi criado e qual camada tomou a decisão final. Para um gerador de testes negativos, essa separação é o contrato mais importante.

Fontes