@@ -28,6 +28,8 @@ import (
2828 "sync"
2929 "time"
3030
31+ "github.com/pkg/errors"
32+
3133 "github.com/dgraph-io/badger/v3/pb"
3234 "github.com/dgraph-io/badger/v3/y"
3335)
@@ -264,7 +266,7 @@ func WriteKeyRegistry(reg *KeyRegistry, opt KeyRegistryOptions) error {
264266 // Write all the datakeys to the buf.
265267 for _ , k := range reg .dataKeys {
266268 // Writing the datakey to the given buffer.
267- if err := storeDataKey (buf , opt .EncryptionKey , k ); err != nil {
269+ if err := storeDataKey (buf , opt .EncryptionKey , * k ); err != nil {
268270 return y .Wrapf (err , "Error while storing datakey in WriteKeyRegistry" )
269271 }
270272 }
@@ -338,44 +340,58 @@ func (kr *KeyRegistry) LatestDataKey() (*pb.DataKey, error) {
338340 defer kr .Unlock ()
339341 // Key might have generated by another go routine. So,
340342 // checking once again.
341- key , valid = validKey ()
342- if valid {
343+ if key , valid := validKey (); valid {
343344 return key , nil
344345 }
345346 k := make ([]byte , len (kr .opt .EncryptionKey ))
346347 iv , err := y .GenerateIV ()
347348 if err != nil {
348349 return nil , err
349350 }
350- _ , err = rand . Read ( k )
351- if err != nil {
351+
352+ if _ , err := rand . Read ( k ); err != nil {
352353 return nil , err
353354 }
354355 // Otherwise Increment the KeyID and generate new datakey.
355356 kr .nextKeyID ++
356- dk := & pb.DataKey {
357+ dk := pb.DataKey {
357358 KeyId : kr .nextKeyID ,
358359 Data : k ,
359360 CreatedAt : time .Now ().Unix (),
360361 Iv : iv ,
361362 }
363+ kr .lastCreated = dk .CreatedAt
364+ kr .dataKeys [kr .nextKeyID ] = & dk
362365 // Don't store the datakey on file if badger is running in InMemory mode.
363- if ! kr .opt .InMemory {
364- // Store the datekey.
365- buf := & bytes.Buffer {}
366- if err = storeDataKey (buf , kr .opt .EncryptionKey , dk ); err != nil {
367- return nil , err
368- }
369- // Persist the datakey to the disk
370- if _ , err = kr .fp .Write (buf .Bytes ()); err != nil {
371- return nil , err
372- }
366+ if kr .opt .InMemory {
367+ return & dk , nil
368+
373369 }
374- // storeDatakey encrypts the datakey So, placing un-encrypted key in the memory.
375- dk .Data = k
376- kr .lastCreated = dk .CreatedAt
377- kr .dataKeys [kr .nextKeyID ] = dk
378- return dk , nil
370+ // Store the datekey.
371+ if err = storeDataKey (kr .fp , kr .opt .EncryptionKey , dk ); err != nil {
372+ return nil , err
373+ }
374+ return & dk , nil
375+ }
376+
377+ func (kr * KeyRegistry ) AddKey (dk pb.DataKey ) (uint64 , error ) {
378+ // If we don't have a encryption key, we cannot store the datakey.
379+ if len (kr .opt .EncryptionKey ) == 0 {
380+ return 0 , errors .New ("No encryption key found. Cannot add data key" )
381+ }
382+
383+ if _ , ok := kr .dataKeys [dk .KeyId ]; ! ok {
384+ // If KeyId does not exists already, then use the next available KeyId to store data key.
385+ kr .nextKeyID ++
386+ dk .KeyId = kr .nextKeyID
387+ }
388+ kr .dataKeys [dk .KeyId ] = & dk
389+
390+ if kr .opt .InMemory {
391+ return dk .KeyId , nil
392+ }
393+ // Store the datakey.
394+ return dk .KeyId , storeDataKey (kr .fp , kr .opt .EncryptionKey , dk )
379395}
380396
381397// Close closes the key registry.
@@ -387,38 +403,30 @@ func (kr *KeyRegistry) Close() error {
387403}
388404
389405// storeDataKey stores datakey in an encrypted format in the given buffer. If storage key preset.
390- func storeDataKey (buf * bytes.Buffer , storageKey []byte , k * pb.DataKey ) error {
406+ // DO NOT use a pointer for key. storeDataKey modifies the kv.Data field.
407+ func storeDataKey (w io.Writer , storageKey []byte , key pb.DataKey ) error {
391408 // xor will encrypt the IV and xor with the given data.
392409 // It'll used for both encryption and decryption.
393410 xor := func () error {
394411 if len (storageKey ) == 0 {
395412 return nil
396413 }
397414 var err error
398- k .Data , err = y .XORBlockAllocate (k .Data , storageKey , k .Iv )
415+ key .Data , err = y .XORBlockAllocate (key .Data , storageKey , key .Iv )
399416 return err
400417 }
401418 // In memory datakey will be plain text so encrypting before storing to the disk.
402- var err error
403- if err = xor (); err != nil {
419+ if err := xor (); err != nil {
404420 return y .Wrapf (err , "Error while encrypting datakey in storeDataKey" )
405421 }
406- var data []byte
407- if data , err = k .Marshal (); err != nil {
408- err = y .Wrapf (err , "Error while marshaling datakey in storeDataKey" )
409- var err2 error
410- // decrypting the datakey back.
411- if err2 = xor (); err2 != nil {
412- return y .Wrapf (err ,
413- y .Wrapf (err2 , "Error while decrypting datakey in storeDataKey" ).Error ())
414- }
415- return err
422+ data , err := key .Marshal ()
423+ if err != nil {
424+ return y .Wrapf (err , "Error while marshaling datakey in storeDataKey" )
416425 }
417426 var lenCrcBuf [8 ]byte
418427 binary .BigEndian .PutUint32 (lenCrcBuf [0 :4 ], uint32 (len (data )))
419428 binary .BigEndian .PutUint32 (lenCrcBuf [4 :8 ], crc32 .Checksum (data , y .CastagnoliCrcTable ))
420- y .Check2 (buf .Write (lenCrcBuf [:]))
421- y .Check2 (buf .Write (data ))
422- // Decrypting the datakey back since we're using the pointer.
423- return xor ()
429+ y .Check2 (w .Write (lenCrcBuf [:]))
430+ y .Check2 (w .Write (data ))
431+ return nil
424432}
0 commit comments