github.com/ethersphere/bee/v2@v2.2.0/pkg/encryption/store/decrypt_store.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package store
     6  
     7  import (
     8  	"context"
     9  	"encoding/binary"
    10  
    11  	"github.com/ethersphere/bee/v2/pkg/encryption"
    12  	"github.com/ethersphere/bee/v2/pkg/file"
    13  	"github.com/ethersphere/bee/v2/pkg/file/redundancy"
    14  	storage "github.com/ethersphere/bee/v2/pkg/storage"
    15  	"github.com/ethersphere/bee/v2/pkg/swarm"
    16  )
    17  
    18  type decryptingStore struct {
    19  	storage.Getter
    20  }
    21  
    22  func New(s storage.Getter) storage.Getter {
    23  	return &decryptingStore{s}
    24  }
    25  
    26  func (s *decryptingStore) Get(ctx context.Context, addr swarm.Address) (ch swarm.Chunk, err error) {
    27  	switch l := len(addr.Bytes()); l {
    28  	case swarm.HashSize:
    29  		// normal, unencrypted content
    30  		return s.Getter.Get(ctx, addr)
    31  
    32  	case encryption.ReferenceSize:
    33  		// encrypted reference
    34  		ref := addr.Bytes()
    35  		address := swarm.NewAddress(ref[:swarm.HashSize])
    36  		ch, err := s.Getter.Get(ctx, address)
    37  		if err != nil {
    38  			return nil, err
    39  		}
    40  
    41  		d, err := DecryptChunkData(ch.Data(), ref[swarm.HashSize:])
    42  		if err != nil {
    43  			return nil, err
    44  		}
    45  		return swarm.NewChunk(address, d), nil
    46  
    47  	default:
    48  		return nil, storage.ErrReferenceLength
    49  	}
    50  }
    51  
    52  func DecryptChunkData(chunkData []byte, encryptionKey encryption.Key) ([]byte, error) {
    53  	decryptedSpan, decryptedData, err := decrypt(chunkData, encryptionKey)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	// removing extra bytes which were just added for padding
    59  	level, span := redundancy.DecodeSpan(decryptedSpan)
    60  	length := binary.LittleEndian.Uint64(span)
    61  	if length > swarm.ChunkSize {
    62  		dataRefSize := uint64(swarm.HashSize + encryption.KeyLength)
    63  		dataShards, parities := file.ReferenceCount(length, level, true)
    64  		length = dataRefSize*uint64(dataShards) + uint64(parities*swarm.HashSize)
    65  	}
    66  
    67  	c := make([]byte, length+8)
    68  	copy(c[:8], decryptedSpan)
    69  	copy(c[8:], decryptedData[:length])
    70  
    71  	return c, nil
    72  }
    73  
    74  func decrypt(chunkData []byte, key encryption.Key) ([]byte, []byte, error) {
    75  	decryptedSpan, err := encryption.NewSpanEncryption(key).Decrypt(chunkData[:swarm.SpanSize])
    76  	if err != nil {
    77  		return nil, nil, err
    78  	}
    79  	decryptedData, err := encryption.NewDataEncryption(key).Decrypt(chunkData[swarm.SpanSize:])
    80  	if err != nil {
    81  		return nil, nil, err
    82  	}
    83  	return decryptedSpan, decryptedData, nil
    84  }