encryption.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package util
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "crypto/rand"
  6. "crypto/sha256"
  7. "io"
  8. "github.com/grafana/grafana/pkg/log"
  9. )
  10. const saltLength = 8
  11. func Decrypt(payload []byte, secret string) []byte {
  12. salt := payload[:saltLength]
  13. key := encryptionKeyToBytes(secret, string(salt))
  14. block, err := aes.NewCipher(key)
  15. if err != nil {
  16. log.Fatal(4, err.Error())
  17. }
  18. // The IV needs to be unique, but not secure. Therefore it's common to
  19. // include it at the beginning of the ciphertext.
  20. if len(payload) < aes.BlockSize {
  21. log.Fatal(4, "payload too short")
  22. }
  23. iv := payload[saltLength : saltLength+aes.BlockSize]
  24. payload = payload[saltLength+aes.BlockSize:]
  25. stream := cipher.NewCFBDecrypter(block, iv)
  26. // XORKeyStream can work in-place if the two arguments are the same.
  27. stream.XORKeyStream(payload, payload)
  28. return payload
  29. }
  30. func Encrypt(payload []byte, secret string) []byte {
  31. salt := GetRandomString(saltLength)
  32. key := encryptionKeyToBytes(secret, salt)
  33. block, err := aes.NewCipher(key)
  34. if err != nil {
  35. log.Fatal(4, err.Error())
  36. }
  37. // The IV needs to be unique, but not secure. Therefore it's common to
  38. // include it at the beginning of the ciphertext.
  39. ciphertext := make([]byte, saltLength+aes.BlockSize+len(payload))
  40. copy(ciphertext[:saltLength], []byte(salt))
  41. iv := ciphertext[saltLength : saltLength+aes.BlockSize]
  42. if _, err := io.ReadFull(rand.Reader, iv); err != nil {
  43. log.Fatal(4, err.Error())
  44. }
  45. stream := cipher.NewCFBEncrypter(block, iv)
  46. stream.XORKeyStream(ciphertext[saltLength+aes.BlockSize:], payload)
  47. return ciphertext
  48. }
  49. // Key needs to be 32bytes
  50. func encryptionKeyToBytes(secret, salt string) []byte {
  51. return PBKDF2([]byte(secret), []byte(salt), 10000, 32, sha256.New)
  52. }