@@ -30,6 +30,7 @@ import (
3030
3131 "github.com/dgraph-io/badger/v3/pb"
3232 "github.com/dgraph-io/badger/v3/y"
33+ "github.com/pkg/errors"
3334)
3435
3536const (
@@ -264,7 +265,7 @@ func WriteKeyRegistry(reg *KeyRegistry, opt KeyRegistryOptions) error {
264265 // Write all the datakeys to the buf.
265266 for _ , k := range reg .dataKeys {
266267 // Writing the datakey to the given buffer.
267- if err := storeDataKey (buf , opt .EncryptionKey , k ); err != nil {
268+ if err := storeDataKey (buf , opt .EncryptionKey , * k ); err != nil {
268269 return y .Wrapf (err , "Error while storing datakey in WriteKeyRegistry" )
269270 }
270271 }
@@ -338,44 +339,58 @@ func (kr *KeyRegistry) LatestDataKey() (*pb.DataKey, error) {
338339 defer kr .Unlock ()
339340 // Key might have generated by another go routine. So,
340341 // checking once again.
341- key , valid = validKey ()
342- if valid {
342+ if key , valid := validKey (); valid {
343343 return key , nil
344344 }
345345 k := make ([]byte , len (kr .opt .EncryptionKey ))
346346 iv , err := y .GenerateIV ()
347347 if err != nil {
348348 return nil , err
349349 }
350- _ , err = rand . Read ( k )
351- if err != nil {
350+
351+ if _ , err = rand . Read ( k ); err != nil {
352352 return nil , err
353353 }
354354 // Otherwise Increment the KeyID and generate new datakey.
355355 kr .nextKeyID ++
356- dk := & pb.DataKey {
356+ dk := pb.DataKey {
357357 KeyId : kr .nextKeyID ,
358358 Data : k ,
359359 CreatedAt : time .Now ().Unix (),
360360 Iv : iv ,
361361 }
362+ kr .lastCreated = dk .CreatedAt
363+ kr .dataKeys [kr .nextKeyID ] = & dk
362364 // 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- }
365+ if kr .opt .InMemory {
366+ return & dk , nil
367+
373368 }
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
369+ // Store the datekey.
370+ if err = storeDataKey (kr .fp , kr .opt .EncryptionKey , dk ); err != nil {
371+ return nil , err
372+ }
373+ return & dk , nil
374+ }
375+
376+ func (kr * KeyRegistry ) AddKey (dk pb.DataKey ) (uint64 , error ) {
377+ // If we don't have a encryption key, we cannot store the datakey.
378+ if len (kr .opt .EncryptionKey ) == 0 {
379+ return 0 , errors .New ("No encryption key found. Cannot add data key" )
380+ }
381+
382+ if _ , ok := kr .dataKeys [dk .KeyId ]; ! ok {
383+ // If KeyId does not exists already, then use the next available KeyId to store data key.
384+ kr .nextKeyID ++
385+ dk .KeyId = kr .nextKeyID
386+ }
387+ kr .dataKeys [dk .KeyId ] = & dk
388+
389+ if kr .opt .InMemory {
390+ return dk .KeyId , nil
391+ }
392+ // Store the datakey.
393+ return dk .KeyId , storeDataKey (kr .fp , kr .opt .EncryptionKey , dk )
379394}
380395
381396// Close closes the key registry.
@@ -387,38 +402,30 @@ func (kr *KeyRegistry) Close() error {
387402}
388403
389404// 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 {
405+ // DO NOT use a pointer for key. storeDataKey modifies the kv.Data field.
406+ func storeDataKey (w io.Writer , storageKey []byte , key pb.DataKey ) error {
391407 // xor will encrypt the IV and xor with the given data.
392408 // It'll used for both encryption and decryption.
393409 xor := func () error {
394410 if len (storageKey ) == 0 {
395411 return nil
396412 }
397413 var err error
398- k .Data , err = y .XORBlockAllocate (k .Data , storageKey , k .Iv )
414+ key .Data , err = y .XORBlockAllocate (key .Data , storageKey , key .Iv )
399415 return err
400416 }
401417 // In memory datakey will be plain text so encrypting before storing to the disk.
402- var err error
403- if err = xor (); err != nil {
418+ if err := xor (); err != nil {
404419 return y .Wrapf (err , "Error while encrypting datakey in storeDataKey" )
405420 }
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
421+ data , err := key .Marshal ()
422+ if err != nil {
423+ return y .Wrapf (err , "Error while marshaling datakey in storeDataKey" )
416424 }
417425 var lenCrcBuf [8 ]byte
418426 binary .BigEndian .PutUint32 (lenCrcBuf [0 :4 ], uint32 (len (data )))
419427 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 ()
428+ y .Check2 (w .Write (lenCrcBuf [:]))
429+ y .Check2 (w .Write (data ))
430+ return nil
424431}
0 commit comments