11package goeql
22
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.
57
68// EQL expects a json format that looks like this:
9+ //
710// '{"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
813
914import (
1015 "encoding/json"
1116 "fmt"
1217 "strconv"
1318)
1419
20+ // TableColumn represents the table and column an encrypted value belongs to
1521type TableColumn struct {
1622 T string `json:"t"`
1723 C string `json:"c"`
1824}
1925
26+ // EncryptedColumn represents the plaintext value sent by a database client
2027type EncryptedColumn struct {
2128 K string `json:"k"`
2229 P string `json:"p"`
2330 I TableColumn `json:"i"`
2431 V int `json:"v"`
2532}
2633
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
2935type EncryptedText string
36+
37+ // EncryptedJsonb is a jsonb value to be encrypted
3038type EncryptedJsonb map [string ]interface {}
39+
40+ // EncryptedInt is a int value to be encrypted
3141type EncryptedInt int
42+
43+ // EncryptedBool is a bool value to be encrypted
3244type EncryptedBool bool
3345
34- // Text
46+ // Serialize turns a EncryptedText value into a jsonb payload for CipherStash Proxy
3547func (et EncryptedText ) Serialize (table string , column string ) ([]byte , error ) {
3648 val , err := ToEncryptedColumn (string (et ), table , column )
3749 if err != nil {
@@ -40,6 +52,7 @@ func (et EncryptedText) Serialize(table string, column string) ([]byte, error) {
4052 return json .Marshal (val )
4153}
4254
55+ // Deserialize turns a jsonb payload from CipherStash Proxy into an EncryptedText value
4356func (et * EncryptedText ) Deserialize (data []byte ) (EncryptedText , error ) {
4457 var jsonData map [string ]interface {}
4558 if err := json .Unmarshal (data , & jsonData ); err != nil {
@@ -53,7 +66,7 @@ func (et *EncryptedText) Deserialize(data []byte) (EncryptedText, error) {
5366 return "" , fmt .Errorf ("invalid format: missing 'p' field in JSONB" )
5467}
5568
56- // Jsonb
69+ // Serialize turns a EncryptedJsonb value into a jsonb payload for CipherStash Proxy
5770func (ej EncryptedJsonb ) Serialize (table string , column string ) ([]byte , error ) {
5871 val , err := ToEncryptedColumn (map [string ]any (ej ), table , column )
5972 if err != nil {
@@ -62,6 +75,7 @@ func (ej EncryptedJsonb) Serialize(table string, column string) ([]byte, error)
6275 return json .Marshal (val )
6376}
6477
78+ // Deserialize turns a jsonb payload from CipherStash Proxy into an EncryptedJsonb value
6579func (ej * EncryptedJsonb ) Deserialize (data []byte ) (EncryptedJsonb , error ) {
6680 var jsonData map [string ]interface {}
6781 if err := json .Unmarshal (data , & jsonData ); err != nil {
@@ -80,7 +94,7 @@ func (ej *EncryptedJsonb) Deserialize(data []byte) (EncryptedJsonb, error) {
8094 return nil , fmt .Errorf ("invalid format: missing 'p' field in JSONB" )
8195}
8296
83- // Int
97+ // Serialize turns a EncryptedInt value into a jsonb payload for CipherStash Proxy
8498func (et EncryptedInt ) Serialize (table string , column string ) ([]byte , error ) {
8599 val , err := ToEncryptedColumn (int (et ), table , column )
86100 if err != nil {
@@ -89,6 +103,7 @@ func (et EncryptedInt) Serialize(table string, column string) ([]byte, error) {
89103 return json .Marshal (val )
90104}
91105
106+ // Deserialize turns a jsonb payload from CipherStash Proxy into an EncryptedInt value
92107func (et * EncryptedInt ) Deserialize (data []byte ) (EncryptedInt , error ) {
93108 var jsonData map [string ]interface {}
94109 if err := json .Unmarshal (data , & jsonData ); err != nil {
@@ -106,7 +121,7 @@ func (et *EncryptedInt) Deserialize(data []byte) (EncryptedInt, error) {
106121 return 0 , fmt .Errorf ("invalid format: missing 'p' field" )
107122}
108123
109- // Bool
124+ // Serialize turns a EncryptedBool value into a jsonb payload for CipherStash Proxy
110125func (eb EncryptedBool ) Serialize (table string , column string ) ([]byte , error ) {
111126 val , err := ToEncryptedColumn (bool (eb ), table , column )
112127 if err != nil {
@@ -115,7 +130,8 @@ func (eb EncryptedBool) Serialize(table string, column string) ([]byte, error) {
115130 return json .Marshal (val )
116131}
117132
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 ) {
119135 var jsonData map [string ]interface {}
120136 if err := json .Unmarshal (data , & jsonData ); err != nil {
121137 // TODO: Check the best return values for these.
@@ -133,8 +149,7 @@ func (et *EncryptedBool) Deserialize(data []byte) (EncryptedBool, error) {
133149 return false , fmt .Errorf ("invalid format: missing 'p' field" )
134150}
135151
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.
138153func SerializeQuery (value any , table string , column string ) ([]byte , error ) {
139154 query , err := ToEncryptedColumn (value , table , column )
140155 if err != nil {
@@ -149,7 +164,7 @@ func SerializeQuery(value any, table string, column string) ([]byte, error) {
149164
150165}
151166
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 .
153168func ToEncryptedColumn (value any , table string , column string ) (EncryptedColumn , error ) {
154169 str , err := convertToString (value )
155170 if err != nil {
0 commit comments