github.com/s7techlab/cckit@v0.10.5/extensions/encryption/state.go (about) 1 package encryption 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 7 "github.com/pkg/errors" 8 9 "github.com/s7techlab/cckit/convert" 10 "github.com/s7techlab/cckit/router" 11 "github.com/s7techlab/cckit/state" 12 ) 13 14 var ( 15 // ErrKeyNotDefinedInTransientMap occurs when key not defined in transient map 16 ErrKeyNotDefinedInTransientMap = errors.New(`encryption key is not defined in transient map`) 17 ) 18 19 // State wrapper, encrypts the data before putting to state and 20 // decrypts the data after getting from state 21 func State(c router.Context, key []byte) (state.State, error) { 22 //current state 23 s := c.State() 24 25 s.UseKeyTransformer(KeyEncryptor(key)) 26 s.UseKeyReverseTransformer(KeyDecryptor(key)) 27 s.UseStateGetTransformer(FromBytesDecryptor(key)) 28 s.UseStatePutTransformer(ToBytesEncryptor(key)) 29 30 return s, nil 31 } 32 33 // KeyFromTransient gets key for encrypting/decrypting from transient map 34 func KeyFromTransient(c router.Context) ([]byte, error) { 35 tm, err := c.Stub().GetTransient() 36 if err != nil { 37 return nil, err 38 } 39 40 key, ok := tm[TransientMapKey] 41 if !ok { 42 return nil, ErrKeyNotDefinedInTransientMap 43 } 44 45 return key, nil 46 } 47 48 // StateWithTransientKey creates encrypted state state with provided key for symmetric encryption/decryption 49 func StateWithTransientKey(c router.Context) (state.State, error) { 50 key, err := KeyFromTransient(c) 51 if err != nil { 52 return nil, err 53 } 54 return State(c, key) 55 } 56 57 // StateWithTransientKeyIfProvided creates encrypted state wrapper with provided key for symmetric encryption/decryption 58 // if key provided, otherwise - standard state wrapper without encryption 59 func StateWithTransientKeyIfProvided(c router.Context) (state.State, error) { 60 key, err := KeyFromTransient(c) 61 switch err { 62 case nil: 63 return State(c, key) 64 case ErrKeyNotDefinedInTransientMap: 65 //default state wrapper without encryption 66 return c.State(), nil 67 } 68 return nil, err 69 } 70 71 // KeyEncryptor encrypts state key 72 func KeyEncryptor(encryptKey []byte) state.KeyTransformer { 73 return func(key state.Key) (state.Key, error) { 74 keyEnc := make(state.Key, len(key)) 75 76 for i, p := range key { 77 keyPartEnc, err := Encrypt(encryptKey, p) 78 if err != nil { 79 return nil, fmt.Errorf(`encrypt key: %w`, err) 80 } 81 keyEnc[i] = base64.StdEncoding.EncodeToString(keyPartEnc) 82 } 83 return keyEnc, nil 84 } 85 } 86 87 // KeyDecryptor decrypts state key 88 func KeyDecryptor(encryptKey []byte) state.KeyTransformer { 89 return func(key state.Key) (state.Key, error) { 90 keyEnc := make(state.Key, len(key)) 91 92 for i, p := range key { 93 keyPartEnc, err := base64.StdEncoding.DecodeString(p) 94 if err != nil { 95 return nil, fmt.Errorf(`decrypt key base4 decode: %w`, err) 96 } 97 keyPart, err := Decrypt(encryptKey, keyPartEnc) 98 if err != nil { 99 return nil, fmt.Errorf(`decrypt key: %w`, err) 100 } 101 keyEnc[i] = string(keyPart) 102 } 103 return keyEnc, nil 104 } 105 } 106 107 // FromBytesDecryptor returns state.FromBytesTransformer - used for decrypting data after reading from state 108 func FromBytesDecryptor(key []byte) state.FromBytesTransformer { 109 return func(bb []byte, config ...interface{}) (interface{}, error) { 110 decrypted, err := Decrypt(key, bb) 111 if err != nil { 112 return nil, errors.Wrap(err, `decrypt bytes`) 113 } 114 if len(config) == 0 { 115 return decrypted, nil 116 } 117 return convert.FromBytes(decrypted, config[0]) 118 } 119 } 120 121 // ToBytesEncryptor returns state.ToBytesTransformer - used for encrypting data for state 122 func ToBytesEncryptor(key []byte) state.ToBytesTransformer { 123 return func(v interface{}, config ...interface{}) ([]byte, error) { 124 bb, err := convert.ToBytes(v) 125 if err != nil { 126 return nil, err 127 } 128 return Encrypt(key, bb) 129 } 130 } 131 132 // EncryptWithTransientKey encrypts val with key from transient map 133 func EncryptWithTransientKey(c router.Context, val interface{}) (encrypted []byte, err error) { 134 var ( 135 key []byte 136 ) 137 138 if key, err = KeyFromTransient(c); err != nil { 139 return 140 } 141 142 return ToBytesEncryptor(key)(val) 143 }