Utilisation des algorithmes Blake2s et Ed25519 afin d'identifier des accès sans transférer le mot de passe "en clair" sur le réseau.
golang ed25519 blake2s password securite

EDITO: Un certains temps que je n’ai pas posté d’articles, cela a été mouvementé pour moi depuis Avril, j’ai changé d’entreprise quittant pour le coup tout un investissement intellectuel de 3 ans. Voilà, je suis passé à autre chose ^^

Encore un dispositif d’identification pour Internet, pfff … encore un !

Oui mais non ^^

Aujourd’hui, trop peu de développeurs prennent les précautions inhérentes au respects des règles de sécurité.

Souvent la Sécurité est un domaine perçu comme difficile, obscur, voir contraignant. Laissant la sécurité être gérée par des contre-mesures périmétriques (Firewall, WAF, etc.), cependant le code est le premier lieu pour contrôler les risques.

Auth Basic over HTTP => la Base 64 n’est pas un algorithme de chiffrement …

Partant de ce constat, j’ai implémenté un dispositif de challenge / response basé sur la dérivation de clés.

$ go get -u -v go.zenithar.org/anvil

Github

L’idée

Le principe est simple utiliser le secret Login / Mot de passe pour en dériver une paire de clés cryptographiques, et effectuer une signature d’un challenge partagé.

Séquence :

Pouvoir faire une identification complète sans déléguer la sécurité au transport (TLS / mTLS / etc.).

L’algorithme

Anvil

Dérivation de clés

Nous allons utiliser l’algorithme Blake2s pour condenser le mot de passe. Le login sera utilisé comme salaison à l’algorithme de dérivation de clés scrypt. La dérivation est configurée pour générer un tampon de 32 octets déterministe, ce tampon permet de créer une paire de clés x25519 (256 bits) pour effectuer des signatures ed25519.

// Hash password using Blake2s (32byte)
key := blake2s.Sum256([]byte(password))

// Use login as salt
salt := []byte(principal)

// Prepare scrypt parameters
N := int(math.Pow(2, 17)) // CPU/Cost
r := 8 // Block size parameter
p := 1 // Parallelism
keyLen := 32 // Derived key length

// Generate 32 bytes from login/password using scrypt derivation
keyRaw, err := scrypt.Key(key[:], salt, N, r, p, keyLen)
...

// Prepare ed25519 keys from 32 bytes generated buffer
read := bytes.NewReader(keyRaw)
pub, priv, err := ed25519.GenerateKey(read)

Cette opération est faite sur le client, sans échange, le secret réside sur la génération et la conservation de la clé privée.

Enregistrement de l’utilisateur

Pour enregistrer un utilisateur, il faut dériver la paire de clés sur le client et transmettre la clé publique au serveur.

Identification

L’identification commence par la dérivation de la paire de clés à partir du Login / Mot de passe.

Pour commencer le processus d’identification, il faut 2 phases :

Les challenges doivent être générés sans vérifier l’existence de l’utilisateur (Time-Attack / User Enumeration)

La vérification du challenge et des paramètres de la signature doivent être fait en temps constant, sans oublier le traitement de la vérification de l’existence de l’utilisateur ne doit pas non plus être statistiquement identifiable (Time-Attack / User Enumeration)

Pour aller plus loin

Il est tout à fait possible d’utiliser des box NaCL avec des clés asymétriques jetables.

Conclusion

Voilà, j’espère ne pas vous avoir perdu ^^ C’est une méthode d’identification qui évite le transport du mot de passe en clair sur le réseau. Je pourrais aborder plus en détails la séquence d’identification out-of-band imaginé mêlant authentification multi-facteur et anvil mais cela sera un prochain article.

Persistence adapter implementations
architecture microservice golang

We are about to prepare a Golang project according to Clean and Hexagonal Architecture principles.
architecture microservice golang

During my software developer experience, I have seen many bad practices as a code reviewer and collected a lot of tips to try to build better products.
architecture microservice golang