diff --git a/README.md b/README.md new file mode 100644 index 0000000..1eb04e0 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +### Link to the original source: [Advanced encryption and decryption](https://astaxie.gitbooks.io/build-web-application-with-golang/content/en/09.6.html) diff --git a/main.go b/main.go new file mode 100644 index 0000000..b8d04e2 --- /dev/null +++ b/main.go @@ -0,0 +1,70 @@ +package aes + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "errors" + "io" + mrand "math/rand" + "time" +) + +const ( + keySize = 32 + allowedRunes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +) + +// RandomKey returns a randomly generated 32 bytes long hex encoded key. +func RandomKey() (key []byte) { + mrand.Seed(time.Now().UnixNano()) + + key = make([]byte, keySize) + + for i := range key { + key[i] = allowedRunes[mrand.Intn(len(allowedRunes))] + } + + return key +} + +// Encrypt encrypts plaintext with key and returns resulting bytes. +func Encrypt(plaintext []byte, key []byte) ([]byte, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + gcm, err := cipher.NewGCM(c) + if err != nil { + return nil, err + } + + nonce := make([]byte, gcm.NonceSize()) + if _, err = io.ReadFull(rand.Reader, nonce); err != nil { + return nil, err + } + + return gcm.Seal(nonce, nonce, plaintext, nil), nil +} + +// Decrypt decrypts ciphertext with key and returns resulting bytes. +func Decrypt(ciphertext []byte, key []byte) ([]byte, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + gcm, err := cipher.NewGCM(c) + if err != nil { + return nil, err + } + + nonceSize := gcm.NonceSize() + if len(ciphertext) < nonceSize { + return nil, errors.New("ciphertext too short") + } + + nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:] + return gcm.Open(nil, nonce, ciphertext, nil) +}