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!")
}
Com isso, você adiciona uma camada extra de segurança simples para o cliente verificar.
Vídeo com a explicação detalhada: