Configuration de l'environnement Front end
L'intégration de portefeuilles décentralisés (tels que MetaMask ou OKX) nécessite une gestion rigoureuse des dépendances et des outils modernes. Pour initialiser un projet Vue 3, il est recommandé d'utiliser pnpm comme gestionnaire de paquets, car il optimise l'espace disque et accélère les installations grâce à son système de liens symboliques.
Commencez par mettre à jour l'interface de ligne de commande Vue et installez pnpm :
npm uninstall vue-cli -g
npm install -g @vue/cli
npm install -g pnpm
Ensuite, installez la bibliothèque Ethers.js dans votre projet. Il est impératif d'utiliser une version 5.x ou supérieure pour bénéficier du support complet des opérations asynchrones modernes :
pnpm install ethers@5.7.2 --save
Connexion au Wallet et Génération de Signature
La version 5 d'Ethers.js s'appuie fortement sur les mots-clés async et await, permettant d'écrire du code asynchrone de manière synchrone sans bloquer le thread principal. Cela simplifie considérablement la gestion des Promesses lors de l'interaction avec le fournisseur Web3.
Voici une implémentation modulaire pour connecter le wallet, récupérer l'adresse publique et générer une signature cryptographique basée sur un horodatage :
import { ethers } from "ethers";
export async function authenticateWallet() {
if (!window.ethereum) {
throw new Error("Aucun fournisseur Web3 détecté dans le navigateur.");
}
// Initialisation du fournisseur et demande de connexion
const web3Provider = new ethers.providers.Web3Provider(window.ethereum);
await web3Provider.send("eth_requestAccounts", []);
const walletSigner = web3Provider.getSigner();
const userAddress = await walletSigner.getAddress();
// Création du message à signer avec un horodatage Unix
const currentTimestamp = Math.floor(Date.now() / 1000);
const payload = `Authentification Web3: ${currentTimestamp}`;
// Demande de signature au wallet
const cryptographicSignature = await walletSigner.signMessage(payload);
return {
address: userAddress,
signature: cryptographicSignature,
timestamp: currentTimestamp
};
}
Lors de l'exécution, le wallet de l'utilisateur affichera une invite pour signer le message. Une fois approuvé, la fonction retourne l'adresse publique et la signature hexadécimale, qui devront être trasnmises au serveur pour validation.
Vérification de la Signature côté Backend avec Golang
Exposer la logique de validation uniquement côté client présente un risque de sécurité majeur : un acteur malveillant pourrait intercepter ou modifier les données avant leur envoi. Il est donc obligatoire de vérifier la signature côté serveur pour s'assurer que le message a bien été signé par le propriétaire légitime de l'adresse publique.
Pour réaliser cette opération en Golang, nous utiliserons la bibliothèque sigverify combinée aux utilitaires de go-ethereum. Installez les dépendances nécessaires :
go get github.com/storyicon/sigverify
go get github.com/ethereum/go-ethereum/common
L'implémentation suivante encapsule la logique de vérification dans une structure dédiée, assurant ainsi une meilleure lisibilité et maintenabilité du code :
package main
import (
"fmt"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/storyicon/sigverify"
)
// AuthPayload regroupe les données nécessaires à la vérification
type AuthPayload struct {
WalletAddress string
Message string
Signature string
}
// validateWeb3Signature vérifie l'authenticité de la signature cryptographique
func validateWeb3Signature(payload AuthPayload) (bool, error) {
targetAddress := common.HexToAddress(payload.WalletAddress)
isValid, err := sigverify.VerifyEllipticCurveHexSignatureEx(
targetAddress,
[]byte(payload.Message),
payload.Signature,
)
return isValid, err
}
func main() {
// Données reçues depuis le client frontend
clientPayload := AuthPayload{
WalletAddress: "0x5cae6c39a56d99d68e7a20c76da0ec387e34249b",
Message: "Authentification Web3: 1670142219",
Signature: "0xc7b06789e6710652d8540487055e0e75918c9c4366ec47c9e7008760df1dedd6506a908f466e448481afed3fe009bbdbfdfa16c28585eff68be54d600083d4251b",
}
verified, validationErr := validateWeb3Signature(clientPayload)
if validationErr != nil {
log.Fatalf("Erreur lors de la vérification cryptographique: %v", validationErr)
}
fmt.Printf("Signature valide: %t\n", verified)
}
La fonction VerifyEllipticCurveHexSignatureEx prend en paramètre l'adresse Ethereum cible, le message original non modifié et la signature hexadécimale. Si la signature correspond mathématiquement à l'adresse publique fournie, le serveur reçoit une confirmation booléenne positive :
Signature valide: true