starcrypto/symm/segment_decrypt.go

55 lines
1.7 KiB
Go

package symm
import (
"crypto/cipher"
"errors"
)
var (
ErrSegmentNotFullBlocks = errors.New("ciphertext segment is not a full block size")
)
func decryptECBBlocks(block cipher.Block, src []byte) ([]byte, error) {
if len(src) == 0 {
return []byte{}, nil
}
if len(src)%block.BlockSize() != 0 {
return nil, ErrSegmentNotFullBlocks
}
out := make([]byte, len(src))
ecbDecryptBlocks(block, out, src)
return out, nil
}
// decryptCBCFromSecondBlock decrypts a CBC ciphertext segment that starts from the second block (or later).
// prevCipherBlock must be the previous ciphertext block (C[i-1]); for i=1 this is the original IV.
func decryptCBCFromSecondBlock(block cipher.Block, src, prevCipherBlock []byte) ([]byte, error) {
if len(src) == 0 {
return []byte{}, nil
}
if len(prevCipherBlock) != block.BlockSize() {
return nil, errors.New("prev cipher block length must match block size")
}
if len(src)%block.BlockSize() != 0 {
return nil, ErrSegmentNotFullBlocks
}
out := make([]byte, len(src))
cipher.NewCBCDecrypter(block, prevCipherBlock).CryptBlocks(out, src)
return out, nil
}
// decryptCFBFromSecondBlock decrypts a CFB ciphertext segment that starts from the second block (or later).
// prevCipherBlock must be the previous ciphertext block (C[i-1]); for i=1 this is the original IV.
func decryptCFBFromSecondBlock(block cipher.Block, src, prevCipherBlock []byte) ([]byte, error) {
if len(src) == 0 {
return []byte{}, nil
}
if len(prevCipherBlock) != block.BlockSize() {
return nil, errors.New("prev cipher block length must match block size")
}
stream := cipher.NewCFBDecrypter(block, prevCipherBlock)
out := make([]byte, len(src))
stream.XORKeyStream(out, src)
return out, nil
}