@@ -28,6 +28,8 @@ import (
28
28
"sync"
29
29
"time"
30
30
31
+ "github.com/pkg/errors"
32
+
31
33
"github.com/dgraph-io/badger/v4/pb"
32
34
"github.com/dgraph-io/badger/v4/y"
33
35
"google.golang.org/protobuf/proto"
@@ -265,7 +267,7 @@ func WriteKeyRegistry(reg *KeyRegistry, opt KeyRegistryOptions) error {
265
267
// Write all the datakeys to the buf.
266
268
for _ , k := range reg .dataKeys {
267
269
// Writing the datakey to the given buffer.
268
- if err := storeDataKey (buf , opt .EncryptionKey , k ); err != nil {
270
+ if err := storeDataKey (buf , opt .EncryptionKey , * k ); err != nil {
269
271
return y .Wrapf (err , "Error while storing datakey in WriteKeyRegistry" )
270
272
}
271
273
}
@@ -339,44 +341,58 @@ func (kr *KeyRegistry) LatestDataKey() (*pb.DataKey, error) {
339
341
defer kr .Unlock ()
340
342
// Key might have generated by another go routine. So,
341
343
// checking once again.
342
- key , valid = validKey ()
343
- if valid {
344
+ if key , valid := validKey (); valid {
344
345
return key , nil
345
346
}
346
347
k := make ([]byte , len (kr .opt .EncryptionKey ))
347
348
iv , err := y .GenerateIV ()
348
349
if err != nil {
349
350
return nil , err
350
351
}
351
- _ , err = rand . Read ( k )
352
- if err != nil {
352
+
353
+ if _ , err := rand . Read ( k ); err != nil {
353
354
return nil , err
354
355
}
355
356
// Otherwise Increment the KeyID and generate new datakey.
356
357
kr .nextKeyID ++
357
- dk := & pb.DataKey {
358
+ dk := pb.DataKey {
358
359
KeyId : kr .nextKeyID ,
359
360
Data : k ,
360
361
CreatedAt : time .Now ().Unix (),
361
362
Iv : iv ,
362
363
}
364
+ kr .lastCreated = dk .CreatedAt
365
+ kr .dataKeys [kr .nextKeyID ] = & dk
363
366
// Don't store the datakey on file if badger is running in InMemory mode.
364
- if ! kr .opt .InMemory {
365
- // Store the datekey.
366
- buf := & bytes.Buffer {}
367
- if err = storeDataKey (buf , kr .opt .EncryptionKey , dk ); err != nil {
368
- return nil , err
369
- }
370
- // Persist the datakey to the disk
371
- if _ , err = kr .fp .Write (buf .Bytes ()); err != nil {
372
- return nil , err
373
- }
367
+ if kr .opt .InMemory {
368
+ return & dk , nil
369
+
374
370
}
375
- // storeDatakey encrypts the datakey So, placing un-encrypted key in the memory.
376
- dk .Data = k
377
- kr .lastCreated = dk .CreatedAt
378
- kr .dataKeys [kr .nextKeyID ] = dk
379
- return dk , nil
371
+ // Store the datekey.
372
+ if err = storeDataKey (kr .fp , kr .opt .EncryptionKey , dk ); err != nil {
373
+ return nil , err
374
+ }
375
+ return & dk , nil
376
+ }
377
+
378
+ func (kr * KeyRegistry ) AddKey (dk pb.DataKey ) (uint64 , error ) {
379
+ // If we don't have a encryption key, we cannot store the datakey.
380
+ if len (kr .opt .EncryptionKey ) == 0 {
381
+ return 0 , errors .New ("No encryption key found. Cannot add data key" )
382
+ }
383
+
384
+ if _ , ok := kr .dataKeys [dk .KeyId ]; ! ok {
385
+ // If KeyId does not exists already, then use the next available KeyId to store data key.
386
+ kr .nextKeyID ++
387
+ dk .KeyId = kr .nextKeyID
388
+ }
389
+ kr .dataKeys [dk .KeyId ] = & dk
390
+
391
+ if kr .opt .InMemory {
392
+ return dk .KeyId , nil
393
+ }
394
+ // Store the datakey.
395
+ return dk .KeyId , storeDataKey (kr .fp , kr .opt .EncryptionKey , dk )
380
396
}
381
397
382
398
// Close closes the key registry.
@@ -388,38 +404,36 @@ func (kr *KeyRegistry) Close() error {
388
404
}
389
405
390
406
// storeDataKey stores datakey in an encrypted format in the given buffer. If storage key preset.
391
- func storeDataKey (buf * bytes.Buffer , storageKey []byte , k * pb.DataKey ) error {
407
+ // DO NOT use a pointer for key. storeDataKey modifies the kv.Data field.
408
+ func storeDataKey (w io.Writer , storageKey []byte , key pb.DataKey ) error {
392
409
// xor will encrypt the IV and xor with the given data.
393
410
// It'll used for both encryption and decryption.
394
411
xor := func () error {
395
412
if len (storageKey ) == 0 {
396
413
return nil
397
414
}
398
415
var err error
399
- k .Data , err = y .XORBlockAllocate (k .Data , storageKey , k .Iv )
416
+ key .Data , err = y .XORBlockAllocate (key .Data , storageKey , key .Iv )
400
417
return err
401
418
}
402
419
// In memory datakey will be plain text so encrypting before storing to the disk.
403
- var err error
404
- if err = xor (); err != nil {
420
+ if err := xor (); err != nil {
405
421
return y .Wrapf (err , "Error while encrypting datakey in storeDataKey" )
406
422
}
407
- var data []byte
408
- if data , err = proto .Marshal (k ); err != nil {
423
+
424
+ data , err := key .Marshal ()
425
+ if err != nil {
409
426
err = y .Wrapf (err , "Error while marshaling datakey in storeDataKey" )
410
- var err2 error
411
- // decrypting the datakey back.
412
- if err2 = xor (); err2 != nil {
413
- return y .Wrapf (err ,
414
- y .Wrapf (err2 , "Error while decrypting datakey in storeDataKey" ).Error ())
427
+ if err2 := xor (); err2 != nil {
428
+ return y .Wrapf (err , y .Wrapf (err2 , "Error while decrypting datakey in storeDataKey" ).Error ())
415
429
}
416
430
return err
417
431
}
432
+
418
433
var lenCrcBuf [8 ]byte
419
434
binary .BigEndian .PutUint32 (lenCrcBuf [0 :4 ], uint32 (len (data )))
420
435
binary .BigEndian .PutUint32 (lenCrcBuf [4 :8 ], crc32 .Checksum (data , y .CastagnoliCrcTable ))
421
- y .Check2 (buf .Write (lenCrcBuf [:]))
422
- y .Check2 (buf .Write (data ))
423
- // Decrypting the datakey back since we're using the pointer.
424
- return xor ()
436
+ y .Check2 (w .Write (lenCrcBuf [:]))
437
+ y .Check2 (w .Write (data ))
438
+ return nil
425
439
}
0 commit comments