...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package encryption
18
19 import (
20 "io"
21
22 "github.com/apache/arrow/go/v15/arrow/memory"
23 "github.com/apache/arrow/go/v15/parquet"
24 )
25
26
27
28 type FileEncryptor interface {
29
30 GetFooterEncryptor() Encryptor
31
32
33 GetFooterSigningEncryptor() Encryptor
34
35
36 GetColumnMetaEncryptor(columnPath string) Encryptor
37
38
39 GetColumnDataEncryptor(columnPath string) Encryptor
40
41
42
43 WipeOutEncryptionKeys()
44 }
45
46 type fileEncryptor struct {
47 props *parquet.FileEncryptionProperties
48 columnDataMap map[string]Encryptor
49 columnMetaDataMap map[string]Encryptor
50 footerSigningEncryptor Encryptor
51 footerEncryptor Encryptor
52
53
54
55 metaEncryptor *aesEncryptor
56 dataEncryptor *aesEncryptor
57
58 mem memory.Allocator
59 }
60
61
62
63
64
65 func NewFileEncryptor(props *parquet.FileEncryptionProperties, mem memory.Allocator) FileEncryptor {
66 if props.IsUtilized() {
67 panic("re-using encryption properties for another file")
68 }
69
70 props.SetUtilized()
71 if mem == nil {
72 mem = memory.DefaultAllocator
73 }
74
75 return &fileEncryptor{
76 props: props,
77 mem: mem,
78 columnDataMap: make(map[string]Encryptor),
79 columnMetaDataMap: make(map[string]Encryptor),
80 }
81 }
82
83 func (e *fileEncryptor) WipeOutEncryptionKeys() {
84 e.props.WipeOutEncryptionKeys()
85 }
86
87 func (e *fileEncryptor) GetFooterEncryptor() Encryptor {
88 if e.footerEncryptor == nil {
89 alg := e.props.Algorithm().Algo
90 footerAad := CreateFooterAad(e.props.FileAad())
91 footerKey := e.props.FooterKey()
92 enc := e.getMetaAesEncryptor(alg)
93 e.footerEncryptor = &encryptor{
94 aesEncryptor: enc,
95 key: []byte(footerKey),
96 fileAad: e.props.FileAad(),
97 aad: footerAad,
98 mem: e.mem,
99 }
100 }
101 return e.footerEncryptor
102 }
103
104 func (e *fileEncryptor) GetFooterSigningEncryptor() Encryptor {
105 if e.footerSigningEncryptor == nil {
106 alg := e.props.Algorithm().Algo
107 footerAad := CreateFooterAad(e.props.FileAad())
108 footerKey := e.props.FooterKey()
109 enc := e.getMetaAesEncryptor(alg)
110 e.footerSigningEncryptor = &encryptor{
111 aesEncryptor: enc,
112 key: []byte(footerKey),
113 fileAad: e.props.FileAad(),
114 aad: footerAad,
115 mem: e.mem,
116 }
117 }
118 return e.footerSigningEncryptor
119 }
120
121 func (e *fileEncryptor) getMetaAesEncryptor(alg parquet.Cipher) *aesEncryptor {
122 if e.metaEncryptor == nil {
123 e.metaEncryptor = NewAesEncryptor(alg, true)
124 }
125 return e.metaEncryptor
126 }
127
128 func (e *fileEncryptor) getDataAesEncryptor(alg parquet.Cipher) *aesEncryptor {
129 if e.dataEncryptor == nil {
130 e.dataEncryptor = NewAesEncryptor(alg, false)
131 }
132 return e.dataEncryptor
133 }
134
135 func (e *fileEncryptor) GetColumnMetaEncryptor(columnPath string) Encryptor {
136 return e.getColumnEncryptor(columnPath, true)
137 }
138
139 func (e *fileEncryptor) GetColumnDataEncryptor(columnPath string) Encryptor {
140 return e.getColumnEncryptor(columnPath, false)
141 }
142
143 func (e *fileEncryptor) getColumnEncryptor(columnPath string, metadata bool) Encryptor {
144 if metadata {
145 if enc, ok := e.columnMetaDataMap[columnPath]; ok {
146 return enc
147 }
148 } else {
149 if enc, ok := e.columnDataMap[columnPath]; ok {
150 return enc
151 }
152 }
153
154 columnProp := e.props.ColumnEncryptionProperties(columnPath)
155 if columnProp == nil {
156 return nil
157 }
158
159 var key string
160 if columnProp.IsEncryptedWithFooterKey() {
161 key = e.props.FooterKey()
162 } else {
163 key = columnProp.Key()
164 }
165
166 alg := e.props.Algorithm().Algo
167 var enc *aesEncryptor
168 if metadata {
169 enc = e.getMetaAesEncryptor(alg)
170 } else {
171 enc = e.getDataAesEncryptor(alg)
172 }
173
174 fileAad := e.props.FileAad()
175 ret := &encryptor{
176 aesEncryptor: enc,
177 key: []byte(key),
178 fileAad: fileAad,
179 aad: "",
180 mem: e.mem,
181 }
182 if metadata {
183 e.columnMetaDataMap[columnPath] = ret
184 } else {
185 e.columnDataMap[columnPath] = ret
186 }
187 return ret
188 }
189
190
191
192
193 type Encryptor interface {
194
195 FileAad() string
196
197 UpdateAad(string)
198
199 Allocator() memory.Allocator
200
201
202 CiphertextSizeDelta() int
203
204
205 Encrypt(w io.Writer, src []byte) int
206
207
208 EncryptColumnMetaData(encryptFooter bool, properties *parquet.ColumnEncryptionProperties) bool
209 }
210
211 type encryptor struct {
212 aesEncryptor *aesEncryptor
213 key []byte
214 fileAad string
215 aad string
216 mem memory.Allocator
217 }
218
219 func (e *encryptor) FileAad() string { return e.fileAad }
220 func (e *encryptor) UpdateAad(aad string) { e.aad = aad }
221 func (e *encryptor) Allocator() memory.Allocator { return e.mem }
222 func (e *encryptor) CiphertextSizeDelta() int { return e.aesEncryptor.CiphertextSizeDelta() }
223
224 func (e *encryptor) EncryptColumnMetaData(encryptFooter bool, properties *parquet.ColumnEncryptionProperties) bool {
225 if properties == nil || !properties.IsEncrypted() {
226 return false
227 }
228 if !encryptFooter {
229 return false
230 }
231
232 return !properties.IsEncryptedWithFooterKey()
233 }
234
235 func (e *encryptor) Encrypt(w io.Writer, src []byte) int {
236 return e.aesEncryptor.Encrypt(w, src, e.key, []byte(e.aad))
237 }
238
View as plain text