package crypt import ( "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/sha256" "fmt" "log" "golang.org/x/crypto/pbkdf2" ) // New generates a new key based on a passphrase and salt func New(passphrase []byte, usersalt []byte) (key []byte, salt []byte, err error) { if len(passphrase) < 1 { err = fmt.Errorf("need more than that for passphrase") return } if usersalt == nil { salt = make([]byte, 8) // http://www.ietf.org/rfc/rfc2898.txt // Salt. if _, err := rand.Read(salt); err != nil { log.Fatalf("can't get random salt: %v", err) } } else { salt = usersalt } key = pbkdf2.Key(passphrase, salt, 100, 32, sha256.New) return } // Encrypt will encrypt using the pre-generated key func Encrypt(plaintext []byte, key []byte) (encrypted []byte, err error) { // generate a random iv each time // http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf // Section 8.2 ivBytes := make([]byte, 12) if _, err := rand.Read(ivBytes); err != nil { log.Fatalf("can't initialize crypto: %v", err) } b, err := aes.NewCipher(key) if err != nil { return } aesgcm, err := cipher.NewGCM(b) if err != nil { return } encrypted = aesgcm.Seal(nil, ivBytes, plaintext, nil) encrypted = append(ivBytes, encrypted...) return } // Decrypt using the pre-generated key func Decrypt(encrypted []byte, key []byte) (plaintext []byte, err error) { if len(encrypted) < 13 { err = fmt.Errorf("incorrect passphrase") return } b, err := aes.NewCipher(key) if err != nil { return } aesgcm, err := cipher.NewGCM(b) if err != nil { return } plaintext, err = aesgcm.Open(nil, encrypted[:12], encrypted[12:], nil) return }