package shared import ( "bytes" "compress/flate" "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "encoding/binary" "fmt" "io" ) func GenerateRandomString(length int) string { b := make([]byte, length) _, err := rand.Read(b) if err != nil { panic(err) } return base64.StdEncoding.EncodeToString(b) } func CovertUintToByte32(id uint) [32]byte { b := make([]byte, 32) binary.LittleEndian.PutUint32(b, uint32(id)) return [32]byte(b) } type EncryptionClient interface { Encrypt(string) (string, error) Decrypt(string) (string, error) } type encryptionClient struct { Secret string } func NewEncryptionClient(secret string) EncryptionClient { return &encryptionClient{Secret: secret} } func compress(text string) ([]byte, error) { var compressedBytes bytes.Buffer w, err := flate.NewWriter(&compressedBytes, flate.BestCompression) w.Write([]byte(text)) w.Close() return compressedBytes.Bytes(), err } func decompress(compressedBytes []byte) (string, error) { reader := flate.NewReader(bytes.NewReader(compressedBytes)) defer reader.Close() textBytes := new(bytes.Buffer) _, err := textBytes.ReadFrom(reader) return textBytes.String(), err } // Encrypt method is to encrypt or hide any classified text func (e encryptionClient) Encrypt(text string) (string, error) { block, err := aes.NewCipher([]byte(e.Secret)) if err != nil { return "", err } compressedText, err := compress(text) if err != nil { return "", err } gcm, err := cipher.NewGCM(block) if err != nil { return "", err } bytes := make([]byte, gcm.NonceSize()) if _, err = io.ReadFull(rand.Reader, bytes); err != nil { return "", err } encodedText := gcm.Seal(bytes, bytes, compressedText, nil) return base64.StdEncoding.EncodeToString(encodedText), nil } // Decrypt method is to extract back the encrypted text func (e encryptionClient) Decrypt(text string) (string, error) { block, err := aes.NewCipher([]byte(e.Secret)) if err != nil { return "", err } cipherText, err := base64.StdEncoding.DecodeString(text) if err != nil { return "", err } gcm, err := cipher.NewGCM(block) if err != nil { return "", err } if len(cipherText) < gcm.NonceSize() { return "", fmt.Errorf("text is too small") } bytes, cipherText := cipherText[:gcm.NonceSize()], cipherText[gcm.NonceSize():] compressedTextBytes, err := gcm.Open(nil, bytes, cipherText, nil) if err != nil { return "", err } return decompress(compressedTextBytes) }