Sécurisation des données avec le chiffrement AES en Go

Le standard AES (Advanced Encryption Standard) est l'un des algorithmes de chiffrement symétrique les plus robustes et les plus utilisés pour protéger les infromations sensibles. Dans l'écosystème Go, les paquets standards crypto/aes et crypto/cipher fournissent les primitives nécessaires pour implémenter différentes méthodes de chiffrement.

Configuration de la clé secrète

La sécurité de l'AES repose sur la confidentialité de la clé. La longueur de cette dernière détermine la variante de l'algorithme :

  • AES-128 : clé de 16 octets.
  • AES-192 : clé de 24 octets.
  • AES-256 : clé de 32 octets.
// Exemple d'une clé de 32 octets pour AES-256
var clePrivee = []byte("a-very-secret-key-32-bytes-long!")

Chiffrement par blocs avec le mode CBC

Le mode CBC (Cipher Block Chaining) nécessite que les données en entrée soient un multiple de la taille du bloc AES (16 octets). Cela implique l'utilisation d'un mécanisme de remplissage (padding), généralement PKCS7.

Gestion du Padding PKCS7

Voici comment ajuster la taille des données avant le traitement :

import "bytes"

func appliquerPadding(source []byte, tailleBloc int) []byte {
   marge := tailleBloc - len(source)%tailleBloc
   remplissage := bytes.Repeat([]byte{byte(marge)}, marge)
   return append(source, remplissage...)
}

func supprimerPadding(source []byte) []byte {
   taille := len(source)
   if taille == 0 {
       return nil
   }
   marge := int(source[taille-1])
   return source[:(taille - marge)]
}

Implémentation du chiffrement CBC

import (
   "crypto/aes"
   "crypto/cipher"
   "crypto/rand"
   "io"
   "fmt"
)

func ChiffrerCBC(donnees, cle []byte) ([]byte, error) {
   bloc, err := aes.NewCipher(cle)
   if err != nil {
       return nil, err
   }

   contenuPadding := appliquerPadding(donnees, aes.BlockSize)
   resultat := make([]byte, aes.BlockSize+len(contenuPadding))
   iv := resultat[:aes.BlockSize]

   // Génération d'un vecteur d'initialisation (IV) unique
   if _, err := io.ReadFull(rand.Reader, iv); err != nil {
       return nil, err
   }

   mode := cipher.NewCBCEncrypter(bloc, iv)
   mode.CryptBlocks(resultat[aes.BlockSize:], contenuPadding)

   return resultat, nil
}

func DechiffrerCBC(donneesCryptees, cle []byte) ([]byte, error) {
   bloc, err := aes.NewCipher(cle)
   if err != nil {
       return nil, err
   }

   if len(donneesCryptees) < aes.BlockSize {
       return nil, fmt.Errorf("données trop courtes")
   }

   iv := donneesCryptees[:aes.BlockSize]
   corps := donneesCryptees[aes.BlockSize:]

   mode := cipher.NewCBCDecrypter(bloc, iv)
   mode.CryptBlocks(corps, corps)

   return supprimerPadding(corps), nil
}

Utilisation du mode GCM (Recommandé)

Le mode GCM (Galois/Counter Mode) est une forme de chiffrement authentifié (AEAD). Il offre à la fois la confidentialité et l'intégrité des données, tout en évitant la complexité liée au padding manuel requis par CBC.

func ChiffrerGCM(message, cle []byte) ([]byte, error) {
   bloc, err := aes.NewCipher(cle)
   if err != nil {
       return nil, err
   }

   aesGCM, err := cipher.NewGCM(bloc)
   if err != nil {
       return nil, err
   }

   nonce := make([]byte, aesGCM.NonceSize())
   if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
       return nil, err
   }

   // Seal ajoute le tag d'authentification automatiquement
   return aesGCM.Seal(nonce, nonce, message, nil), nil
}

func DechiffrerGCM(donnees, cle []byte) ([]byte, error) {
   bloc, err := aes.NewCipher(cle)
   if err != nil {
       return nil, err
   }

   aesGCM, err := cipher.NewGCM(bloc)
   if err != nil {
       return nil, err
   }

   tailleNonce := aesGCM.NonceSize()
   if len(donnees) < tailleNonce {
       return nil, fmt.Errorf("données invalides")
   }

   nonce, texteChiffre := donnees[:tailleNonce], donnees[tailleNonce:]
   return aesGCM.Open(nil, nonce, texteChiffre, nil)
}

Considérations de sécurité

  • Vecteur d'initialisation (IV) : Ne réutilisez jamais le même IV ou Nonce avec la même clé. Utilisez toujours crypto/rand pour assurer l'imprévisibilité.
  • Authentification : Préférez le mode GCM car il détecte toute modification malveillante des données chiffrées, contrairement au mode CBC standard qui nécessite un HMAC supplémentaire.
  • Stockage des clés : Ne stockez jamais de clés de chiffrement en dur dans le code source. Utilisez des variables d'environnement ou des services de gestion de secrets (KMS).

Étiquettes: Go cryptographie AES Sécurité GCM

Publié le 24 juillet à 23h21