github.com/emmansun/gmsm@v0.29.1/cipher/ecb.go (about)

     1  // Electronic Code Book (ECB) mode.
     2  
     3  // Please do NOT use this mode alone.
     4  package cipher
     5  
     6  import (
     7  	goCipher "crypto/cipher"
     8  
     9  	"github.com/emmansun/gmsm/internal/alias"
    10  )
    11  
    12  type ecb struct {
    13  	b         goCipher.Block
    14  	blockSize int
    15  }
    16  
    17  func newECB(b goCipher.Block) *ecb {
    18  	return &ecb{
    19  		b:         b,
    20  		blockSize: b.BlockSize(),
    21  	}
    22  }
    23  
    24  func validate(size int, dst, src []byte) {
    25  	if len(src)%size != 0 {
    26  		panic("cipher: input not full blocks")
    27  	}
    28  	if len(dst) < len(src) {
    29  		panic("cipher: output smaller than input")
    30  	}
    31  	if alias.InexactOverlap(dst[:len(src)], src) {
    32  		panic("cipher: invalid buffer overlap")
    33  	}
    34  }
    35  
    36  type ecbEncrypter ecb
    37  
    38  // ecbEncAble is an interface implemented by ciphers that have a specific
    39  // optimized implementation of ECB encryption, like sm4.
    40  // NewECBEncrypter will check for this interface and return the specific
    41  // BlockMode if found.
    42  type ecbEncAble interface {
    43  	NewECBEncrypter() goCipher.BlockMode
    44  }
    45  
    46  // NewECBEncrypter returns a BlockMode which encrypts in electronic code book
    47  // mode, using the given Block.
    48  func NewECBEncrypter(b goCipher.Block) goCipher.BlockMode {
    49  	if ecb, ok := b.(ecbEncAble); ok {
    50  		return ecb.NewECBEncrypter()
    51  	}
    52  	return (*ecbEncrypter)(newECB(b))
    53  }
    54  
    55  func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
    56  
    57  func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
    58  	validate(x.blockSize, dst, src)
    59  
    60  	for len(src) > 0 {
    61  		x.b.Encrypt(dst[:x.blockSize], src[:x.blockSize])
    62  		src = src[x.blockSize:]
    63  		dst = dst[x.blockSize:]
    64  	}
    65  }
    66  
    67  type ecbDecrypter ecb
    68  
    69  // ecbDecAble is an interface implemented by ciphers that have a specific
    70  // optimized implementation of ECB decryption, like sm4.
    71  // NewECBDecrypter will check for this interface and return the specific
    72  // BlockMode if found.
    73  type ecbDecAble interface {
    74  	NewECBDecrypter() goCipher.BlockMode
    75  }
    76  
    77  // NewECBDecrypter returns a BlockMode which decrypts in electronic code book
    78  // mode, using the given Block.
    79  func NewECBDecrypter(b goCipher.Block) goCipher.BlockMode {
    80  	if ecb, ok := b.(ecbDecAble); ok {
    81  		return ecb.NewECBDecrypter()
    82  	}
    83  	return (*ecbDecrypter)(newECB(b))
    84  }
    85  
    86  func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
    87  
    88  func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
    89  	validate(x.blockSize, dst, src)
    90  
    91  	if len(src) == 0 {
    92  		return
    93  	}
    94  
    95  	for len(src) > 0 {
    96  		x.b.Decrypt(dst[:x.blockSize], src[:x.blockSize])
    97  		src = src[x.blockSize:]
    98  		dst = dst[x.blockSize:]
    99  	}
   100  }