package cryptojs import ( "crypto/aes" "crypto/cipher" "crypto/md5" "encoding/base64" "errors" "math/rand" "bytes" "paste.ee/go/evpkdf" ) const ( keySize = 32 ) func Encrypt(data, passphrase string) (string, error) { salt := make([]byte, 8) if _, err := rand.Read(salt); err != nil { return "", err } key := make([]byte, keySize) iv := make([]byte, aes.BlockSize) keymat := evpkdf.New(md5.New, []byte(passphrase), salt, keySize + aes.BlockSize, 1) keymatbuf := bytes.NewReader(keymat) n, err := keymatbuf.Read(key) if n != keySize || err != nil { return "", err } n, err = keymatbuf.Read(iv) if n != aes.BlockSize || err != nil { return "", err } block, err := aes.NewCipher(key) if err != nil { return "", err } padded, err := pkcs7Pad([]byte(data), block.BlockSize()) if err != nil { return "", err } ciphertext := make([]byte, len(padded)) cbc := cipher.NewCBCEncrypter(block, iv) cbc.CryptBlocks(ciphertext, padded) return encode(ciphertext, salt), nil } func Decrypt(b64, passphrase string) ([]byte, error) { salt, ct, err := decode(b64) if err != nil { return nil, err } key := make([]byte, keySize) iv := make([]byte, aes.BlockSize) keymat := evpkdf.New(md5.New, []byte(passphrase), salt, keySize + aes.BlockSize, 1) keymatbuf := bytes.NewReader(keymat) n, err := keymatbuf.Read(key) if n != keySize || err != nil { return nil, err } n, err = keymatbuf.Read(iv) if n != aes.BlockSize || err != nil { return nil, err } block, err := aes.NewCipher(key) if err != nil { return nil, err } cbc := cipher.NewCBCDecrypter(block, iv) cbc.CryptBlocks(ct, ct) plain, err := pkcs7Unpad(ct, block.BlockSize()) if err != nil { return nil, err } return plain, nil } func encode(ct []byte, salt []byte) string { b := []byte("Salted__") b = append(b, salt...) b = append(b, ct...) return base64.StdEncoding.EncodeToString(b) } func decode(b64 string) ([]byte, []byte, error) { decoded, err := base64.StdEncoding.DecodeString(b64) if err != nil { return nil, nil, err } if string(decoded[0:8]) != "Salted__" { return nil, nil, errors.New("invalid data") } return decoded[8:16], decoded[16:], nil }