summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-08-30 00:20:31 +0200
committerJakob Unterwurzacher2016-09-25 16:43:17 +0200
commit5931eea3877ae34cdb18ac36e5cf5fba3f74b82b (patch)
treef6cd8dd41c213013741ae893e67ec1adf3ff5b4c /internal
parent1d4c6288f29d74efce83ada1ea2a7b3819178bde (diff)
contentenc: add helpers for reverse mode
Add the reverse variant of DecryptBlocks etc: * EncryptBlocks * JointPlaintextRange * ExplodeCipherRange
Diffstat (limited to 'internal')
-rw-r--r--internal/contentenc/content.go14
-rw-r--r--internal/contentenc/intrablock.go28
-rw-r--r--internal/contentenc/offsets.go31
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
}