1
1
package goeql
2
2
3
- // This package contains helpers to use with Go/Xorm to serialize/deserialize values
4
- // into the shape EQL and the CipherStash proxy needs to enable encryption/decryption.
3
+ // goeql is a collection of helpers for serializing and deserializing values
4
+ // into the shape EQL and the CipherStash Proxy needs to enable encryption and
5
+ // decryption of values, and search of those encrypted values while keeping them
6
+ // encrypted at all times.
5
7
6
8
// EQL expects a json format that looks like this:
9
+ //
7
10
// '{"k":"pt","p":"a string representation of the plaintext that is being encrypted","i":{"t":"table","c":"column"},"v":1}'
11
+ //
12
+ // More documentation on this format can be found at https://github.com/cipherstash/encrypt-query-language#data-format
8
13
9
14
import (
10
15
"encoding/json"
11
16
"fmt"
12
17
"strconv"
13
18
)
14
19
20
+ // TableColumn represents the table and column an encrypted value belongs to
15
21
type TableColumn struct {
16
22
T string `json:"t"`
17
23
C string `json:"c"`
18
24
}
19
25
26
+ // EncryptedColumn represents the plaintext value sent by a database client
20
27
type EncryptedColumn struct {
21
28
K string `json:"k"`
22
29
P string `json:"p"`
23
30
I TableColumn `json:"i"`
24
31
V int `json:"v"`
25
32
}
26
33
27
- // Creating custom types for encrypted fields to enable creating methods for
28
- // serialization/deserialization of these types.
34
+ // EncryptedText is a string value to be encrypted
29
35
type EncryptedText string
36
+
37
+ // EncryptedJsonb is a jsonb value to be encrypted
30
38
type EncryptedJsonb map [string ]interface {}
39
+
40
+ // EncryptedInt is a int value to be encrypted
31
41
type EncryptedInt int
42
+
43
+ // EncryptedBool is a bool value to be encrypted
32
44
type EncryptedBool bool
33
45
34
- // Text
46
+ // Serialize turns a EncryptedText value into a jsonb payload for CipherStash Proxy
35
47
func (et EncryptedText ) Serialize (table string , column string ) ([]byte , error ) {
36
48
val , err := ToEncryptedColumn (string (et ), table , column )
37
49
if err != nil {
@@ -40,6 +52,7 @@ func (et EncryptedText) Serialize(table string, column string) ([]byte, error) {
40
52
return json .Marshal (val )
41
53
}
42
54
55
+ // Deserialize turns a jsonb payload from CipherStash Proxy into an EncryptedText value
43
56
func (et * EncryptedText ) Deserialize (data []byte ) (EncryptedText , error ) {
44
57
var jsonData map [string ]interface {}
45
58
if err := json .Unmarshal (data , & jsonData ); err != nil {
@@ -53,7 +66,7 @@ func (et *EncryptedText) Deserialize(data []byte) (EncryptedText, error) {
53
66
return "" , fmt .Errorf ("invalid format: missing 'p' field in JSONB" )
54
67
}
55
68
56
- // Jsonb
69
+ // Serialize turns a EncryptedJsonb value into a jsonb payload for CipherStash Proxy
57
70
func (ej EncryptedJsonb ) Serialize (table string , column string ) ([]byte , error ) {
58
71
val , err := ToEncryptedColumn (map [string ]any (ej ), table , column )
59
72
if err != nil {
@@ -62,6 +75,7 @@ func (ej EncryptedJsonb) Serialize(table string, column string) ([]byte, error)
62
75
return json .Marshal (val )
63
76
}
64
77
78
+ // Deserialize turns a jsonb payload from CipherStash Proxy into an EncryptedJsonb value
65
79
func (ej * EncryptedJsonb ) Deserialize (data []byte ) (EncryptedJsonb , error ) {
66
80
var jsonData map [string ]interface {}
67
81
if err := json .Unmarshal (data , & jsonData ); err != nil {
@@ -80,7 +94,7 @@ func (ej *EncryptedJsonb) Deserialize(data []byte) (EncryptedJsonb, error) {
80
94
return nil , fmt .Errorf ("invalid format: missing 'p' field in JSONB" )
81
95
}
82
96
83
- // Int
97
+ // Serialize turns a EncryptedInt value into a jsonb payload for CipherStash Proxy
84
98
func (et EncryptedInt ) Serialize (table string , column string ) ([]byte , error ) {
85
99
val , err := ToEncryptedColumn (int (et ), table , column )
86
100
if err != nil {
@@ -89,6 +103,7 @@ func (et EncryptedInt) Serialize(table string, column string) ([]byte, error) {
89
103
return json .Marshal (val )
90
104
}
91
105
106
+ // Deserialize turns a jsonb payload from CipherStash Proxy into an EncryptedInt value
92
107
func (et * EncryptedInt ) Deserialize (data []byte ) (EncryptedInt , error ) {
93
108
var jsonData map [string ]interface {}
94
109
if err := json .Unmarshal (data , & jsonData ); err != nil {
@@ -106,7 +121,7 @@ func (et *EncryptedInt) Deserialize(data []byte) (EncryptedInt, error) {
106
121
return 0 , fmt .Errorf ("invalid format: missing 'p' field" )
107
122
}
108
123
109
- // Bool
124
+ // Serialize turns a EncryptedBool value into a jsonb payload for CipherStash Proxy
110
125
func (eb EncryptedBool ) Serialize (table string , column string ) ([]byte , error ) {
111
126
val , err := ToEncryptedColumn (bool (eb ), table , column )
112
127
if err != nil {
@@ -115,7 +130,8 @@ func (eb EncryptedBool) Serialize(table string, column string) ([]byte, error) {
115
130
return json .Marshal (val )
116
131
}
117
132
118
- func (et * EncryptedBool ) Deserialize (data []byte ) (EncryptedBool , error ) {
133
+ // Deserialize turns a jsonb payload from CipherStash Proxy into an EncryptedBool value
134
+ func (eb * EncryptedBool ) Deserialize (data []byte ) (EncryptedBool , error ) {
119
135
var jsonData map [string ]interface {}
120
136
if err := json .Unmarshal (data , & jsonData ); err != nil {
121
137
// TODO: Check the best return values for these.
@@ -133,8 +149,7 @@ func (et *EncryptedBool) Deserialize(data []byte) (EncryptedBool, error) {
133
149
return false , fmt .Errorf ("invalid format: missing 'p' field" )
134
150
}
135
151
136
- // Serialize a query
137
-
152
+ // SerializeQuery produces a jsonb payload used by EQL query functions to perform search operations like equality checks, range queries, and unique constraints.
138
153
func SerializeQuery (value any , table string , column string ) ([]byte , error ) {
139
154
query , err := ToEncryptedColumn (value , table , column )
140
155
if err != nil {
@@ -149,7 +164,7 @@ func SerializeQuery(value any, table string, column string) ([]byte, error) {
149
164
150
165
}
151
166
152
- // Converts a plaintext value to a string and returns the EncryptedColumn struct to use to insert into the db .
167
+ // ToEncryptedColumn converts a plaintext value to a string, and returns the EncryptedColumn struct for inserting into a database .
153
168
func ToEncryptedColumn (value any , table string , column string ) (EncryptedColumn , error ) {
154
169
str , err := convertToString (value )
155
170
if err != nil {
0 commit comments