From 02e6457443a119211351e3ac584b8ea3c7cadaa4 Mon Sep 17 00:00:00 2001 From: eater <=@eater.me> Date: Sun, 11 Aug 2019 14:47:08 +0200 Subject: [PATCH] Fix crypto --- crypto.go | 117 +++++++++++++++++++++++++++++++++++++++++++++++ crypto_test.go | 29 ++++++++++++ http.go | 121 ++++--------------------------------------------- 3 files changed, 154 insertions(+), 113 deletions(-) create mode 100644 crypto.go create mode 100644 crypto_test.go diff --git a/crypto.go b/crypto.go new file mode 100644 index 0000000..769a107 --- /dev/null +++ b/crypto.go @@ -0,0 +1,117 @@ +package service + +import ( + cipher2 "crypto/cipher" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "errors" + "golang.org/x/crypto/blowfish" + "io" +) + +type BaseMessage struct { + Signature string +} + +func DecryptAndVerify(input []byte, key *rsa.PrivateKey, pub *rsa.PublicKey, signature []byte, v interface{}) error { + all, err := hex.DecodeString(string(input)) + if err != nil { + return err + } + + encPasswordAndIV := all[:512] + encBody := all[512:] + + passwordAndIV, err := rsa.DecryptPKCS1v15(rand.Reader, key, encPasswordAndIV) + + if err != nil { + return err + } + + password := passwordAndIV[:32] + iv := passwordAndIV[32:] + + cipher, err := blowfish.NewCipher(password) + + if err != nil { + return err + } + + body := make([]byte, len(encBody)) + dec := cipher2.NewCBCDecrypter(cipher, iv) + dec.CryptBlocks(body, encBody) + err = json.Unmarshal(body, v) + + if err != nil { + return err + } + + baseReq, ok := v.(*BaseMessage) + if !ok { + return errors.New("non-base request") + } + + recvSignature, err := hex.DecodeString(baseReq.Signature) + if err != nil { + return err + } + + fingerprint := signature + fingerprintHashed := sha256.Sum256(fingerprint) + err = rsa.VerifyPKCS1v15(pub, 0, fingerprintHashed[:], recvSignature) + return err +} + +func EncryptAndSign(v interface{}, key *rsa.PrivateKey, pub *rsa.PublicKey, signature []byte, writer io.Writer) error { + passwordAndIV := make([]byte, 40) + _, err := rand.Read(passwordAndIV) + if err != nil { + return err + } + + encPasswordAndIV, err := rsa.EncryptPKCS1v15(rand.Reader, pub, passwordAndIV) + if err != nil { + return err + } + + _, err = writer.Write([]byte(hex.EncodeToString(encPasswordAndIV))) + if err != nil { + return err + } + + password := passwordAndIV[:32] + iv := passwordAndIV[32:] + + cipher, err := blowfish.NewCipher(password) + if err != nil { + return err + } + + hashedFingerpint := sha256.Sum256(signature) + plainSignature, err := rsa.SignPKCS1v15(rand.Reader, key, 0, hashedFingerpint[:]) + if err != nil { + return err + } + + sign, ok := v.(*BaseMessage) + if !ok { + return errors.New("given message can't be signed") + } + sign.Signature = hex.EncodeToString(plainSignature) + + body, err := json.Marshal(v) + + if err != nil { + return err + } + + encBody := make([]byte, len(body)) + enc := cipher2.NewCBCEncrypter(cipher, iv) + enc.CryptBlocks(encBody, body) + writer.Write([]byte(hex.EncodeToString(encBody))) + + return nil +} diff --git a/crypto_test.go b/crypto_test.go new file mode 100644 index 0000000..4c6c604 --- /dev/null +++ b/crypto_test.go @@ -0,0 +1,29 @@ +package service_test + +import ( + "bytes" + "crypto/rand" + "crypto/rsa" + "git.cijber.net/zer.ooo/service" + "testing" +) + +func TestSingleRound(t *testing.T) { + keyA, _ := rsa.GenerateKey(rand.Reader, 4096) + keyB, _ := rsa.GenerateKey(rand.Reader, 4096) + signature := []byte("Hello world!") + v := &service.BaseMessage{} + x := make([]byte, 0) + b := bytes.NewBuffer(x) + err := service.EncryptAndSign(v, keyA, &keyB.PublicKey, signature, b) + + if err != nil { + t.Errorf("Failed encrypting: %s", err) + } + + err = service.DecryptAndVerify(b.Bytes(), keyB, &keyA.PublicKey, signature, &service.BaseMessage{}) + + if err != nil { + t.Errorf("Failed decrypting: %s", err) + } +} diff --git a/http.go b/http.go index c6f8827..7352108 100644 --- a/http.go +++ b/http.go @@ -1,20 +1,12 @@ package service import ( - "crypto/rand" - "crypto/rsa" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "errors" "io/ioutil" "log" "net/http" "strings" ) -import "golang.org/x/crypto/blowfish" - type Status int const ( @@ -23,11 +15,7 @@ const ( ERROR ) -type BaseMessage struct { - Signature string -} - -type httpServer struct { +type HttpServer struct { manager *Manager status Status } @@ -52,11 +40,11 @@ type DeliverCertificateRequest struct { Certificate string } -func NewHttpServer(manager *Manager) *httpServer { - return &httpServer{manager, WAITING} +func NewHttpServer(manager *Manager) *HttpServer { + return &HttpServer{manager, WAITING} } -func (it *httpServer) Start() { +func (it *HttpServer) Start() { http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { log.Printf("%s /", strings.ToUpper(request.Method)) writer.WriteHeader(200) @@ -126,108 +114,15 @@ func (it *httpServer) Start() { http.ListenAndServe(":7864", nil) } -func (it *httpServer) writeResponse(writer http.ResponseWriter, v interface{}) error { - passwordAndIV := make([]byte, 48) - _, err := rand.Read(passwordAndIV) - if err != nil { - return err - } - - encPasswordAndIV, err := rsa.EncryptPKCS1v15(rand.Reader, it.manager.CAPublicKey(), passwordAndIV) - if err != nil { - return err - } - - _, err = writer.Write([]byte(hex.EncodeToString(encPasswordAndIV))) - if err != nil { - return err - } - - password := passwordAndIV[:32] - iv := passwordAndIV[32:] - - cipher, err := blowfish.NewSaltedCipher(password, iv) - if err != nil { - return err - } - - hashedFingerpint := sha256.Sum256(it.manager.GetServerFingerprint()) - plainSignature, err := rsa.SignPKCS1v15(rand.Reader, it.manager.privateKey, 0, hashedFingerpint[:]) - if err != nil { - return err - } - - sign, ok := v.(*BaseMessage) - if !ok { - return errors.New("Given message can't be signed") - } - sign.Signature = hex.EncodeToString(plainSignature) - - body, err := json.Marshal(v) - - if err != nil { - return err - } - - encBody := make([]byte, len(body)) - cipher.Encrypt(encBody, body) - writer.Write([]byte(hex.EncodeToString(encBody))) - - return nil +func (it *HttpServer) writeResponse(writer http.ResponseWriter, v interface{}) error { + return EncryptAndSign(v, it.manager.privateKey, it.manager.CAPublicKey(), it.manager.GetServerFingerprint(), writer) } -func (it *httpServer) verifyRequest(r *http.Request, v interface{}) (error) { +func (it *HttpServer) verifyRequest(r *http.Request, v interface{}) (error) { hexBody, err := ioutil.ReadAll(r.Body) if err != nil { return err } - all, err := hex.DecodeString(string(hexBody)) - if err != nil { - return err - } - - log.Printf("req: %s", hexBody) - - encPasswordAndIV := all[:256] - encBody := all[256:] - - passwordAndIV, err := rsa.DecryptPKCS1v15(rand.Reader, it.manager.privateKey, encPasswordAndIV) - - if err != nil { - return err - } - - password := passwordAndIV[:32] - iv := passwordAndIV[32:] - - cipher, err := blowfish.NewSaltedCipher(password, iv) - - if err != nil { - return err - } - - body := make([]byte, len(encBody)) - cipher.Decrypt(body, encBody) - - err = json.Unmarshal(body, v) - - if err != nil { - return err - } - - baseReq, ok := v.(*BaseMessage) - if !ok { - return errors.New("non-base request") - } - - signature, err := hex.DecodeString(baseReq.Signature) - if err != nil { - return err - } - - fingerprint := it.manager.GetServerFingerprint() - fingerprintHashed := sha256.Sum256(fingerprint) - err = rsa.VerifyPKCS1v15(it.manager.CAPublicKey(), 0, fingerprintHashed[:], signature) - return err + return DecryptAndVerify(hexBody, it.manager.privateKey, it.manager.CAPublicKey(), it.manager.GetServerFingerprint(), v) }