package aeshelper import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/md5" "crypto/rand" "encoding/base64" "io" ) // Encrypt text with the passphrase func Encrypt(text string, passphrase string) string { salt := make([]byte, 8) if _, err := io.ReadFull(rand.Reader, salt); err != nil { panic(err.Error()) } key, iv := DeriveKeyAndIv(passphrase, string(salt)) block, err := aes.NewCipher([]byte(key)) if err != nil { panic(err) } pad := PKCS7Padding([]byte(text), block.BlockSize()) ecb := cipher.NewCBCEncrypter(block, []byte(iv)) encrypted := make([]byte, len(pad)) ecb.CryptBlocks(encrypted, pad) return base64.StdEncoding.EncodeToString([]byte("Salted__" + string(salt) + string(encrypted))) } // Decrypt encrypted text with the passphrase func Decrypt(encrypted string, passphrase string) string { ct, _ := base64.StdEncoding.DecodeString(encrypted) if len(ct) < 16 || string(ct[:8]) != "Salted__" { return "" } salt := ct[8:16] ct = ct[16:] key, iv := DeriveKeyAndIv(passphrase, string(salt)) block, err := aes.NewCipher([]byte(key)) if err != nil { panic(err) } cbc := cipher.NewCBCDecrypter(block, []byte(iv)) dst := make([]byte, len(ct)) cbc.CryptBlocks(dst, ct) return string(PKCS7Trimming(dst)) } // PKCS7Padding PKCS7Padding func PKCS7Padding(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext)%blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padtext...) } // PKCS7Trimming PKCS7Trimming func PKCS7Trimming(encrypt []byte) []byte { padding := encrypt[len(encrypt)-1] return encrypt[:len(encrypt)-int(padding)] } // DeriveKeyAndIv DeriveKeyAndIv func DeriveKeyAndIv(passphrase string, salt string) (string, string) { salted := "" dI := "" for len(salted) < 48 { md := md5.New() md.Write([]byte(dI + passphrase + salt)) dM := md.Sum(nil) dI = string(dM[:16]) salted = salted + dI } key := salted[0:32] iv := salted[32:48] return key, iv }