github.com/goravel/framework@v1.13.9/crypt/aes.go (about) 1 package crypt 2 3 import ( 4 "crypto/aes" 5 "crypto/cipher" 6 "crypto/rand" 7 "encoding/base64" 8 "errors" 9 "io" 10 11 "github.com/gookit/color" 12 13 "github.com/goravel/framework/contracts/config" 14 "github.com/goravel/framework/support" 15 "github.com/goravel/framework/support/json" 16 ) 17 18 type AES struct { 19 key []byte 20 } 21 22 // NewAES returns a new AES hasher. 23 func NewAES(config config.Config) *AES { 24 key := config.GetString("app.key") 25 26 // Don't use AES in artisan when the key is empty. 27 if support.Env == support.EnvArtisan && len(key) == 0 { 28 return nil 29 } 30 31 // check key length before using it 32 if len(key) != 16 && len(key) != 24 && len(key) != 32 { 33 color.Redln("[Crypt] Empty or invalid APP_KEY, please reset it.\nExample command:\ngo run . artisan key:generate") 34 return nil 35 } 36 keyBytes := []byte(key) 37 return &AES{ 38 key: keyBytes, 39 } 40 } 41 42 // EncryptString encrypts the given string, and returns the iv and ciphertext as base64 encoded strings. 43 func (b *AES) EncryptString(value string) (string, error) { 44 block, err := aes.NewCipher(b.key) 45 if err != nil { 46 return "", err 47 } 48 49 plaintext := []byte(value) 50 51 iv := make([]byte, 12) 52 if _, err = io.ReadFull(rand.Reader, iv); err != nil { 53 return "", err 54 } 55 56 aesgcm, err := cipher.NewGCM(block) 57 if err != nil { 58 return "", err 59 } 60 61 ciphertext := aesgcm.Seal(nil, iv, plaintext, nil) 62 63 var jsonEncoded []byte 64 jsonEncoded, err = json.Marshal(map[string][]byte{ 65 "iv": iv, 66 "value": ciphertext, 67 }) 68 69 if err != nil { 70 return "", err 71 } 72 73 return base64.StdEncoding.EncodeToString(jsonEncoded), nil 74 } 75 76 // DecryptString decrypts the given iv and ciphertext, and returns the plaintext. 77 func (b *AES) DecryptString(payload string) (string, error) { 78 decodePayload, err := base64.StdEncoding.DecodeString(payload) 79 if err != nil { 80 return "", err 81 } 82 83 decodeJson := make(map[string][]byte) 84 err = json.Unmarshal(decodePayload, &decodeJson) 85 if err != nil { 86 return "", err 87 } 88 89 // check if the json payload has the correct keys 90 if _, ok := decodeJson["iv"]; !ok { 91 return "", errors.New("decrypt payload error: missing iv key") 92 } 93 if _, ok := decodeJson["value"]; !ok { 94 return "", errors.New("decrypt payload error: missing value key") 95 } 96 97 decodeIv := decodeJson["iv"] 98 decodeCiphertext := decodeJson["value"] 99 100 block, err := aes.NewCipher(b.key) 101 if err != nil { 102 return "", err 103 } 104 105 aesgcm, err := cipher.NewGCM(block) 106 if err != nil { 107 return "", err 108 } 109 110 plaintext, err := aesgcm.Open(nil, decodeIv, decodeCiphertext, nil) 111 if err != nil { 112 return "", err 113 } 114 115 return string(plaintext), nil 116 }