Otimizando a Verificação de Integridade de Mensagens com FNV-1a em Go

Vimos no artigo HMAC (Hash-based Message Authentication Code) como essa técnica garante que a mensagem não foi alterada durante o transporte e confirma a validade da assinatura.

No entanto, esse processo, embora seguro, é lento e consome muitos recursos. Quando precisamos apenas verificar a integridade da mensagem sem validar uma assinatura, podemos usar uma função de hash mais rápida. Para isso, utilizaremos o algoritmo FNV-1a (Fowler-Noll-Vo), conhecido por sua rapidez e baixa taxa de colisão.

Primeiro, vamos criar um pool de hashes para evitar a alocação de memória a cada chamada da função de hash. Isso reduz a pressão sobre o garbage collector.

var (
    hashPool = sync.Pool{
        New: func() interface{} {
            return fnv.New32a()
        },
    }
)

Para gerenciar o pool de hashes, criaremos duas funções: uma para obter um hash do pool e outra para devolvê-lo.

func getHash() hash.Hash32 {
    return hashPool.Get().(hash.Hash32)
}

func putHash(h hash.Hash32) {
    hashPool.Put(h)
}

Agora, vamos criar uma função para calcular o checksum da mensagem. Essa função obtém um hash do pool, calcula o checksum e devolve o hash para o pool.

func checksum(data []byte) uint32 {
    hash := getHash()
    defer putHash(hash)
    hash.Reset()
    _, _ = hash.Write(data)
    return hash.Sum32()
}

código fonte completo

A partir de agora, podemos usar a função checksum para calcular o hash da mensagem. Esse sistema é muito mais rápido que o HMAC e ideal para sistemas como um broker de mensagens, que precisa transmitir um grande fluxo de informações.

Esse sistema não verifica a autenticidade da mensagem, apenas sua integridade. Contudo, em muitos casos, isso é suficiente. A segurança pode ser garantida por outros meios, como uma conexão segura TLS.

Vídeo com a explicação do código:

Cesar Gimenes

Última modificação