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>