160 lines
3.8 KiB
Go
Executable File
160 lines
3.8 KiB
Go
Executable File
package main
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
encrypt "fckeuspy-go/lib"
|
|
)
|
|
|
|
func NewServer() *http.ServeMux {
|
|
server := &http.ServeMux{}
|
|
|
|
// 3) routing
|
|
server.HandleFunc("/", indexHandler)
|
|
server.HandleFunc("/public.pem", publicKeyHandler)
|
|
server.HandleFunc("/public.crt", publicCertHandler)
|
|
server.HandleFunc("/encrypt", encryptHandler)
|
|
server.HandleFunc("/decrypt", decryptHandler)
|
|
server.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
|
|
|
// log.Println("Server běží na http://localhost:8080")
|
|
|
|
return server
|
|
}
|
|
|
|
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
|
_ = tmpl.ExecuteTemplate(w, "index.html", nil)
|
|
}
|
|
|
|
func publicKeyHandler(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/x-pem-file")
|
|
w.Write(pubPEM)
|
|
}
|
|
|
|
func publicCertHandler(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/x-pem-file")
|
|
w.Write(certPEM)
|
|
}
|
|
|
|
func encryptHandler(w http.ResponseWriter, r *http.Request) {
|
|
if err := r.ParseForm(); err != nil {
|
|
http.Error(w, "Bad form", http.StatusBadRequest)
|
|
return
|
|
}
|
|
msg := r.Form.Get("message")
|
|
peer := r.Form.Get("pubkey") // může to být PEM PUBLIC KEY nebo CERT
|
|
|
|
pubKey, err := encrypt.ParsePeerPublicKey(peer)
|
|
if err != nil {
|
|
http.Error(w, "Neplatný public key/cert: "+err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// --- hybrid: AES-GCM + RSA-OAEP(SHA-256) ---
|
|
// 1) vygeneruj náhodný sym. klíč
|
|
aesKey := make([]byte, 32) // AES-256
|
|
if _, err := rand.Read(aesKey); err != nil {
|
|
http.Error(w, "Rand fail", 500)
|
|
return
|
|
}
|
|
|
|
block, err := aes.NewCipher(aesKey)
|
|
if err != nil {
|
|
http.Error(w, "AES fail", 500)
|
|
return
|
|
}
|
|
gcm, err := cipher.NewGCM(block)
|
|
if err != nil {
|
|
http.Error(w, "GCM fail", 500)
|
|
return
|
|
}
|
|
|
|
nonce := make([]byte, gcm.NonceSize())
|
|
if _, err := rand.Read(nonce); err != nil {
|
|
http.Error(w, "Nonce fail", 500)
|
|
return
|
|
}
|
|
|
|
ciphertext := gcm.Seal(nil, nonce, []byte(msg), nil)
|
|
|
|
// 2) zašifruj AES klíč cizím RSA klíčem (OAEP SHA-256)
|
|
label := []byte{} // prázdný label
|
|
ek, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, pubKey, aesKey, label)
|
|
if err != nil {
|
|
http.Error(w, "RSA-OAEP fail: "+err.Error(), 500)
|
|
return
|
|
}
|
|
|
|
env := envelope{
|
|
EK: base64.StdEncoding.EncodeToString(ek),
|
|
N: base64.StdEncoding.EncodeToString(nonce),
|
|
CT: base64.StdEncoding.EncodeToString(ciphertext),
|
|
}
|
|
|
|
payload, _ := json.MarshalIndent(env, "", " ")
|
|
_ = tmpl.ExecuteTemplate(w, "encrypt.html", string(payload))
|
|
}
|
|
|
|
func decryptHandler(w http.ResponseWriter, r *http.Request) {
|
|
if err := r.ParseForm(); err != nil {
|
|
http.Error(w, "Bad form", http.StatusBadRequest)
|
|
return
|
|
}
|
|
in := r.Form.Get("payload")
|
|
|
|
var env envelope
|
|
if err := json.Unmarshal([]byte(in), &env); err != nil {
|
|
http.Error(w, "Neplatné JSON", 400)
|
|
return
|
|
}
|
|
|
|
ek, err := base64.StdEncoding.DecodeString(env.EK)
|
|
if err != nil {
|
|
http.Error(w, "ek base64", 400)
|
|
return
|
|
}
|
|
nonce, err := base64.StdEncoding.DecodeString(env.N)
|
|
if err != nil {
|
|
http.Error(w, "nonce base64", 400)
|
|
return
|
|
}
|
|
ct, err := base64.StdEncoding.DecodeString(env.CT)
|
|
if err != nil {
|
|
http.Error(w, "ct base64", 400)
|
|
return
|
|
}
|
|
|
|
// 1) rozšifruj AES klíč naším RSA
|
|
label := []byte{}
|
|
aesKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, priv, ek, label)
|
|
if err != nil {
|
|
http.Error(w, "RSA-OAEP decrypt fail: "+err.Error(), 400)
|
|
return
|
|
}
|
|
|
|
block, err := aes.NewCipher(aesKey)
|
|
if err != nil {
|
|
http.Error(w, "AES fail", 500)
|
|
return
|
|
}
|
|
gcm, err := cipher.NewGCM(block)
|
|
if err != nil {
|
|
http.Error(w, "GCM fail", 500)
|
|
return
|
|
}
|
|
plain, err := gcm.Open(nil, nonce, ct, nil)
|
|
if err != nil {
|
|
http.Error(w, "GCM open fail: "+err.Error(), 400)
|
|
return
|
|
}
|
|
|
|
_ = tmpl.ExecuteTemplate(w, "decrypt.html", string(plain))
|
|
}
|