summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--http-client/client.go43
-rw-r--r--http-client/cryptography.go39
2 files changed, 82 insertions, 0 deletions
diff --git a/http-client/client.go b/http-client/client.go
index a83659e..d448b8c 100644
--- a/http-client/client.go
+++ b/http-client/client.go
@@ -29,6 +29,8 @@ var storage struct {
binding binding.ExternalStringList
}
+var userKeys = make(map[string]string)
+
type Request struct {
User string
Data string
@@ -106,6 +108,26 @@ func tryAuth(user UserData) (bool, error) {
}
}
+func getUserKey(user UserData, checkedUser string) (string, error) {
+ var resp Response
+ httpResp, err := makeRequest(Request{
+ User: user.Username,
+ Data: checkedUser,
+ }, GetUserKey, user)
+ if err != nil {
+ return "", err
+ }
+
+ body, _ := io.ReadAll(httpResp.Body)
+ _ = json.Unmarshal(body, &resp)
+
+ if httpResp.StatusCode == http.StatusOK {
+ return resp.Message, nil
+ } else {
+ return "", errors.New(resp.Message)
+ }
+}
+
func pingServer(user UserData) error {
_, err := http.Get(user.ServerUrl)
return err
@@ -157,6 +179,27 @@ func runClient(user UserData) {
storage.Lock()
for _, signedMessage := range signedMessages {
msg, _ := parseMessage(signedMessage)
+ userKey, ok := userKeys[msg.User]
+ if !ok {
+ key, err := getUserKey(user, msg.User)
+ if err != nil {
+ fmt.Printf("Error occurred when polling user (%s) key\n", msg.User)
+ continue
+ }
+ userKey = key
+ userKeys[msg.User] = key
+ }
+ passed, err := checkSignature(msg.Payload, msg.Signature, userKey)
+ if !passed {
+ fmt.Printf("Message didn't pass signature check. From %s: %s\n", msg.User, msg.Data)
+ continue
+ }
+ if err != nil {
+ fmt.Printf(
+ "Error occurred when checking signature of message. From %s: %s\n",
+ msg.User, msg.Data)
+ }
+
fmt.Printf("Polled new message from %s: %s\n", msg.User, msg.Data)
_ = storage.binding.Append(msg.toString())
storage.messages = append(storage.messages, msg)
diff --git a/http-client/cryptography.go b/http-client/cryptography.go
index 175e60b..135f6b2 100644
--- a/http-client/cryptography.go
+++ b/http-client/cryptography.go
@@ -9,6 +9,7 @@ import (
"encoding/base64"
"encoding/json"
"encoding/pem"
+ "errors"
"fmt"
)
@@ -17,6 +18,8 @@ const KeyBitSize = 4096
// Приватный ключ - отдаётся серверу
// Публичный ключ - сохраняется на клиенте
+// Функции для подписи сообщений
+
func signRequest(req Request, key *rsa.PublicKey) (string, error) {
body, _ := json.Marshal(req)
based := base64.StdEncoding.EncodeToString(body)
@@ -58,3 +61,39 @@ func generateKeys() (private []byte, public []byte, err error) {
bytePublic := pem.EncodeToMemory(publicKey)
return bytePrivate, bytePublic, nil
}
+
+// Функции для проверки подписи полученных сообщений
+
+func decodeMessage(ciphertext []byte, stringKey string) ([]byte, error) {
+ block, _ := pem.Decode([]byte(stringKey))
+ if block == nil {
+ return nil, errors.New("key is not found in given string")
+ }
+
+ key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+ if err != nil {
+ return nil, err
+ }
+
+ plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, key, ciphertext)
+ if err != nil {
+ return nil, err
+ }
+ return plaintext, err
+}
+
+func checkSignature(payload string, signature string, key string) (bool, error) {
+ h := sha256.Sum256([]byte(payload))
+ requestHash := fmt.Sprintf("%x", h)
+
+ decodedSign, err := base64.StdEncoding.DecodeString(signature)
+ if err != nil {
+ return false, err
+ }
+ signHash, err := decodeMessage(decodedSign, key)
+ if err != nil {
+ return false, err
+ }
+
+ return requestHash == string(signHash), nil
+}