/* To double check aes.js, I wrote the same thing in go. Because of standards, we should be able to encrypt in js and decrypt in go. Seems to work fine, with some odd padding. */ package main import ( "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/sha256" "encoding/hex" "fmt" "strings" "golang.org/x/crypto/pbkdf2" ) func deriveKey(passphrase string, salt []byte) ([]byte, []byte) { if salt == nil { salt = make([]byte, 16) rand.Read(salt) } return pbkdf2.Key([]byte(passphrase), salt, 1000, 32, sha256.New), salt } func decrypt(passphrase, ciphertext string) string { arr := strings.Split(ciphertext, "-") salt, _ := hex.DecodeString(arr[0]) iv, _ := hex.DecodeString(arr[1]) data, _ := hex.DecodeString(arr[2]) key, _ := deriveKey(passphrase, salt) b, _ := aes.NewCipher(key) mode := cipher.NewCBCDecrypter(b, iv) mode.CryptBlocks(data, data) return string(data) } func encrypt(passphrase, plaintext string) string { key, salt := deriveKey(passphrase, nil) b, _ := aes.NewCipher(key) iv := make([]byte, 16) rand.Read(iv) mode := cipher.NewCBCEncrypter(b, iv) data := []byte(plaintext) for len(data)%16 != 0 { data = append(data, 11) // I don't know why, but it seems that using web crypto you get extra 11's } mode.CryptBlocks(data, data) return hex.EncodeToString(salt) + "-" + hex.EncodeToString(iv) + "-" + hex.EncodeToString(data) } func main() { passphrase := "world" ciphertext := "de8d8b4d845c12b3085059d652403735-8e86a6ca52f4c44c744a3a0bee0c2d7d-778f133498a21f1b7aeb7c6f2e82bfd5" plaintext := decrypt(passphrase, ciphertext) fmt.Println([]byte(plaintext)) plaintext = "hello" ciphertext = encrypt(passphrase, plaintext) fmt.Println(ciphertext) fmt.Println(decrypt(passphrase, ciphertext)) }