github.com/emmansun/gmsm@v0.29.1/sm9/enc_mode.go (about)

     1  package sm9
     2  
     3  import (
     4  	"crypto/cipher"
     5  	"io"
     6  
     7  	_cipher "github.com/emmansun/gmsm/cipher"
     8  	"github.com/emmansun/gmsm/internal/subtle"
     9  	"github.com/emmansun/gmsm/padding"
    10  	"github.com/emmansun/gmsm/sm4"
    11  )
    12  
    13  // EncrypterOpts is an interface implemented by detail encrypt/decrypt mode.
    14  type EncrypterOpts interface {
    15  	// GetEncryptType returns the encrypt type/mode.
    16  	GetEncryptType() encryptType
    17  	// GetKeySize returns key size used by this encrypt mode.
    18  	GetKeySize(plaintext []byte) int
    19  	// Encrypt encrypts the plaintext with the key, returns ciphertext.
    20  	Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error)
    21  	// Decrypt decrypts the ciphertext with the key, returns plaintext.
    22  	Decrypt(key, ciphertext []byte) ([]byte, error)
    23  }
    24  
    25  // XOREncrypterOpts represents XOR mode.
    26  type XOREncrypterOpts struct{}
    27  
    28  func (opts *XOREncrypterOpts) GetEncryptType() encryptType {
    29  	return ENC_TYPE_XOR
    30  }
    31  
    32  func (opts *XOREncrypterOpts) GetKeySize(plaintext []byte) int {
    33  	return len(plaintext)
    34  }
    35  
    36  func (opts *XOREncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
    37  	subtle.XORBytes(key, key, plaintext)
    38  	return key, nil
    39  }
    40  
    41  func (opts *XOREncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
    42  	if len(ciphertext) == 0 {
    43  		return nil, ErrDecryption
    44  	}
    45  	subtle.XORBytes(key, ciphertext, key)
    46  	return key, nil
    47  }
    48  
    49  type newCipher func(key []byte) (cipher.Block, error)
    50  
    51  type baseBlockEncrypterOpts struct {
    52  	encryptType   encryptType
    53  	newCipher     newCipher
    54  	cipherKeySize int
    55  }
    56  
    57  func (opts *baseBlockEncrypterOpts) GetEncryptType() encryptType {
    58  	return opts.encryptType
    59  }
    60  
    61  func (opts *baseBlockEncrypterOpts) GetKeySize(plaintext []byte) int {
    62  	return opts.cipherKeySize
    63  }
    64  
    65  // CBCEncrypterOpts represents CBC (Cipher block chaining) mode.
    66  type CBCEncrypterOpts struct {
    67  	baseBlockEncrypterOpts
    68  	padding padding.Padding
    69  }
    70  
    71  func NewCBCEncrypterOpts(padding padding.Padding, newCipher newCipher, keySize int) EncrypterOpts {
    72  	opts := new(CBCEncrypterOpts)
    73  	opts.encryptType = ENC_TYPE_CBC
    74  	opts.padding = padding
    75  	opts.newCipher = newCipher
    76  	opts.cipherKeySize = keySize
    77  	return opts
    78  }
    79  
    80  // Encrypt encrypts the plaintext with the key, includes generated IV at the beginning of the ciphertext.
    81  func (opts *CBCEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
    82  	block, err := opts.newCipher(key)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  	paddedPlainText := opts.padding.Pad(plaintext)
    87  	blockSize := block.BlockSize()
    88  	ciphertext := make([]byte, blockSize+len(paddedPlainText))
    89  	iv := ciphertext[:blockSize]
    90  	if _, err := io.ReadFull(rand, iv); err != nil {
    91  		return nil, err
    92  	}
    93  	mode := cipher.NewCBCEncrypter(block, iv)
    94  	mode.CryptBlocks(ciphertext[blockSize:], paddedPlainText)
    95  	return ciphertext, nil
    96  }
    97  
    98  func (opts *CBCEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
    99  	block, err := opts.newCipher(key)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	blockSize := block.BlockSize()
   104  	if len(ciphertext) <= blockSize {
   105  		return nil, ErrDecryption
   106  	}
   107  	iv := ciphertext[:blockSize]
   108  	ciphertext = ciphertext[blockSize:]
   109  	plaintext := make([]byte, len(ciphertext))
   110  	mode := cipher.NewCBCDecrypter(block, iv)
   111  	mode.CryptBlocks(plaintext, ciphertext)
   112  	return opts.padding.Unpad(plaintext)
   113  }
   114  
   115  // ECBEncrypterOpts represents ECB (Electronic Code Book) mode.
   116  type ECBEncrypterOpts struct {
   117  	baseBlockEncrypterOpts
   118  	padding padding.Padding
   119  }
   120  
   121  func NewECBEncrypterOpts(padding padding.Padding, newCipher newCipher, keySize int) EncrypterOpts {
   122  	opts := new(ECBEncrypterOpts)
   123  	opts.encryptType = ENC_TYPE_ECB
   124  	opts.padding = padding
   125  	opts.newCipher = newCipher
   126  	opts.cipherKeySize = keySize
   127  	return opts
   128  }
   129  
   130  func (opts *ECBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
   131  	block, err := opts.newCipher(key)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	paddedPlainText := opts.padding.Pad(plaintext)
   136  	ciphertext := make([]byte, len(paddedPlainText))
   137  	mode := _cipher.NewECBEncrypter(block)
   138  	mode.CryptBlocks(ciphertext, paddedPlainText)
   139  	return ciphertext, nil
   140  }
   141  
   142  func (opts *ECBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
   143  	block, err := opts.newCipher(key)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  	if len(ciphertext) == 0 {
   148  		return nil, ErrDecryption
   149  	}
   150  	plaintext := make([]byte, len(ciphertext))
   151  	mode := _cipher.NewECBDecrypter(block)
   152  	mode.CryptBlocks(plaintext, ciphertext)
   153  	return opts.padding.Unpad(plaintext)
   154  }
   155  
   156  // CFBEncrypterOpts represents CFB (Cipher Feedback) mode.
   157  type CFBEncrypterOpts struct {
   158  	baseBlockEncrypterOpts
   159  }
   160  
   161  func NewCFBEncrypterOpts(newCipher newCipher, keySize int) EncrypterOpts {
   162  	opts := new(CFBEncrypterOpts)
   163  	opts.encryptType = ENC_TYPE_CFB
   164  	opts.newCipher = newCipher
   165  	opts.cipherKeySize = keySize
   166  	return opts
   167  }
   168  
   169  // Encrypt encrypts the plaintext with the key, includes generated IV at the beginning of the ciphertext.
   170  func (opts *CFBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
   171  	block, err := opts.newCipher(key)
   172  	if err != nil {
   173  		return nil, err
   174  	}
   175  	blockSize := block.BlockSize()
   176  	ciphertext := make([]byte, blockSize+len(plaintext))
   177  	iv := ciphertext[:blockSize]
   178  	if _, err := io.ReadFull(rand, iv); err != nil {
   179  		return nil, err
   180  	}
   181  	stream := cipher.NewCFBEncrypter(block, iv)
   182  	stream.XORKeyStream(ciphertext[blockSize:], plaintext)
   183  	return ciphertext, nil
   184  }
   185  
   186  func (opts *CFBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
   187  	block, err := opts.newCipher(key)
   188  	if err != nil {
   189  		return nil, err
   190  	}
   191  	blockSize := block.BlockSize()
   192  	if len(ciphertext) <= blockSize {
   193  		return nil, ErrDecryption
   194  	}
   195  	iv := ciphertext[:blockSize]
   196  	ciphertext = ciphertext[blockSize:]
   197  	plaintext := make([]byte, len(ciphertext))
   198  	stream := cipher.NewCFBDecrypter(block, iv)
   199  	stream.XORKeyStream(plaintext, ciphertext)
   200  	return plaintext, nil
   201  }
   202  
   203  // OFBEncrypterOpts represents OFB (Output Feedback) mode.
   204  type OFBEncrypterOpts struct {
   205  	baseBlockEncrypterOpts
   206  }
   207  
   208  func NewOFBEncrypterOpts(newCipher newCipher, keySize int) EncrypterOpts {
   209  	opts := new(OFBEncrypterOpts)
   210  	opts.encryptType = ENC_TYPE_OFB
   211  	opts.newCipher = newCipher
   212  	opts.cipherKeySize = keySize
   213  	return opts
   214  }
   215  
   216  // Encrypt encrypts the plaintext with the key, includes generated IV at the beginning of the ciphertext.
   217  func (opts *OFBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
   218  	block, err := opts.newCipher(key)
   219  	if err != nil {
   220  		return nil, err
   221  	}
   222  	blockSize := block.BlockSize()
   223  	ciphertext := make([]byte, blockSize+len(plaintext))
   224  	iv := ciphertext[:blockSize]
   225  	if _, err := io.ReadFull(rand, iv); err != nil {
   226  		return nil, err
   227  	}
   228  	stream := cipher.NewOFB(block, iv)
   229  	stream.XORKeyStream(ciphertext[blockSize:], plaintext)
   230  	return ciphertext, nil
   231  }
   232  
   233  func (opts *OFBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
   234  	block, err := opts.newCipher(key)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	blockSize := block.BlockSize()
   239  	if len(ciphertext) <= blockSize {
   240  		return nil, ErrDecryption
   241  	}
   242  	iv := ciphertext[:blockSize]
   243  	ciphertext = ciphertext[blockSize:]
   244  	plaintext := make([]byte, len(ciphertext))
   245  	stream := cipher.NewOFB(block, iv)
   246  	stream.XORKeyStream(plaintext, ciphertext)
   247  	return plaintext, nil
   248  }
   249  
   250  // DefaultEncrypterOpts default option represents XOR mode
   251  var DefaultEncrypterOpts = new(XOREncrypterOpts)
   252  
   253  // SM4ECBEncrypterOpts option represents SM4 ECB mode
   254  var SM4ECBEncrypterOpts = NewECBEncrypterOpts(padding.NewPKCS7Padding(sm4.BlockSize), sm4.NewCipher, sm4.BlockSize)
   255  
   256  // SM4CBCEncrypterOpts option represents SM4 CBC mode
   257  var SM4CBCEncrypterOpts = NewCBCEncrypterOpts(padding.NewPKCS7Padding(sm4.BlockSize), sm4.NewCipher, sm4.BlockSize)
   258  
   259  // SM4CFBEncrypterOpts option represents SM4 CFB mode
   260  var SM4CFBEncrypterOpts = NewCFBEncrypterOpts(sm4.NewCipher, sm4.BlockSize)
   261  
   262  // SM4OFBEncrypterOpts option represents SM4 OFB mode
   263  var SM4OFBEncrypterOpts = NewOFBEncrypterOpts(sm4.NewCipher, sm4.BlockSize)
   264  
   265  func shangMiEncrypterOpts(encType encryptType) EncrypterOpts {
   266  	switch encType {
   267  	case ENC_TYPE_XOR:
   268  		return DefaultEncrypterOpts
   269  	case ENC_TYPE_CBC:
   270  		return SM4CBCEncrypterOpts
   271  	case ENC_TYPE_ECB:
   272  		return SM4ECBEncrypterOpts
   273  	case ENC_TYPE_CFB:
   274  		return SM4CFBEncrypterOpts
   275  	case ENC_TYPE_OFB:
   276  		return SM4OFBEncrypterOpts
   277  	}
   278  	return nil
   279  }