Implementação de Assinatura HMAC-SHA256 em Aplicações Vue.js

No desenvolvimento de aplicações Vue.js, a geração de assinaturas digitais utilizando o algoritmo HMAC-SHA256 é crucial para garantir a integridade e autenticidade dos dados. O processo típico inclui coletar os dados necessários, formatá-los conforme o protocolo, calcular a assinatura com uma chave secreta e incorporá-la nas requisições, seja via cabeçalhos HTTP, parâmetros ou corpo da mensagem.

Instalação da Biblioteca

Para implementar a funcionalidade, é necessário instalar a biblioteca CryptoJS usando npm:

npm install crypto-js

Exemplo em Vue 2

Veja como integrar a assinatura HMAC-SHA256 em um componente Vue 2, com variáveis e lógica adaptadas:

<template>
  <div>
    <h1>Demonstração de Assinatura</h1>
    <button @click="criarAssinatura">Criar Assinatura</button>
    <p>Resultado: {{ assinaturaGerada }}</p>
  </div>
</template>

<script>
import CryptoJS from "crypto-js";

export default {
  data() {
    return {
      assinaturaGerada: "",
    };
  },
  methods: {
    criarAssinatura() {
      // Dados de exemplo para assinatura
      const corpoDados = {
        conteudo: "Exemplo de texto",
        nonce: 42,
      };

      // Chave secreta (em produção, deve ser protegida)
      const segredo = "exemplo_chave";

      // Processar os dados: ordenar chaves e concatenar
      const chavesOrdenadas = Object.keys(corpoDados).sort();
      const parametrosFormatados = chavesOrdenadas.reduce((acumulador, chave) => {
        return acumulador + `${chave}=${corpoDados[chave]}&`;
      }, "").replace(/&$/, ""); // Remove o '&' final

      // Gerar o hash HMAC-SHA256
      const resultadoHash = CryptoJS.HmacSHA256(parametrosFormatados, segredo);

      // Converter para formato hexadecimal legível
      this.assinaturaGerada = CryptoJS.enc.Hex.stringify(resultadoHash);
    },
  },
};
</script>

<style scoped>
h1 {
  font-size: 1.5em;
}
</style>

Explicação do Código

No código acima, os dados são processadoss usando Object.keys e reduce para ordenar e concatenar em uma string no formato chave=valor. A assinatura é calculada com CryptoJS.HmacSHA256 e convertida para hexadecimal.

Considerações Práticas

Ao usar assinaturas em aplicações reais, é vital considerar:

  • Segurança: Chaves secretas não devem ser expostas no frontend; idealmente, a assinatura deve ser gerada no backend.
  • Codificação: Dados podem necessitar de encoding, como URL encoding, dependendo da API.
  • Proteção contra replay: Incluir timestamps ou nonces nos dados ajuda a prevenir ataques de repetição.

Exemplo de Requisição HTTP Assinada

Integre a assinatura em uma chamada de API usando Axios:

<template>
  <div>
    <h1>Requisição com Assinatura</h1>
    <button @click="enviarRequisicaoAssinada">Enviar</button>
    <p>Resposta: {{ resultadoRequisicao }}</p>
  </div>
</template>

<script>
import axios from 'axios';
import CryptoJS from 'crypto-js';

export default {
  data() {
    return {
      resultadoRequisicao: ''
    };
  },
  methods: {
    gerarHashAssinatura(dados, chave) {
      const chaves = Object.keys(dados).sort();
      const textoOrdenado = chaves.map(chave => `${chave}=${dados[chave]}`).join('&');
      const hash = CryptoJS.HmacSHA256(textoOrdenado, chave);
      return CryptoJS.enc.Hex.stringify(hash);
    },
    async enviarRequisicaoAssinada() {
      const dadosApi = {
        acao: 'consultar',
        timestamp: Math.floor(Date.now() / 1000)
      };

      const chavePrivada = 'minha_chave_secreta';
      const assinatura = this.gerarHashAssinatura(dadosApi, chavePrivada);

      try {
        const resposta = await axios.post('https://api.exemplo.com/endpoint', dadosApi, {
          headers: {
            'X-Signature': assinatura
          }
        });
        this.resultadoRequisicao = resposta.data;
      } catch (erro) {
        this.resultadoRequisicao = erro.message;
      }
    }
  }
};
</script>

<style scoped>
h1 {
  font-size: 1.5em;
}
</style>

Exemplo em HTML Puro

Para cenários sem framework, aqui está uma impplementação básica com JavaScript puro:


<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Assinatura HMAC-SHA256</title>
  <style>
    h1 { font-size: 1.5em; }
    .botao { padding: 10px; background-color: #007bff; color: white; border: none; cursor: pointer; }
    .resultado { margin-top: 10px; font-family: monospace; }
  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
</head>
<body>
  <h1>Exemplo de Assinatura</h1>
  <button class="botao" onclick="criarAssinatura()">Gerar Assinatura</button>
  <p class="resultado">Assinatura: <span id="assinaturaSpan"></span></p>

  <script>
    function criarAssinatura() {
      const informacoes = {
        mensagem: "Teste de assinatura",
        valor: 123,
      };

      const segredo = "chave_para_teste";

      const chaves = Object.keys(informacoes).sort();
      const dadosConcatenados = chaves.reduce((acumulador, chave) => {
        return acumulador + `${chave}=${informacoes[chave]}&`;
      }, "").slice(0, -1);

      const hashGerado = CryptoJS.HmacSHA256(dadosConcatenados, segredo);
      const assinaturaFinal = CryptoJS.enc.Hex.stringify(hashGerado);

      document.getElementById("assinaturaSpan").textContent = assinaturaFinal;
    }
  </script>
</body>
</html>

Tags: Vue.js hmac-sha256 crypto-js javascript assinatura-digital

Publicado em 6-22 00:44