openssl genrsa -out private.pem 1024 openssl rsa -pubout -in private.pem -out public.pem
<!doctype html> <html> <head> <meta charset="utf-8"> <title></title> <script src="/js/jsencrypt.min.js"></script> <script src="/js/jquery-1.10.2.min.js"></script> </head> <body> <form id="target" action="/send" method="POST"> <label for="User">User:</label> <input type="text" name="User" autofocus required /><br /> <input type="hidden" name="CipheredValue" id="CipheredValue" /><br /> </form> <label for="Password">Password:</label> <input type="password" name="Password" id="Password" required /><br /> <input id="encrypt" type="button" value="send" /> <script> var public_key = "{{printf "%s" .Value}}"; $(function() { $('#encrypt').click(function() { var encrypt = new JSEncrypt(); encrypt.setPublicKey(public_key); var encrypted = encrypt.encrypt($('#Password').val()); $('#CipheredValue').val(encrypted); $('#target').submit(); }); }); </script> </body> </html>Voici le code du handler qui gère la page de connexion. Le code est simple puisqu’il s’agit simplement de servir le template et de remplir la variable contenant la clé publique :
type Page struct { Title string Value []byte } func homeHandler(w http.ResponseWriter, r *http.Request) { // Read the public key pemData, err := ioutil.ReadFile(publicKey) if err != nil { log.Fatalf("read key file: %s", err) } var p = Page{Title: "Login", Value: pemData} err = templates.ExecuteTemplate(w, "home.html", p) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }
func sendHandler(w http.ResponseWriter, r *http.Request) { // Lire le fichier contenant la clé privée pemData, err := ioutil.ReadFile(privateKey) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Décoder le fichier de la clé privée (au format PEM) et tester sa validité block, _ := pem.Decode(pemData) if block == nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if got, want := block.Type, "RSA PRIVATE KEY"; got != want { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Charger la clé privée priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Convertir le message crypté (du formulaire) de la base64 à du binaire cipheredValue, err := base64.StdEncoding.DecodeString(r.FormValue("CipheredValue")) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Déchiffrer le message crypté (le mot de passe) var out []byte out, err = rsa.DecryptPKCS1v15(rand.Reader, priv, cipheredValue) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } var p = Page{Title: "Decrypt value", Value: out} err = templates.ExecuteTemplate(w, "send.html", p) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }Il ne vous reste plus qu’à compléter cet extrait de code avec un système de gestion des utilisateurs. Par exemple, en vérifiant le mot de passe avec une valeur stockée en base de données.
Une traduction du blog officiel de golang expliquant le mécanisme de la réflexion en Go. Lire »
Traduction d'un article du blog officiel expliquant comment échanger des données entre deux programmes golang grâce à un format natif Lire »
La bibliothèque standard de go ne gère pas les variables de session d'une application. Il existe une solution avec le toolkit Gorilla Lire »
Préconisations officielles pour la gestion des erreurs dans un programme golang. Cet article complète les explications sur panic, defer et recover Lire »
Exemples d'utilisation du type chan et des go routines stateful et stateless Lire »
Soyez le premier à commenter cet article
Tous les commentaires sont soumis à modération. Les balises HTML sont pour la plupart autorisées. Les liens contextuels et intéressants sont en follow.