113 lines
2.7 KiB
Go
113 lines
2.7 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"encoding/base64"
|
|
"io"
|
|
)
|
|
|
|
type CryptoService struct {
|
|
privateKey *rsa.PrivateKey
|
|
Vault *VaultManager
|
|
}
|
|
|
|
func NewCryptoService() (*CryptoService, error) {
|
|
vault, err := NewVaultManager()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Загрузка приватного ключа из Vault
|
|
keyBytes, err := vault.GetMasterPrivateKey()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
privateKey, err := x509.ParsePKCS1PrivateKey(keyBytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &CryptoService{
|
|
privateKey: privateKey,
|
|
Vault: vault,
|
|
}, nil
|
|
}
|
|
|
|
// Шифрование сообщения - возвращает зашифрованный контент, ключ и nonce
|
|
func (cs *CryptoService) EncryptMessage(content string) ([]byte, []byte, []byte, error) {
|
|
// Генерация сессионного AES ключа
|
|
aesKey := make([]byte, 32)
|
|
if _, err := rand.Read(aesKey); err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
// Шифрование сообщения AES-GCM
|
|
block, err := aes.NewCipher(aesKey)
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
gcm, err := cipher.NewGCM(block)
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
nonce := make([]byte, gcm.NonceSize())
|
|
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
encryptedContent := gcm.Seal(nil, nonce, []byte(content), nil)
|
|
|
|
// Шифрование AES ключа RSA-OAEP
|
|
encryptedKey, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, &cs.privateKey.PublicKey, aesKey, nil)
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
return encryptedContent, encryptedKey, nonce, nil
|
|
}
|
|
|
|
// Расшифровка сообщения
|
|
func (cs *CryptoService) DecryptMessage(encryptedContent, encryptedKey, nonce []byte) (string, error) {
|
|
// Расшифровка AES ключа
|
|
aesKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, cs.privateKey, encryptedKey, nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Расшифровка сообщения
|
|
block, err := aes.NewCipher(aesKey)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
gcm, err := cipher.NewGCM(block)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
plaintext, err := gcm.Open(nil, nonce, encryptedContent, nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(plaintext), nil
|
|
}
|
|
|
|
// Утилитарная функция для base64 кодирования (для хранения в Vault)
|
|
func (cs *CryptoService) EncodeBase64(data []byte) string {
|
|
return base64.StdEncoding.EncodeToString(data)
|
|
}
|
|
|
|
// Утилитарная функция для base64 декодирования
|
|
func (cs *CryptoService) DecodeBase64(data string) ([]byte, error) {
|
|
return base64.StdEncoding.DecodeString(data)
|
|
}
|