@@ -35,8 +35,9 @@ constexpr int aesCtr = 1;
3535constexpr int encryptType = 0 ;
3636constexpr int decryptType = 1 ;
3737constexpr int gcmTagLen = 16 ;
38- constexpr int gcmIvLen = 12 ;
38+ constexpr int nonceLen = 12 ;
3939constexpr int ctrIvLen = 16 ;
40+ constexpr int bufferSizeLen = 4 ;
4041constexpr int rndMaxBytes = 32 ;
4142
4243#define ENCRYPT_INIT (CTX, ALG ) \
@@ -141,8 +142,8 @@ int gcm_encrypt(const uint8_t* plaintext, int plaintext_len, uint8_t* key, int k
141142
142143 uint8_t tag[gcmTagLen];
143144 memset (tag, 0 , gcmTagLen);
144- uint8_t iv[gcmIvLen ];
145- memset (iv, 0 , gcmIvLen );
145+ uint8_t iv[nonceLen ];
146+ memset (iv, 0 , nonceLen );
146147
147148 // Random IV
148149 RAND_load_file (" /dev/urandom" , rndMaxBytes);
@@ -163,15 +164,15 @@ int gcm_encrypt(const uint8_t* plaintext, int plaintext_len, uint8_t* key, int k
163164 }
164165
165166 // Encryption
166- if (1 != EVP_EncryptUpdate (cipher.get (), ciphertext + gcmIvLen, &len, plaintext,
167- plaintext_len)) {
167+ if (1 != EVP_EncryptUpdate (cipher.get (), ciphertext + bufferSizeLen + nonceLen,
168+ &len, plaintext, plaintext_len)) {
168169 throw ParquetException (" Failed encryption update" );
169170 }
170171
171172 ciphertext_len = len;
172173
173174 // Finalization
174- if (1 != EVP_EncryptFinal_ex (cipher.get (), ciphertext + gcmIvLen + len, &len)) {
175+ if (1 != EVP_EncryptFinal_ex (cipher.get (), ciphertext + bufferSizeLen + nonceLen + len, &len)) {
175176 throw ParquetException (" Failed encryption finalization" );
176177 }
177178
@@ -182,11 +183,18 @@ int gcm_encrypt(const uint8_t* plaintext, int plaintext_len, uint8_t* key, int k
182183 throw ParquetException (" Couldn't get AES-GCM tag" );
183184 }
184185
185- // Copying the IV and tag to ciphertext
186- std::copy (iv, iv + gcmIvLen, ciphertext);
187- std::copy (tag, tag + gcmTagLen, ciphertext + gcmIvLen + ciphertext_len);
188-
189- return gcmIvLen + ciphertext_len + gcmTagLen;
186+ // Copying the buffer size, IV and tag to ciphertext
187+ int bufferSize = nonceLen + ciphertext_len + gcmTagLen;
188+ uint8_t bufferSizeArray [bufferSizeLen];
189+ bufferSizeArray[3 ] = 0xff & (bufferSize >> 24 );
190+ bufferSizeArray[2 ] = 0xff & (bufferSize >> 16 );
191+ bufferSizeArray[1 ] = 0xff & (bufferSize >> 8 );
192+ bufferSizeArray[0 ] = 0xff & (bufferSize);
193+ std::copy (bufferSizeArray, bufferSizeArray + bufferSizeLen, ciphertext);
194+ std::copy (iv, iv + nonceLen, ciphertext + bufferSizeLen);
195+ std::copy (tag, tag + gcmTagLen, ciphertext + bufferSizeLen + nonceLen + ciphertext_len);
196+
197+ return bufferSize;
190198}
191199
192200int ctr_encrypt (const uint8_t * plaintext, int plaintext_len, uint8_t * key, int key_len,
@@ -196,10 +204,16 @@ int ctr_encrypt(const uint8_t* plaintext, int plaintext_len, uint8_t* key, int k
196204
197205 uint8_t iv[ctrIvLen];
198206 memset (iv, 0 , ctrIvLen);
207+ iv[ctrIvLen - 1 ] = 1 ;
208+
209+ uint8_t nonce[nonceLen];
210+ memset (iv, 0 , nonceLen);
199211
200- // Random IV
212+ // Random nonce
201213 RAND_load_file (" /dev/urandom" , rndMaxBytes);
202- RAND_bytes (iv, sizeof (iv));
214+ RAND_bytes (nonce, sizeof (nonce));
215+
216+ std::copy (nonce, nonce + nonceLen, iv);
203217
204218 // Init cipher context
205219 EvpCipher cipher (aesCtr, key_len, encryptType);
@@ -210,24 +224,31 @@ int ctr_encrypt(const uint8_t* plaintext, int plaintext_len, uint8_t* key, int k
210224 }
211225
212226 // Encryption
213- if (1 != EVP_EncryptUpdate (cipher.get (), ciphertext + ctrIvLen, &len, plaintext,
227+ if (1 != EVP_EncryptUpdate (cipher.get (), ciphertext + bufferSizeLen + ctrIvLen, &len, plaintext,
214228 plaintext_len)) {
215229 throw ParquetException (" Failed encryption update" );
216230 }
217231
218232 ciphertext_len = len;
219233
220234 // Finalization
221- if (1 != EVP_EncryptFinal_ex (cipher.get (), ciphertext + ctrIvLen + len, &len)) {
235+ if (1 != EVP_EncryptFinal_ex (cipher.get (), ciphertext + bufferSizeLen + ctrIvLen + len, &len)) {
222236 throw ParquetException (" Failed encryption finalization" );
223237 }
224238
225239 ciphertext_len += len;
226240
227- // Copying the IV ciphertext
228- std::copy (iv, iv + ctrIvLen, ciphertext);
229-
230- return ctrIvLen + ciphertext_len;
241+ // Copying the buffer size and IV to ciphertext
242+ int bufferSize = ctrIvLen + ciphertext_len;
243+ uint8_t bufferSizeArray [bufferSizeLen];
244+ bufferSizeArray[3 ] = 0xff & (bufferSize >> 24 );
245+ bufferSizeArray[2 ] = 0xff & (bufferSize >> 16 );
246+ bufferSizeArray[1 ] = 0xff & (bufferSize >> 8 );
247+ bufferSizeArray[0 ] = 0xff & (bufferSize);
248+ std::copy (bufferSizeArray, bufferSizeArray + bufferSizeLen, ciphertext);
249+ std::copy (iv, iv + ctrIvLen, ciphertext + bufferSizeLen);
250+
251+ return bufferSize;
231252}
232253
233254int Encrypt (Encryption::type alg_id, bool metadata, const uint8_t * plaintext,
@@ -262,11 +283,11 @@ int gcm_decrypt(const uint8_t* ciphertext, int ciphertext_len, uint8_t* key, int
262283
263284 uint8_t tag[gcmTagLen];
264285 memset (tag, 0 , gcmTagLen);
265- uint8_t iv[gcmIvLen ];
266- memset (iv, 0 , gcmIvLen );
286+ uint8_t iv[nonceLen ];
287+ memset (iv, 0 , nonceLen );
267288
268289 // Extracting IV and tag
269- std::copy (ciphertext, ciphertext + gcmIvLen , iv);
290+ std::copy (ciphertext + bufferSizeLen , ciphertext + bufferSizeLen + nonceLen , iv);
270291 std::copy (ciphertext + ciphertext_len - gcmTagLen, ciphertext + ciphertext_len, tag);
271292
272293 // Init cipher context
@@ -284,8 +305,8 @@ int gcm_decrypt(const uint8_t* ciphertext, int ciphertext_len, uint8_t* key, int
284305 }
285306
286307 // Decryption
287- if (!EVP_DecryptUpdate (cipher.get (), plaintext, &len, ciphertext + gcmIvLen ,
288- ciphertext_len - gcmIvLen - gcmTagLen)) {
308+ if (!EVP_DecryptUpdate (cipher.get (), plaintext, &len, ciphertext + bufferSizeLen + nonceLen ,
309+ ciphertext_len - bufferSizeLen - nonceLen - gcmTagLen)) {
289310 throw ParquetException (" Failed decryption update" );
290311 }
291312
@@ -314,7 +335,7 @@ int ctr_decrypt(const uint8_t* ciphertext, int ciphertext_len, uint8_t* key, int
314335 memset (iv, 0 , ctrIvLen);
315336
316337 // Extracting IV and tag
317- std::copy (ciphertext, ciphertext + ctrIvLen, iv);
338+ std::copy (ciphertext + bufferSizeLen , ciphertext + bufferSizeLen + ctrIvLen, iv);
318339
319340 // Init cipher context
320341 EvpCipher cipher (aesCtr, key_len, decryptType);
@@ -325,8 +346,8 @@ int ctr_decrypt(const uint8_t* ciphertext, int ciphertext_len, uint8_t* key, int
325346 }
326347
327348 // Decryption
328- if (!EVP_DecryptUpdate (cipher.get (), plaintext, &len, ciphertext + ctrIvLen,
329- ciphertext_len - ctrIvLen)) {
349+ if (!EVP_DecryptUpdate (cipher.get (), plaintext, &len, ciphertext + bufferSizeLen + ctrIvLen,
350+ ciphertext_len - bufferSizeLen - ctrIvLen)) {
330351 throw ParquetException (" Failed decryption update" );
331352 }
332353
0 commit comments