-
-
Save mickelsonm/e1bf365a149f3fe59119 to your computer and use it in GitHub Desktop.
Golang AES Encryption/Decryption example. See running example: http://play.golang.org/p/5G-IUlYqQV
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/aes" | |
"crypto/cipher" | |
"crypto/rand" | |
"encoding/base64" | |
"errors" | |
"io" | |
"log" | |
) | |
func main() { | |
CIPHER_KEY := []byte("0123456789012345") | |
msg := "A quick brown fox jumped over the lazy dog." | |
if encrypted, err := encrypt(CIPHER_KEY, msg); err != nil { | |
log.Println(err) | |
} else { | |
log.Printf("CIPHER KEY: %s\n", string(CIPHER_KEY)) | |
log.Printf("ENCRYPTED: %s\n", encrypted) | |
if decrypted, err := decrypt(CIPHER_KEY, encrypted); err != nil { | |
log.Println(err) | |
} else { | |
log.Printf("DECRYPTED: %s\n", decrypted) | |
} | |
} | |
} | |
func encrypt(key []byte, message string) (encmess string, err error) { | |
plainText := []byte(message) | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
return | |
} | |
//IV needs to be unique, but doesn't have to be secure. | |
//It's common to put it at the beginning of the ciphertext. | |
cipherText := make([]byte, aes.BlockSize+len(plainText)) | |
iv := cipherText[:aes.BlockSize] | |
if _, err = io.ReadFull(rand.Reader, iv); err != nil { | |
return | |
} | |
stream := cipher.NewCFBEncrypter(block, iv) | |
stream.XORKeyStream(cipherText[aes.BlockSize:], plainText) | |
//returns to base64 encoded string | |
encmess = base64.URLEncoding.EncodeToString(cipherText) | |
return | |
} | |
func decrypt(key []byte, securemess string) (decodedmess string, err error) { | |
cipherText, err := base64.URLEncoding.DecodeString(securemess) | |
if err != nil { | |
return | |
} | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
return | |
} | |
if len(cipherText) < aes.BlockSize { | |
err = errors.New("Ciphertext block size is too short!") | |
return | |
} | |
//IV needs to be unique, but doesn't have to be secure. | |
//It's common to put it at the beginning of the ciphertext. | |
iv := cipherText[:aes.BlockSize] | |
cipherText = cipherText[aes.BlockSize:] | |
stream := cipher.NewCFBDecrypter(block, iv) | |
// XORKeyStream can work in-place if the two arguments are the same. | |
stream.XORKeyStream(cipherText, cipherText) | |
decodedmess = string(cipherText) | |
return | |
} |
@Kiura you need calculate a hmac, and add that to the payload. This allows the receiver to validate the message is authentic. Take a look at encrypt-then-mac for high level details.
Code would look something like the following for sha512 (64 bit key)
cipherText := make([]byte, aes.BlockSize+len(plainText)+64)
// Build cipherText
// Append MAC
cipherText[len(cipherText)-64:] = plainTextMAC
// Decrypt
iv := cipherText[:aes.BlockSize]
cipherText = cipherText[aes.BlockSize:]
// Decrypt cipherText
plainText := cipherText[:len(cipherText)-64]
plainTextMAC := cipherText[len(cipherText)-64:]
// Calculate MAC from the decoded plainText
hmac.Equal(plainTextMAC, calculatedPlainTextMAC)
@timthesinner you could use something else to verify it, like a JWT library.
@timthesinner that snippet of code seems more encrypt-and-mac though, no?
I think that to do encrypt-then-mac you'd need to compute the MAC on the ciphertext+iv
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, is this secure/complete to use for production? if so what would you suggest to bear in mind to make sure it is secure.
also, which one is better this or
crypto/des
? (it is used to encrypt/decrypt plain text messages)