gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/sm4/sm4.go (about)

     1  // Copyright (c) 2022 zhaochun
     2  // core-gm is licensed under Mulan PSL v2.
     3  // You can use this software according to the terms and conditions of the Mulan PSL v2.
     4  // You may obtain a copy of Mulan PSL v2 at:
     5  //          http://license.coscl.org.cn/MulanPSL2
     6  // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
     7  // See the Mulan PSL v2 for more details.
     8  
     9  package sm4
    10  
    11  import (
    12  	"crypto/cipher"
    13  	"crypto/rand"
    14  	"fmt"
    15  	"gitee.com/ks-custle/core-gm/utils"
    16  	"io"
    17  )
    18  
    19  // Sm4EncryptCbc sm4加密,CBC模式
    20  //
    21  //goland:noinspection GoNameStartsWithPackageName
    22  func Sm4EncryptCbc(plainData, key []byte) (iv, encryptData []byte, err error) {
    23  	block, err := NewCipher(key)
    24  	if err != nil {
    25  		return nil, nil, err
    26  	}
    27  	paddedData := utils.PKCS7Padding(plainData, BlockSize)
    28  	encryptData = make([]byte, len(paddedData))
    29  	iv = make([]byte, BlockSize)
    30  	if _, err = io.ReadFull(rand.Reader, iv); err != nil {
    31  		return nil, nil, err
    32  	}
    33  	mode := cipher.NewCBCEncrypter(block, iv)
    34  	mode.CryptBlocks(encryptData, paddedData)
    35  	return
    36  }
    37  
    38  // Sm4DecryptCbc sm4解密,CBC模式
    39  //
    40  //goland:noinspection GoNameStartsWithPackageName
    41  func Sm4DecryptCbc(encryptData, key, iv []byte) (plainData []byte, err error) {
    42  	block, err := NewCipher(key)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  	// 长度检查
    47  	length := len(encryptData)
    48  	if length < BlockSize || length%BlockSize != 0 {
    49  		return nil, fmt.Errorf("sm4.Sm4DecryptCbc: 密文长度不正确,不是Block字节数的整数倍. Block字节数: [%d]", BlockSize)
    50  	}
    51  	paddedData := make([]byte, len(encryptData))
    52  	mode := cipher.NewCBCDecrypter(block, iv)
    53  	mode.CryptBlocks(paddedData, encryptData)
    54  	plainData, err = utils.PKCS7UnPadding(paddedData, BlockSize)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	return
    59  }
    60  
    61  // Sm4EncryptCfb sm4加密,CFB模式
    62  //
    63  //goland:noinspection GoNameStartsWithPackageName
    64  func Sm4EncryptCfb(plainData, key []byte) (iv, encryptData []byte, err error) {
    65  	block, err := NewCipher(key)
    66  	if err != nil {
    67  		return nil, nil, err
    68  	}
    69  	encryptData = make([]byte, len(plainData))
    70  	iv = make([]byte, BlockSize)
    71  	if _, err = io.ReadFull(rand.Reader, iv); err != nil {
    72  		return nil, nil, err
    73  	}
    74  	mode := cipher.NewCFBEncrypter(block, iv)
    75  	mode.XORKeyStream(encryptData, plainData)
    76  	return
    77  }
    78  
    79  // Sm4DecryptCfb sm4解密,CFB模式
    80  //
    81  //goland:noinspection GoNameStartsWithPackageName
    82  func Sm4DecryptCfb(encryptData, key, iv []byte) (plainData []byte, err error) {
    83  	block, err := NewCipher(key)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	plainData = make([]byte, len(encryptData))
    88  	mode := cipher.NewCFBDecrypter(block, iv)
    89  	mode.XORKeyStream(plainData, encryptData)
    90  	return
    91  }
    92  
    93  // Sm4EncryptOfb sm4加密,OFB模式
    94  //
    95  //goland:noinspection GoNameStartsWithPackageName
    96  func Sm4EncryptOfb(plainData, key []byte) (iv, encryptData []byte, err error) {
    97  	block, err := NewCipher(key)
    98  	if err != nil {
    99  		return nil, nil, err
   100  	}
   101  	encryptData = make([]byte, len(plainData))
   102  	iv = make([]byte, BlockSize)
   103  	if _, err = io.ReadFull(rand.Reader, iv); err != nil {
   104  		return nil, nil, err
   105  	}
   106  	mode := cipher.NewOFB(block, iv)
   107  	mode.XORKeyStream(encryptData, plainData)
   108  	return
   109  }
   110  
   111  // Sm4DecryptOfb sm4解密,OFB模式
   112  //
   113  //goland:noinspection GoNameStartsWithPackageName
   114  func Sm4DecryptOfb(encryptData, key, iv []byte) (plainData []byte, err error) {
   115  	block, err := NewCipher(key)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	plainData = make([]byte, len(encryptData))
   120  	mode := cipher.NewOFB(block, iv)
   121  	mode.XORKeyStream(plainData, encryptData)
   122  	return
   123  }
   124  
   125  // Sm4EncryptGcm sm4加密,GCM模式
   126  //
   127  //goland:noinspection GoNameStartsWithPackageName
   128  func Sm4EncryptGcm(plainData, key []byte) (nonce, encryptData []byte, err error) {
   129  	block, err := NewCipher(key)
   130  	if err != nil {
   131  		return nil, nil, err
   132  	}
   133  	sm4gcm, err := cipher.NewGCM(block)
   134  	if err != nil {
   135  		return nil, nil, err
   136  	}
   137  	nonce = make([]byte, sm4gcm.NonceSize())
   138  	_, err = io.ReadFull(rand.Reader, nonce)
   139  	if err != nil {
   140  		return nil, nil, err
   141  	}
   142  	encryptData = sm4gcm.Seal(nil, nonce, plainData, nil)
   143  	return
   144  }
   145  
   146  // Sm4DecryptGcm sm4解密,GCM模式
   147  //
   148  //goland:noinspection GoNameStartsWithPackageName
   149  func Sm4DecryptGcm(encryptData, key, nonce []byte) ([]byte, error) {
   150  	block, err := NewCipher(key)
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  	sm4gcm, err := cipher.NewGCM(block)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	// nonce, ciphertext := data[:sm4gcm.NonceSize()], data[sm4gcm.NonceSize():]
   159  	out, err := sm4gcm.Open(nil, nonce, encryptData, nil)
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  	return out, nil
   164  }
   165  
   166  // Sm4EncryptGcmWithNonce sm4加密,GCM模式
   167  //
   168  //goland:noinspection GoNameStartsWithPackageName
   169  func Sm4EncryptGcmWithNonce(plainData, key, nonce, dst []byte) (encryptData []byte, err error) {
   170  	block, err := NewCipher(key)
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  	sm4gcm, err := cipher.NewGCM(block)
   175  	if err != nil {
   176  		return nil, err
   177  	}
   178  	out := sm4gcm.Seal(dst, nonce, plainData, dst)
   179  	encryptData = out[len(dst):]
   180  	return
   181  }
   182  
   183  // Sm4DecryptGcmWithNonce sm4解密,GCM模式
   184  //
   185  //goland:noinspection GoNameStartsWithPackageName
   186  func Sm4DecryptGcmWithNonce(encryptData, key, nonce, dst []byte) ([]byte, error) {
   187  	block, err := NewCipher(key)
   188  	if err != nil {
   189  		return nil, err
   190  	}
   191  	sm4gcm, err := cipher.NewGCM(block)
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  	out, err := sm4gcm.Open(encryptData[:0], nonce, encryptData, dst)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  	return out, nil
   200  }