madipo2611 f983a2f9d9
All checks were successful
continuous-integration/drone/push Build is passing
v.0.0.4.6 Добавлено шифрование сообщения
2025-08-21 00:50:27 +03:00

132 lines
3.5 KiB
Go

package crypto
import (
"encoding/base64"
"fmt"
"log"
"strings"
"time"
"github.com/hashicorp/vault/api"
)
type VaultManager struct {
client *api.Client
}
func NewVaultManager() (*VaultManager, error) {
config := api.DefaultConfig()
config.Address = "http://192.168.0.59:8200"
client, err := api.NewClient(config)
if err != nil {
return nil, fmt.Errorf("failed to create Vault client: %v", err)
}
// Аутентификация через username/password
authData := map[string]interface{}{
"password": "2T6sDQ3PyG6x+0Z950ojAA+lWQ8HhUqd",
}
secret, err := client.Logical().Write("auth/userpass/login/tailly-app", authData)
if err != nil {
return nil, fmt.Errorf("failed to authenticate with Vault: %v", err)
}
if secret == nil || secret.Auth == nil {
return nil, fmt.Errorf("empty authentication response from Vault")
}
client.SetToken(secret.Auth.ClientToken)
// Настраиваем автоматическое обновление токена
go func() {
for {
time.Sleep(30 * time.Minute)
secret, err := client.Auth().Token().RenewSelf(0)
if err != nil {
log.Printf("Failed to renew Vault token: %v", err)
} else if secret != nil && secret.Auth != nil {
client.SetToken(secret.Auth.ClientToken)
}
}
}()
return &VaultManager{client: client}, nil
}
func (v *VaultManager) GetMasterPrivateKey() ([]byte, error) {
secret, err := v.client.Logical().Read("kv/data/keys/master")
if err != nil {
return nil, fmt.Errorf("failed to read master key: %v", err)
}
if secret == nil || secret.Data == nil {
return nil, fmt.Errorf("master key not found")
}
// Получаем данные из секрета
data, ok := secret.Data["data"].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("invalid data format in Vault secret")
}
// Получаем приватный ключ в base64
keyInterface, ok := data["private_key_base64"]
if !ok {
return nil, fmt.Errorf("private_key_base64 not found in Vault data")
}
keyBase64, ok := keyInterface.(string)
if !ok {
return nil, fmt.Errorf("private_key_base64 is not a string")
}
// Очищаем строку от лишних символов
keyBase64 = strings.TrimSpace(keyBase64)
keyBase64 = strings.ReplaceAll(keyBase64, "\n", "")
keyBase64 = strings.ReplaceAll(keyBase64, "\r", "")
keyBase64 = strings.ReplaceAll(keyBase64, " ", "")
// Декодируем base64
keyBytes, err := base64.StdEncoding.DecodeString(keyBase64)
if err != nil {
return nil, fmt.Errorf("failed to decode base64 private key: %v. Input: %s", err, keyBase64)
}
return keyBytes, nil
}
func (v *VaultManager) StoreSessionKey(chatID int, messageID int, encryptedKey []byte) error {
path := fmt.Sprintf("kv/data/keys/chat_%d/message_%d", chatID, messageID)
_, err := v.client.Logical().Write(path, map[string]interface{}{
"data": map[string]interface{}{
"encrypted_key": base64.StdEncoding.EncodeToString(encryptedKey),
"timestamp": time.Now().Unix(),
"chat_id": chatID,
"message_id": messageID,
},
})
return err
}
func (v *VaultManager) GetSessionKey(chatID int, messageID int) ([]byte, error) {
path := fmt.Sprintf("kv/data/keys/chat_%d/message_%d", chatID, messageID)
secret, err := v.client.Logical().Read(path)
if err != nil {
return nil, err
}
if secret == nil || secret.Data == nil {
return nil, fmt.Errorf("session key not found")
}
data := secret.Data["data"].(map[string]interface{})
keyBase64 := data["encrypted_key"].(string)
return base64.StdEncoding.DecodeString(keyBase64)
}