55 lines
1.7 KiB
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
|
||
|
|
}
|