HMAC (Hash-based Message Authentication Code) em Golang

Quando criamos APIs, é recomendável adicionar um cabeçalho de autenticação para garantir a integridade das mensagens. Por exemplo, quando seu servidor recebe uma requisição ou um webhook, inclua um cabeçalho X-Signature com uma assinatura HMAC (Hash-based Message Authentication Code).

Para gerar a assinatura HMAC, você utiliza uma chave secreta e o conteúdo a ser assinado, como o body da requisição. Em seguida, envia a assinatura no cabeçalho. É importante deixar claro o que está sendo assinado. Já enfrentei problemas com clientes que não conseguiam validar a assinatura porque usavam o body parseado como JSON em vez do body raw recebido na requisição.

Manter a chave secreta segura é fundamental. Uma boa prática é usar duas chaves: uma para suas comunicações com o cliente e outra para comunicações do cliente com você. Além disso, as chaves devem ser longas e aleatórias.

A assinatura HMAC não substitui o uso de HTTPS; ela adiciona uma camada extra de segurança. Outra opção interessante é usar mTLS (mutual TLS), que oferece maior segurança. Você pode combinar essas camadas para criar um sistema robusto.

Aqui está um exemplo de como usar HMAC em Golang:

func HMACSign(payload, key []byte) string {
    mac := hmac.New(sha256.New, key)
    mac.Write(payload)
    return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}

A função HMACSign recebe o payload e a chave secreta e retorna a assinatura em base64. Você pode enviar essa assinatura no cabeçalho da sua requisição.

func HMACVerify(payload, key []byte, receivedSig string) bool {
    rMac, err := base64.StdEncoding.DecodeString(receivedSig)
    if err != nil {
        return false
    }

    eMac := hmac.New(sha256.New, key)
    eMac.Write(payload)

    return hmac.Equal(eMac.Sum(nil), rMac)
}

A função HMACVerify recebe o payload, a chave secreta e a assinatura recebida. Ela retorna true se a assinatura for válida e false caso contrário.

payload := []byte("Conteúdo da mensagem a ser assinada")
key := []byte("MinhaChaveSecretaSuperSegura")

signature := HMACSign(payload, key)
fmt.Println("Assinatura:", signature)

if HMACVerify(payload, key, signature) {
    fmt.Println("Assinatura válida!")
}

código fonte

Com isso, você adiciona uma camada extra de segurança simples para o cliente verificar.

Vídeo com a explicação detalhada:

Cesar Gimenes

Última modificação