contentenc: add helpers for reverse mode
Add the reverse variant of DecryptBlocks etc: * EncryptBlocks * JointPlaintextRange * ExplodeCipherRange
This commit is contained in:
parent
1d4c6288f2
commit
5931eea387
@ -50,6 +50,7 @@ func (be *ContentEnc) CipherBS() uint64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DecryptBlocks - Decrypt a number of blocks
|
// DecryptBlocks - Decrypt a number of blocks
|
||||||
|
// TODO refactor to three-param for
|
||||||
func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, fileId []byte) ([]byte, error) {
|
func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, fileId []byte) ([]byte, error) {
|
||||||
cBuf := bytes.NewBuffer(ciphertext)
|
cBuf := bytes.NewBuffer(ciphertext)
|
||||||
var err error
|
var err error
|
||||||
@ -110,6 +111,19 @@ func (be *ContentEnc) DecryptBlock(ciphertext []byte, blockNo uint64, fileId []b
|
|||||||
return plaintext, nil
|
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
|
// encryptBlock - Encrypt and add IV and MAC
|
||||||
func (be *ContentEnc) EncryptBlock(plaintext []byte, blockNo uint64, fileID []byte) []byte {
|
func (be *ContentEnc) EncryptBlock(plaintext []byte, blockNo uint64, fileID []byte) []byte {
|
||||||
|
|
||||||
|
@ -2,9 +2,18 @@ package contentenc
|
|||||||
|
|
||||||
// intraBlock identifies a part of a file block
|
// intraBlock identifies a part of a file block
|
||||||
type intraBlock struct {
|
type intraBlock struct {
|
||||||
BlockNo uint64 // Block number in file
|
// Block number in the file
|
||||||
Skip uint64 // Offset into block plaintext
|
BlockNo uint64
|
||||||
Length uint64 // Length of plaintext data in this block
|
// 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
|
fs *ContentEnc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,3 +56,14 @@ func (ib *intraBlock) JointCiphertextRange(blocks []intraBlock) (offset uint64,
|
|||||||
|
|
||||||
return offset, length
|
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
|
||||||
|
}
|
||||||
|
@ -11,8 +11,11 @@ func (be *ContentEnc) PlainOffToBlockNo(plainOffset uint64) uint64 {
|
|||||||
return plainOffset / be.plainBS
|
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 {
|
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
|
return (cipherOffset - HEADER_LEN) / be.cipherBS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +92,32 @@ func (be *ContentEnc) ExplodePlainRange(offset uint64, length uint64) []intraBlo
|
|||||||
return blocks
|
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 {
|
func (be *ContentEnc) BlockOverhead() uint64 {
|
||||||
return be.cipherBS - be.plainBS
|
return be.cipherBS - be.plainBS
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user