diff options
| author | Jakob Unterwurzacher | 2016-08-30 00:20:31 +0200 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2016-09-25 16:43:17 +0200 | 
| commit | 5931eea3877ae34cdb18ac36e5cf5fba3f74b82b (patch) | |
| tree | f6cd8dd41c213013741ae893e67ec1adf3ff5b4c | |
| parent | 1d4c6288f29d74efce83ada1ea2a7b3819178bde (diff) | |
contentenc: add helpers for reverse mode
Add the reverse variant of DecryptBlocks etc:
* EncryptBlocks
* JointPlaintextRange
* ExplodeCipherRange
| -rw-r--r-- | internal/contentenc/content.go | 14 | ||||
| -rw-r--r-- | internal/contentenc/intrablock.go | 28 | ||||
| -rw-r--r-- | internal/contentenc/offsets.go | 31 | 
3 files changed, 68 insertions, 5 deletions
| diff --git a/internal/contentenc/content.go b/internal/contentenc/content.go index 493ec56..375221a 100644 --- a/internal/contentenc/content.go +++ b/internal/contentenc/content.go @@ -50,6 +50,7 @@ func (be *ContentEnc) CipherBS() uint64 {  }  // DecryptBlocks - Decrypt a number of blocks +// TODO refactor to three-param for  func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, fileId []byte) ([]byte, error) {  	cBuf := bytes.NewBuffer(ciphertext)  	var err error @@ -110,6 +111,19 @@ func (be *ContentEnc) DecryptBlock(ciphertext []byte, blockNo uint64, fileId []b  	return plaintext, nil  } +// EncryptBlocks - Encrypt a number of blocks +// Used for reverse mode +func (be *ContentEnc) EncryptBlocks(plaintext []byte, firstBlockNo uint64, fileId []byte) []byte { +	inBuf := bytes.NewBuffer(plaintext) +	var outBuf bytes.Buffer +	for blockNo := firstBlockNo; inBuf.Len() > 0; blockNo++ { +		inBlock := inBuf.Next(int(be.plainBS)) +		outBlock := be.EncryptBlock(inBlock, blockNo, fileId) +		outBuf.Write(outBlock) +	} +	return outBuf.Bytes() +} +  // encryptBlock - Encrypt and add IV and MAC  func (be *ContentEnc) EncryptBlock(plaintext []byte, blockNo uint64, fileID []byte) []byte { diff --git a/internal/contentenc/intrablock.go b/internal/contentenc/intrablock.go index 9a22ea2..632e76b 100644 --- a/internal/contentenc/intrablock.go +++ b/internal/contentenc/intrablock.go @@ -2,10 +2,19 @@ package contentenc  // intraBlock identifies a part of a file block  type intraBlock struct { -	BlockNo uint64 // Block number in file -	Skip    uint64 // Offset into block plaintext -	Length  uint64 // Length of plaintext data in this block -	fs      *ContentEnc +	// Block number in the file +	BlockNo uint64 +	// Offset into block payload +	// In forwared mode: block plaintext +	// In reverse mode: offset into block ciphertext. Takes the header into +	// account. +	Skip uint64 +	// Length of payload data in this block +	// In forwared mode: length of the plaintext +	// In reverse mode: length of the ciphertext. Takes header and trailer into +	// account. +	Length uint64 +	fs     *ContentEnc  }  // isPartial - is the block partial? This means we have to do read-modify-write. @@ -47,3 +56,14 @@ func (ib *intraBlock) JointCiphertextRange(blocks []intraBlock) (offset uint64,  	return offset, length  } + +// Plaintext range corresponding to the sum of all "blocks" (complete blocks) +func JointPlaintextRange(blocks []intraBlock) (offset uint64, length uint64) { +	firstBlock := blocks[0] +	lastBlock := blocks[len(blocks)-1] + +	offset = firstBlock.BlockPlainOff() +	length = lastBlock.BlockPlainOff() + lastBlock.fs.PlainBS() - offset + +	return offset, length +} diff --git a/internal/contentenc/offsets.go b/internal/contentenc/offsets.go index 813a15f..e331d55 100644 --- a/internal/contentenc/offsets.go +++ b/internal/contentenc/offsets.go @@ -11,8 +11,11 @@ func (be *ContentEnc) PlainOffToBlockNo(plainOffset uint64) uint64 {  	return plainOffset / be.plainBS  } -// get the block number at ciphter-text offset +// get the block number at cipher-text offset  func (be *ContentEnc) CipherOffToBlockNo(cipherOffset uint64) uint64 { +	if cipherOffset < HEADER_LEN { +		panic("BUG: offset is inside the file header") +	}  	return (cipherOffset - HEADER_LEN) / be.cipherBS  } @@ -89,6 +92,32 @@ func (be *ContentEnc) ExplodePlainRange(offset uint64, length uint64) []intraBlo  	return blocks  } +// Split a ciphertext byte range into (possibly partial) blocks +// This is used in reverse mode when reading files +func (be *ContentEnc) ExplodeCipherRange(offset uint64, length uint64) []intraBlock { +	var blocks []intraBlock +	var nextBlock intraBlock +	nextBlock.fs = be + +	for length > 0 { +		nextBlock.BlockNo = be.CipherOffToBlockNo(offset) +		nextBlock.Skip = offset - be.BlockNoToCipherOff(nextBlock.BlockNo) + +		// This block can carry up to "maxLen" payload bytes +		maxLen := be.cipherBS - nextBlock.Skip +		nextBlock.Length = maxLen +		// But if the user requested less, we truncate the block to "length". +		if length < maxLen { +			nextBlock.Length = length +		} + +		blocks = append(blocks, nextBlock) +		offset += nextBlock.Length +		length -= nextBlock.Length +	} +	return blocks +} +  func (be *ContentEnc) BlockOverhead() uint64 {  	return be.cipherBS - be.plainBS  } | 
