aes.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package crypto
  2. import (
  3. "context"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "crypto/rand"
  7. "encoding/base64"
  8. "encoding/json"
  9. "io"
  10. "reflect"
  11. "github.com/0xJacky/Nginx-UI/settings"
  12. "gorm.io/gorm/schema"
  13. )
  14. // AesEncrypt encrypts text and given key with AES.
  15. func AesEncrypt(text []byte) ([]byte, error) {
  16. if len(text) == 0 {
  17. return nil, ErrPlainTextEmpty
  18. }
  19. block, err := aes.NewCipher(settings.CryptoSettings.GetSecretMd5())
  20. if err != nil {
  21. return nil, err
  22. }
  23. b := base64.StdEncoding.EncodeToString(text)
  24. ciphertext := make([]byte, aes.BlockSize+len(b))
  25. iv := ciphertext[:aes.BlockSize]
  26. if _, err = io.ReadFull(rand.Reader, iv); err != nil {
  27. return nil, err
  28. }
  29. cfb := cipher.NewCFBEncrypter(block, iv)
  30. cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
  31. return ciphertext, nil
  32. }
  33. // AesDecrypt decrypts text and given key with AES.
  34. func AesDecrypt(text []byte) ([]byte, error) {
  35. block, err := aes.NewCipher(settings.CryptoSettings.GetSecretMd5())
  36. if err != nil {
  37. return nil, err
  38. }
  39. if len(text) < aes.BlockSize {
  40. return nil, ErrCipherTextTooShort
  41. }
  42. iv := text[:aes.BlockSize]
  43. text = text[aes.BlockSize:]
  44. cfb := cipher.NewCFBDecrypter(block, iv)
  45. cfb.XORKeyStream(text, text)
  46. data, err := base64.StdEncoding.DecodeString(string(text))
  47. if err != nil {
  48. return nil, err
  49. }
  50. return data, nil
  51. }
  52. type JSONAesSerializer struct{}
  53. func (JSONAesSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) (err error) {
  54. fieldValue := reflect.New(field.FieldType)
  55. if dbValue != nil {
  56. var bytes []byte
  57. switch v := dbValue.(type) {
  58. case []byte:
  59. bytes = v
  60. case string:
  61. bytes = []byte(v)
  62. default:
  63. bytes, err = json.Marshal(v)
  64. if err != nil {
  65. return err
  66. }
  67. }
  68. if len(bytes) > 0 {
  69. bytes, err = AesDecrypt(bytes)
  70. if err != nil {
  71. return err
  72. }
  73. err = json.Unmarshal(bytes, fieldValue.Interface())
  74. }
  75. }
  76. field.ReflectValueOf(ctx, dst).Set(fieldValue.Elem())
  77. return
  78. }
  79. // Value implements serializer interface
  80. func (JSONAesSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
  81. result, err := json.Marshal(fieldValue)
  82. if string(result) == "null" {
  83. if field.TagSettings["NOT NULL"] != "" {
  84. return "", nil
  85. }
  86. return nil, err
  87. }
  88. encrypt, err := AesEncrypt(result)
  89. return string(encrypt), err
  90. }