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 }