github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/sm4soft/sm4.go (about)

     1  // Copyright 2022 s1ren@github.com/hxx258456.
     2  
     3  /*
     4  sm4soft 是sm4的纯软实现,基于tjfoc国密算法库`tjfoc/gmsm`做了少量修改。
     5  对应版权声明: thrid_licenses/github.com/tjfoc/gmsm/版权声明
     6  */
     7  
     8  package sm4soft
     9  
    10  /*
    11  sm4soft/sm4.go SM4纯软实现
    12  */
    13  
    14  import (
    15  	"bytes"
    16  	"crypto/cipher"
    17  	"errors"
    18  	"strconv"
    19  )
    20  
    21  // BlockSize 分组长度 16字节
    22  const BlockSize = 16
    23  
    24  // IVDefault 默认初始化向量 IVDefault
    25  var IVDefault = make([]byte, BlockSize)
    26  
    27  // SM4Key sm4密钥
    28  type SM4Key []byte
    29  
    30  // Cipher is an instance of SM4 encryption.
    31  // Sm4Cipher sm4加密实例结构体
    32  type Sm4Cipher struct {
    33  	// 轮密钥 长度32的uint32切片,每个元素是32bit的integer,即一个word
    34  	subkeys []uint32
    35  	// 长度4的uint32切片,用来缓存将要被加解密的源字节数组转换而来的word切片
    36  	block1 []uint32
    37  	// 长度16的字节切片,用来缓存完成加解密之后word切片转换而来的字节切片
    38  	block2 []byte
    39  }
    40  
    41  // sm4密钥参量FK
    42  var fk = [4]uint32{
    43  	0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc,
    44  }
    45  
    46  // sm4密钥参量CK
    47  var ck = [32]uint32{
    48  	0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
    49  	0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
    50  	0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
    51  	0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
    52  	0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
    53  	0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
    54  	0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
    55  	0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,
    56  }
    57  
    58  // sm4密钥参量SBox
    59  var sbox = [256]uint8{
    60  	0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
    61  	0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
    62  	0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
    63  	0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
    64  	0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
    65  	0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
    66  	0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
    67  	0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
    68  	0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
    69  	0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
    70  	0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
    71  	0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
    72  	0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
    73  	0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
    74  	0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
    75  	0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
    76  }
    77  
    78  var sbox0 = [256]uint32{
    79  	0xd55b5b8e, 0x924242d0, 0xeaa7a74d, 0xfdfbfb06, 0xcf3333fc, 0xe2878765, 0x3df4f4c9, 0xb5dede6b, 0x1658584e, 0xb4dada6e, 0x14505044, 0xc10b0bca, 0x28a0a088, 0xf8efef17, 0x2cb0b09c, 0x05141411,
    80  	0x2bacac87, 0x669d9dfb, 0x986a6af2, 0x77d9d9ae, 0x2aa8a882, 0xbcfafa46, 0x04101014, 0xc00f0fcf, 0xa8aaaa02, 0x45111154, 0x134c4c5f, 0x269898be, 0x4825256d, 0x841a1a9e, 0x0618181e, 0x9b6666fd,
    81  	0x9e7272ec, 0x4309094a, 0x51414110, 0xf7d3d324, 0x934646d5, 0xecbfbf53, 0x9a6262f8, 0x7be9e992, 0x33ccccff, 0x55515104, 0x0b2c2c27, 0x420d0d4f, 0xeeb7b759, 0xcc3f3ff3, 0xaeb2b21c, 0x638989ea,
    82  	0xe7939374, 0xb1cece7f, 0x1c70706c, 0xaba6a60d, 0xca2727ed, 0x08202028, 0xeba3a348, 0x975656c1, 0x82020280, 0xdc7f7fa3, 0x965252c4, 0xf9ebeb12, 0x74d5d5a1, 0x8d3e3eb3, 0x3ffcfcc3, 0xa49a9a3e,
    83  	0x461d1d5b, 0x071c1c1b, 0xa59e9e3b, 0xfff3f30c, 0xf0cfcf3f, 0x72cdcdbf, 0x175c5c4b, 0xb8eaea52, 0x810e0e8f, 0x5865653d, 0x3cf0f0cc, 0x1964647d, 0xe59b9b7e, 0x87161691, 0x4e3d3d73, 0xaaa2a208,
    84  	0x69a1a1c8, 0x6aadadc7, 0x83060685, 0xb0caca7a, 0x70c5c5b5, 0x659191f4, 0xd96b6bb2, 0x892e2ea7, 0xfbe3e318, 0xe8afaf47, 0x0f3c3c33, 0x4a2d2d67, 0x71c1c1b0, 0x5759590e, 0x9f7676e9, 0x35d4d4e1,
    85  	0x1e787866, 0x249090b4, 0x0e383836, 0x5f797926, 0x628d8def, 0x59616138, 0xd2474795, 0xa08a8a2a, 0x259494b1, 0x228888aa, 0x7df1f18c, 0x3bececd7, 0x01040405, 0x218484a5, 0x79e1e198, 0x851e1e9b,
    86  	0xd7535384, 0x00000000, 0x4719195e, 0x565d5d0b, 0x9d7e7ee3, 0xd04f4f9f, 0x279c9cbb, 0x5349491a, 0x4d31317c, 0x36d8d8ee, 0x0208080a, 0xe49f9f7b, 0xa2828220, 0xc71313d4, 0xcb2323e8, 0x9c7a7ae6,
    87  	0xe9abab42, 0xbdfefe43, 0x882a2aa2, 0xd14b4b9a, 0x41010140, 0xc41f1fdb, 0x38e0e0d8, 0xb7d6d661, 0xa18e8e2f, 0xf4dfdf2b, 0xf1cbcb3a, 0xcd3b3bf6, 0xfae7e71d, 0x608585e5, 0x15545441, 0xa3868625,
    88  	0xe3838360, 0xacbaba16, 0x5c757529, 0xa6929234, 0x996e6ef7, 0x34d0d0e4, 0x1a686872, 0x54555501, 0xafb6b619, 0x914e4edf, 0x32c8c8fa, 0x30c0c0f0, 0xf6d7d721, 0x8e3232bc, 0xb3c6c675, 0xe08f8f6f,
    89  	0x1d747469, 0xf5dbdb2e, 0xe18b8b6a, 0x2eb8b896, 0x800a0a8a, 0x679999fe, 0xc92b2be2, 0x618181e0, 0xc30303c0, 0x29a4a48d, 0x238c8caf, 0xa9aeae07, 0x0d343439, 0x524d4d1f, 0x4f393976, 0x6ebdbdd3,
    90  	0xd6575781, 0xd86f6fb7, 0x37dcdceb, 0x44151551, 0xdd7b7ba6, 0xfef7f709, 0x8c3a3ab6, 0x2fbcbc93, 0x030c0c0f, 0xfcffff03, 0x6ba9a9c2, 0x73c9c9ba, 0x6cb5b5d9, 0x6db1b1dc, 0x5a6d6d37, 0x50454515,
    91  	0x8f3636b9, 0x1b6c6c77, 0xadbebe13, 0x904a4ada, 0xb9eeee57, 0xde7777a9, 0xbef2f24c, 0x7efdfd83, 0x11444455, 0xda6767bd, 0x5d71712c, 0x40050545, 0x1f7c7c63, 0x10404050, 0x5b696932, 0xdb6363b8,
    92  	0x0a282822, 0xc20707c5, 0x31c4c4f5, 0x8a2222a8, 0xa7969631, 0xce3737f9, 0x7aeded97, 0xbff6f649, 0x2db4b499, 0x75d1d1a4, 0xd3434390, 0x1248485a, 0xbae2e258, 0xe6979771, 0xb6d2d264, 0xb2c2c270,
    93  	0x8b2626ad, 0x68a5a5cd, 0x955e5ecb, 0x4b292962, 0x0c30303c, 0x945a5ace, 0x76ddddab, 0x7ff9f986, 0x649595f1, 0xbbe6e65d, 0xf2c7c735, 0x0924242d, 0xc61717d1, 0x6fb9b9d6, 0xc51b1bde, 0x86121294,
    94  	0x18606078, 0xf3c3c330, 0x7cf5f589, 0xefb3b35c, 0x3ae8e8d2, 0xdf7373ac, 0x4c353579, 0x208080a0, 0x78e5e59d, 0xedbbbb56, 0x5e7d7d23, 0x3ef8f8c6, 0xd45f5f8b, 0xc82f2fe7, 0x39e4e4dd, 0x49212168,
    95  }
    96  
    97  var sbox1 = [256]uint32{
    98  	0x5b5b8ed5, 0x4242d092, 0xa7a74dea, 0xfbfb06fd, 0x3333fccf, 0x878765e2, 0xf4f4c93d, 0xdede6bb5, 0x58584e16, 0xdada6eb4, 0x50504414, 0x0b0bcac1, 0xa0a08828, 0xefef17f8, 0xb0b09c2c, 0x14141105,
    99  	0xacac872b, 0x9d9dfb66, 0x6a6af298, 0xd9d9ae77, 0xa8a8822a, 0xfafa46bc, 0x10101404, 0x0f0fcfc0, 0xaaaa02a8, 0x11115445, 0x4c4c5f13, 0x9898be26, 0x25256d48, 0x1a1a9e84, 0x18181e06, 0x6666fd9b,
   100  	0x7272ec9e, 0x09094a43, 0x41411051, 0xd3d324f7, 0x4646d593, 0xbfbf53ec, 0x6262f89a, 0xe9e9927b, 0xccccff33, 0x51510455, 0x2c2c270b, 0x0d0d4f42, 0xb7b759ee, 0x3f3ff3cc, 0xb2b21cae, 0x8989ea63,
   101  	0x939374e7, 0xcece7fb1, 0x70706c1c, 0xa6a60dab, 0x2727edca, 0x20202808, 0xa3a348eb, 0x5656c197, 0x02028082, 0x7f7fa3dc, 0x5252c496, 0xebeb12f9, 0xd5d5a174, 0x3e3eb38d, 0xfcfcc33f, 0x9a9a3ea4,
   102  	0x1d1d5b46, 0x1c1c1b07, 0x9e9e3ba5, 0xf3f30cff, 0xcfcf3ff0, 0xcdcdbf72, 0x5c5c4b17, 0xeaea52b8, 0x0e0e8f81, 0x65653d58, 0xf0f0cc3c, 0x64647d19, 0x9b9b7ee5, 0x16169187, 0x3d3d734e, 0xa2a208aa,
   103  	0xa1a1c869, 0xadadc76a, 0x06068583, 0xcaca7ab0, 0xc5c5b570, 0x9191f465, 0x6b6bb2d9, 0x2e2ea789, 0xe3e318fb, 0xafaf47e8, 0x3c3c330f, 0x2d2d674a, 0xc1c1b071, 0x59590e57, 0x7676e99f, 0xd4d4e135,
   104  	0x7878661e, 0x9090b424, 0x3838360e, 0x7979265f, 0x8d8def62, 0x61613859, 0x474795d2, 0x8a8a2aa0, 0x9494b125, 0x8888aa22, 0xf1f18c7d, 0xececd73b, 0x04040501, 0x8484a521, 0xe1e19879, 0x1e1e9b85,
   105  	0x535384d7, 0x00000000, 0x19195e47, 0x5d5d0b56, 0x7e7ee39d, 0x4f4f9fd0, 0x9c9cbb27, 0x49491a53, 0x31317c4d, 0xd8d8ee36, 0x08080a02, 0x9f9f7be4, 0x828220a2, 0x1313d4c7, 0x2323e8cb, 0x7a7ae69c,
   106  	0xabab42e9, 0xfefe43bd, 0x2a2aa288, 0x4b4b9ad1, 0x01014041, 0x1f1fdbc4, 0xe0e0d838, 0xd6d661b7, 0x8e8e2fa1, 0xdfdf2bf4, 0xcbcb3af1, 0x3b3bf6cd, 0xe7e71dfa, 0x8585e560, 0x54544115, 0x868625a3,
   107  	0x838360e3, 0xbaba16ac, 0x7575295c, 0x929234a6, 0x6e6ef799, 0xd0d0e434, 0x6868721a, 0x55550154, 0xb6b619af, 0x4e4edf91, 0xc8c8fa32, 0xc0c0f030, 0xd7d721f6, 0x3232bc8e, 0xc6c675b3, 0x8f8f6fe0,
   108  	0x7474691d, 0xdbdb2ef5, 0x8b8b6ae1, 0xb8b8962e, 0x0a0a8a80, 0x9999fe67, 0x2b2be2c9, 0x8181e061, 0x0303c0c3, 0xa4a48d29, 0x8c8caf23, 0xaeae07a9, 0x3434390d, 0x4d4d1f52, 0x3939764f, 0xbdbdd36e,
   109  	0x575781d6, 0x6f6fb7d8, 0xdcdceb37, 0x15155144, 0x7b7ba6dd, 0xf7f709fe, 0x3a3ab68c, 0xbcbc932f, 0x0c0c0f03, 0xffff03fc, 0xa9a9c26b, 0xc9c9ba73, 0xb5b5d96c, 0xb1b1dc6d, 0x6d6d375a, 0x45451550,
   110  	0x3636b98f, 0x6c6c771b, 0xbebe13ad, 0x4a4ada90, 0xeeee57b9, 0x7777a9de, 0xf2f24cbe, 0xfdfd837e, 0x44445511, 0x6767bdda, 0x71712c5d, 0x05054540, 0x7c7c631f, 0x40405010, 0x6969325b, 0x6363b8db,
   111  	0x2828220a, 0x0707c5c2, 0xc4c4f531, 0x2222a88a, 0x969631a7, 0x3737f9ce, 0xeded977a, 0xf6f649bf, 0xb4b4992d, 0xd1d1a475, 0x434390d3, 0x48485a12, 0xe2e258ba, 0x979771e6, 0xd2d264b6, 0xc2c270b2,
   112  	0x2626ad8b, 0xa5a5cd68, 0x5e5ecb95, 0x2929624b, 0x30303c0c, 0x5a5ace94, 0xddddab76, 0xf9f9867f, 0x9595f164, 0xe6e65dbb, 0xc7c735f2, 0x24242d09, 0x1717d1c6, 0xb9b9d66f, 0x1b1bdec5, 0x12129486,
   113  	0x60607818, 0xc3c330f3, 0xf5f5897c, 0xb3b35cef, 0xe8e8d23a, 0x7373acdf, 0x3535794c, 0x8080a020, 0xe5e59d78, 0xbbbb56ed, 0x7d7d235e, 0xf8f8c63e, 0x5f5f8bd4, 0x2f2fe7c8, 0xe4e4dd39, 0x21216849,
   114  }
   115  
   116  var sbox2 = [256]uint32{
   117  	0x5b8ed55b, 0x42d09242, 0xa74deaa7, 0xfb06fdfb, 0x33fccf33, 0x8765e287, 0xf4c93df4, 0xde6bb5de, 0x584e1658, 0xda6eb4da, 0x50441450, 0x0bcac10b, 0xa08828a0, 0xef17f8ef, 0xb09c2cb0, 0x14110514,
   118  	0xac872bac, 0x9dfb669d, 0x6af2986a, 0xd9ae77d9, 0xa8822aa8, 0xfa46bcfa, 0x10140410, 0x0fcfc00f, 0xaa02a8aa, 0x11544511, 0x4c5f134c, 0x98be2698, 0x256d4825, 0x1a9e841a, 0x181e0618, 0x66fd9b66,
   119  	0x72ec9e72, 0x094a4309, 0x41105141, 0xd324f7d3, 0x46d59346, 0xbf53ecbf, 0x62f89a62, 0xe9927be9, 0xccff33cc, 0x51045551, 0x2c270b2c, 0x0d4f420d, 0xb759eeb7, 0x3ff3cc3f, 0xb21caeb2, 0x89ea6389,
   120  	0x9374e793, 0xce7fb1ce, 0x706c1c70, 0xa60daba6, 0x27edca27, 0x20280820, 0xa348eba3, 0x56c19756, 0x02808202, 0x7fa3dc7f, 0x52c49652, 0xeb12f9eb, 0xd5a174d5, 0x3eb38d3e, 0xfcc33ffc, 0x9a3ea49a,
   121  	0x1d5b461d, 0x1c1b071c, 0x9e3ba59e, 0xf30cfff3, 0xcf3ff0cf, 0xcdbf72cd, 0x5c4b175c, 0xea52b8ea, 0x0e8f810e, 0x653d5865, 0xf0cc3cf0, 0x647d1964, 0x9b7ee59b, 0x16918716, 0x3d734e3d, 0xa208aaa2,
   122  	0xa1c869a1, 0xadc76aad, 0x06858306, 0xca7ab0ca, 0xc5b570c5, 0x91f46591, 0x6bb2d96b, 0x2ea7892e, 0xe318fbe3, 0xaf47e8af, 0x3c330f3c, 0x2d674a2d, 0xc1b071c1, 0x590e5759, 0x76e99f76, 0xd4e135d4,
   123  	0x78661e78, 0x90b42490, 0x38360e38, 0x79265f79, 0x8def628d, 0x61385961, 0x4795d247, 0x8a2aa08a, 0x94b12594, 0x88aa2288, 0xf18c7df1, 0xecd73bec, 0x04050104, 0x84a52184, 0xe19879e1, 0x1e9b851e,
   124  	0x5384d753, 0x00000000, 0x195e4719, 0x5d0b565d, 0x7ee39d7e, 0x4f9fd04f, 0x9cbb279c, 0x491a5349, 0x317c4d31, 0xd8ee36d8, 0x080a0208, 0x9f7be49f, 0x8220a282, 0x13d4c713, 0x23e8cb23, 0x7ae69c7a,
   125  	0xab42e9ab, 0xfe43bdfe, 0x2aa2882a, 0x4b9ad14b, 0x01404101, 0x1fdbc41f, 0xe0d838e0, 0xd661b7d6, 0x8e2fa18e, 0xdf2bf4df, 0xcb3af1cb, 0x3bf6cd3b, 0xe71dfae7, 0x85e56085, 0x54411554, 0x8625a386,
   126  	0x8360e383, 0xba16acba, 0x75295c75, 0x9234a692, 0x6ef7996e, 0xd0e434d0, 0x68721a68, 0x55015455, 0xb619afb6, 0x4edf914e, 0xc8fa32c8, 0xc0f030c0, 0xd721f6d7, 0x32bc8e32, 0xc675b3c6, 0x8f6fe08f,
   127  	0x74691d74, 0xdb2ef5db, 0x8b6ae18b, 0xb8962eb8, 0x0a8a800a, 0x99fe6799, 0x2be2c92b, 0x81e06181, 0x03c0c303, 0xa48d29a4, 0x8caf238c, 0xae07a9ae, 0x34390d34, 0x4d1f524d, 0x39764f39, 0xbdd36ebd,
   128  	0x5781d657, 0x6fb7d86f, 0xdceb37dc, 0x15514415, 0x7ba6dd7b, 0xf709fef7, 0x3ab68c3a, 0xbc932fbc, 0x0c0f030c, 0xff03fcff, 0xa9c26ba9, 0xc9ba73c9, 0xb5d96cb5, 0xb1dc6db1, 0x6d375a6d, 0x45155045,
   129  	0x36b98f36, 0x6c771b6c, 0xbe13adbe, 0x4ada904a, 0xee57b9ee, 0x77a9de77, 0xf24cbef2, 0xfd837efd, 0x44551144, 0x67bdda67, 0x712c5d71, 0x05454005, 0x7c631f7c, 0x40501040, 0x69325b69, 0x63b8db63,
   130  	0x28220a28, 0x07c5c207, 0xc4f531c4, 0x22a88a22, 0x9631a796, 0x37f9ce37, 0xed977aed, 0xf649bff6, 0xb4992db4, 0xd1a475d1, 0x4390d343, 0x485a1248, 0xe258bae2, 0x9771e697, 0xd264b6d2, 0xc270b2c2,
   131  	0x26ad8b26, 0xa5cd68a5, 0x5ecb955e, 0x29624b29, 0x303c0c30, 0x5ace945a, 0xddab76dd, 0xf9867ff9, 0x95f16495, 0xe65dbbe6, 0xc735f2c7, 0x242d0924, 0x17d1c617, 0xb9d66fb9, 0x1bdec51b, 0x12948612,
   132  	0x60781860, 0xc330f3c3, 0xf5897cf5, 0xb35cefb3, 0xe8d23ae8, 0x73acdf73, 0x35794c35, 0x80a02080, 0xe59d78e5, 0xbb56edbb, 0x7d235e7d, 0xf8c63ef8, 0x5f8bd45f, 0x2fe7c82f, 0xe4dd39e4, 0x21684921,
   133  }
   134  
   135  var sbox3 = [256]uint32{
   136  	0x8ed55b5b, 0xd0924242, 0x4deaa7a7, 0x06fdfbfb, 0xfccf3333, 0x65e28787, 0xc93df4f4, 0x6bb5dede, 0x4e165858, 0x6eb4dada, 0x44145050, 0xcac10b0b, 0x8828a0a0, 0x17f8efef, 0x9c2cb0b0, 0x11051414,
   137  	0x872bacac, 0xfb669d9d, 0xf2986a6a, 0xae77d9d9, 0x822aa8a8, 0x46bcfafa, 0x14041010, 0xcfc00f0f, 0x02a8aaaa, 0x54451111, 0x5f134c4c, 0xbe269898, 0x6d482525, 0x9e841a1a, 0x1e061818, 0xfd9b6666,
   138  	0xec9e7272, 0x4a430909, 0x10514141, 0x24f7d3d3, 0xd5934646, 0x53ecbfbf, 0xf89a6262, 0x927be9e9, 0xff33cccc, 0x04555151, 0x270b2c2c, 0x4f420d0d, 0x59eeb7b7, 0xf3cc3f3f, 0x1caeb2b2, 0xea638989,
   139  	0x74e79393, 0x7fb1cece, 0x6c1c7070, 0x0daba6a6, 0xedca2727, 0x28082020, 0x48eba3a3, 0xc1975656, 0x80820202, 0xa3dc7f7f, 0xc4965252, 0x12f9ebeb, 0xa174d5d5, 0xb38d3e3e, 0xc33ffcfc, 0x3ea49a9a,
   140  	0x5b461d1d, 0x1b071c1c, 0x3ba59e9e, 0x0cfff3f3, 0x3ff0cfcf, 0xbf72cdcd, 0x4b175c5c, 0x52b8eaea, 0x8f810e0e, 0x3d586565, 0xcc3cf0f0, 0x7d196464, 0x7ee59b9b, 0x91871616, 0x734e3d3d, 0x08aaa2a2,
   141  	0xc869a1a1, 0xc76aadad, 0x85830606, 0x7ab0caca, 0xb570c5c5, 0xf4659191, 0xb2d96b6b, 0xa7892e2e, 0x18fbe3e3, 0x47e8afaf, 0x330f3c3c, 0x674a2d2d, 0xb071c1c1, 0x0e575959, 0xe99f7676, 0xe135d4d4,
   142  	0x661e7878, 0xb4249090, 0x360e3838, 0x265f7979, 0xef628d8d, 0x38596161, 0x95d24747, 0x2aa08a8a, 0xb1259494, 0xaa228888, 0x8c7df1f1, 0xd73becec, 0x05010404, 0xa5218484, 0x9879e1e1, 0x9b851e1e,
   143  	0x84d75353, 0x00000000, 0x5e471919, 0x0b565d5d, 0xe39d7e7e, 0x9fd04f4f, 0xbb279c9c, 0x1a534949, 0x7c4d3131, 0xee36d8d8, 0x0a020808, 0x7be49f9f, 0x20a28282, 0xd4c71313, 0xe8cb2323, 0xe69c7a7a,
   144  	0x42e9abab, 0x43bdfefe, 0xa2882a2a, 0x9ad14b4b, 0x40410101, 0xdbc41f1f, 0xd838e0e0, 0x61b7d6d6, 0x2fa18e8e, 0x2bf4dfdf, 0x3af1cbcb, 0xf6cd3b3b, 0x1dfae7e7, 0xe5608585, 0x41155454, 0x25a38686,
   145  	0x60e38383, 0x16acbaba, 0x295c7575, 0x34a69292, 0xf7996e6e, 0xe434d0d0, 0x721a6868, 0x01545555, 0x19afb6b6, 0xdf914e4e, 0xfa32c8c8, 0xf030c0c0, 0x21f6d7d7, 0xbc8e3232, 0x75b3c6c6, 0x6fe08f8f,
   146  	0x691d7474, 0x2ef5dbdb, 0x6ae18b8b, 0x962eb8b8, 0x8a800a0a, 0xfe679999, 0xe2c92b2b, 0xe0618181, 0xc0c30303, 0x8d29a4a4, 0xaf238c8c, 0x07a9aeae, 0x390d3434, 0x1f524d4d, 0x764f3939, 0xd36ebdbd,
   147  	0x81d65757, 0xb7d86f6f, 0xeb37dcdc, 0x51441515, 0xa6dd7b7b, 0x09fef7f7, 0xb68c3a3a, 0x932fbcbc, 0x0f030c0c, 0x03fcffff, 0xc26ba9a9, 0xba73c9c9, 0xd96cb5b5, 0xdc6db1b1, 0x375a6d6d, 0x15504545,
   148  	0xb98f3636, 0x771b6c6c, 0x13adbebe, 0xda904a4a, 0x57b9eeee, 0xa9de7777, 0x4cbef2f2, 0x837efdfd, 0x55114444, 0xbdda6767, 0x2c5d7171, 0x45400505, 0x631f7c7c, 0x50104040, 0x325b6969, 0xb8db6363,
   149  	0x220a2828, 0xc5c20707, 0xf531c4c4, 0xa88a2222, 0x31a79696, 0xf9ce3737, 0x977aeded, 0x49bff6f6, 0x992db4b4, 0xa475d1d1, 0x90d34343, 0x5a124848, 0x58bae2e2, 0x71e69797, 0x64b6d2d2, 0x70b2c2c2,
   150  	0xad8b2626, 0xcd68a5a5, 0xcb955e5e, 0x624b2929, 0x3c0c3030, 0xce945a5a, 0xab76dddd, 0x867ff9f9, 0xf1649595, 0x5dbbe6e6, 0x35f2c7c7, 0x2d092424, 0xd1c61717, 0xd66fb9b9, 0xdec51b1b, 0x94861212,
   151  	0x78186060, 0x30f3c3c3, 0x897cf5f5, 0x5cefb3b3, 0xd23ae8e8, 0xacdf7373, 0x794c3535, 0xa0208080, 0x9d78e5e5, 0x56edbbbb, 0x235e7d7d, 0xc63ef8f8, 0x8bd45f5f, 0xe7c82f2f, 0xdd39e4e4, 0x68492121,
   152  }
   153  
   154  // 对x做32位循环左移i位
   155  func rl(x uint32, i uint8) uint32 { return (x << (i % 32)) | (x >> (32 - (i % 32))) }
   156  
   157  // 密钥扩展用线性变换 L'
   158  func l0(b uint32) uint32 { return b ^ rl(b, 13) ^ rl(b, 23) }
   159  
   160  // 密钥扩展算法
   161  func feistel0(x0, x1, x2, x3, rk uint32) uint32 { return x0 ^ l0(p(x1^x2^x3^rk)) }
   162  
   163  // 非线性变换τ(.)
   164  func p(a uint32) uint32 {
   165  	return (uint32(sbox[a>>24]) << 24) ^ (uint32(sbox[(a>>16)&0xff]) << 16) ^ (uint32(sbox[(a>>8)&0xff]) << 8) ^ uint32(sbox[(a)&0xff])
   166  }
   167  
   168  // 将长度16的字节切片转为长度4的word切片
   169  func permuteInitialBlock(b []uint32, block []byte) {
   170  	// 将block分为4组,每组4个字节
   171  	// 经过计算,转换为长度为4的word切片
   172  	for i := 0; i < 4; i++ {
   173  		b[i] = (uint32(block[i*4]) << 24) | (uint32(block[i*4+1]) << 16) |
   174  			(uint32(block[i*4+2]) << 8) | (uint32(block[i*4+3]))
   175  	}
   176  }
   177  
   178  // 将长度4的word切片转为长度16的字节切片
   179  func permuteFinalBlock(b []byte, block []uint32) {
   180  	for i := 0; i < 4; i++ {
   181  		b[i*4] = uint8(block[i] >> 24)
   182  		b[i*4+1] = uint8(block[i] >> 16)
   183  		b[i*4+2] = uint8(block[i] >> 8)
   184  		b[i*4+3] = uint8(block[i])
   185  	}
   186  }
   187  
   188  // SM4分组加密核心函数
   189  // subkeys : 轮密钥 长度32,每个元素是一个32bit的word
   190  // b : 用来存放src转换而来的长度4的word切片
   191  // r : 用来存放加密/解密后转换而来的长度16的字节切片
   192  // dst : r的拷贝,用来返回加解密结果,长度16的字节切片
   193  // src : 将要进行加解密的字节切片,长度16
   194  // decrypt : 是否解密
   195  func cryptBlock(subkeys []uint32, b []uint32, r []byte, dst, src []byte, decrypt bool) {
   196  	// 将src转为word切片,长度4
   197  	permuteInitialBlock(b, src)
   198  
   199  	// bounds check elimination in major encryption loop
   200  	// https://go101.org/article/bounds-check-elimination.html
   201  	_ = b[3]
   202  	if decrypt {
   203  		// 解密
   204  		// 将轮密钥分为8轮执行解密,注意获取本轮密钥时顺序为逆序
   205  		// 每轮4个word,分别对src转换来的word切片进行解密。
   206  		for i := 0; i < 8; i++ {
   207  			s := subkeys[31-4*i-3 : 31-4*i-3+4]
   208  			x := b[1] ^ b[2] ^ b[3] ^ s[3]
   209  			b[0] = b[0] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
   210  			x = b[0] ^ b[2] ^ b[3] ^ s[2]
   211  			b[1] = b[1] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
   212  			x = b[0] ^ b[1] ^ b[3] ^ s[1]
   213  			b[2] = b[2] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
   214  			x = b[1] ^ b[2] ^ b[0] ^ s[0]
   215  			b[3] = b[3] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
   216  		}
   217  	} else {
   218  		// 加密
   219  		// 将轮密钥分为8轮执行加密,注意获取本轮密钥时顺序为正序
   220  		// 每轮4个word,分别对src转换来的word切片进行加密。
   221  		for i := 0; i < 8; i++ {
   222  			s := subkeys[4*i : 4*i+4]
   223  			x := b[1] ^ b[2] ^ b[3] ^ s[0]
   224  			b[0] = b[0] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
   225  			x = b[0] ^ b[2] ^ b[3] ^ s[1]
   226  			b[1] = b[1] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
   227  			x = b[0] ^ b[1] ^ b[3] ^ s[2]
   228  			b[2] = b[2] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
   229  			x = b[1] ^ b[2] ^ b[0] ^ s[3]
   230  			b[3] = b[3] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
   231  		}
   232  	}
   233  	// 倒序
   234  	b[0], b[1], b[2], b[3] = b[3], b[2], b[1], b[0]
   235  	// 将加密后的长度4的word切片转回长度16的字节切片
   236  	permuteFinalBlock(r, b)
   237  	// 结果拷贝到dist
   238  	copy(dst, r)
   239  }
   240  
   241  // 生成轮密钥 长度32的uint32切片 每个元素是一个32bit的integer,即word
   242  func generateSubKeys(key []byte) []uint32 {
   243  	subkeys := make([]uint32, 32)
   244  	b := make([]uint32, 4)
   245  	permuteInitialBlock(b, key)
   246  	b[0] ^= fk[0]
   247  	b[1] ^= fk[1]
   248  	b[2] ^= fk[2]
   249  	b[3] ^= fk[3]
   250  	for i := 0; i < 32; i++ {
   251  		subkeys[i] = feistel0(b[0], b[1], b[2], b[3], ck[i])
   252  		b[0], b[1], b[2], b[3] = b[1], b[2], b[3], subkeys[i]
   253  	}
   254  	return subkeys
   255  }
   256  
   257  // NewCipher creates and returns a new cipher.Block.
   258  func NewCipher(key []byte) (cipher.Block, error) {
   259  	if len(key) != BlockSize {
   260  		return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key)))
   261  	}
   262  	c := new(Sm4Cipher)
   263  	c.subkeys = generateSubKeys(key)
   264  	c.block1 = make([]uint32, 4)
   265  	c.block2 = make([]byte, 16)
   266  	return c, nil
   267  }
   268  
   269  // BlockSize 获取分组长度(字节数量)
   270  func (c *Sm4Cipher) BlockSize() int {
   271  	return BlockSize
   272  }
   273  
   274  // Encrypt 块加密
   275  func (c *Sm4Cipher) Encrypt(dst, src []byte) {
   276  	cryptBlock(c.subkeys, c.block1, c.block2, dst, src, false)
   277  }
   278  
   279  // Decrypt 块解密
   280  func (c *Sm4Cipher) Decrypt(dst, src []byte) {
   281  	cryptBlock(c.subkeys, c.block1, c.block2, dst, src, true)
   282  }
   283  
   284  // 异或处理
   285  //
   286  //	根据较短的入参,按字节单位异或
   287  func xor(in, iv []byte) (out []byte) {
   288  	n := len(in)
   289  	if len(iv) < n {
   290  		n = len(iv)
   291  	}
   292  	if n == 0 {
   293  		return nil
   294  	}
   295  	out = make([]byte, n)
   296  	for i := 0; i < n; i++ {
   297  		out[i] = in[i] ^ iv[i]
   298  	}
   299  	return
   300  }
   301  
   302  // 根据pkcs7标准填充明文
   303  func pkcs7Padding(src []byte) []byte {
   304  	padding := BlockSize - len(src)%BlockSize
   305  	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
   306  	return append(src, padtext...)
   307  }
   308  
   309  // 根据pkcs7标准去除填充
   310  func pkcs7UnPadding(src []byte) ([]byte, error) {
   311  	length := len(src)
   312  	if length == 0 {
   313  		return nil, errors.New("invalid pkcs7 padding (len(padtext) == 0)")
   314  	}
   315  	unpadding := int(src[length-1])
   316  	if unpadding > BlockSize || unpadding == 0 {
   317  		return nil, errors.New("invalid pkcs7 padding (unpadding > BlockSize || unpadding == 0)")
   318  	}
   319  
   320  	pad := src[len(src)-unpadding:]
   321  	for i := 0; i < unpadding; i++ {
   322  		if pad[i] != byte(unpadding) {
   323  			return nil, errors.New("invalid pkcs7 padding (pad[i] != unpadding)")
   324  		}
   325  	}
   326  
   327  	return src[:(length - unpadding)], nil
   328  }
   329  
   330  //goland:noinspection GoUnusedExportedFunction
   331  func SetIVDefault(iv []byte) error {
   332  	if len(iv) != BlockSize {
   333  		return errors.New("SM4: invalid iv size")
   334  	}
   335  	IVDefault = iv
   336  	return nil
   337  }
   338  
   339  // Sm4Ecb sm4加密(ECB模式),不需要IV,有PKCS#7填充
   340  func Sm4Ecb(key []byte, in []byte, encrypt bool) (out []byte, err error) {
   341  	if len(key) != BlockSize {
   342  		return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key)))
   343  	}
   344  	var inData []byte
   345  	if encrypt {
   346  		// 加密前填充明文
   347  		inData = pkcs7Padding(in)
   348  	} else {
   349  		inData = in
   350  	}
   351  	out = make([]byte, len(inData))
   352  	c, err := NewCipher(key)
   353  	if err != nil {
   354  		return nil, err
   355  	}
   356  	if encrypt {
   357  		// 加密
   358  		for i := 0; i < len(inData)/16; i++ {
   359  			inTmp := inData[i*16 : i*16+16]
   360  			outTmp := make([]byte, 16)
   361  			// 本组明文块加密
   362  			c.Encrypt(outTmp, inTmp)
   363  			copy(out[i*16:i*16+16], outTmp)
   364  		}
   365  	} else {
   366  		for i := 0; i < len(inData)/16; i++ {
   367  			inTmp := inData[i*16 : i*16+16]
   368  			outTmp := make([]byte, 16)
   369  			// 本组密文块解密
   370  			c.Decrypt(outTmp, inTmp)
   371  			copy(out[i*16:i*16+16], outTmp)
   372  		}
   373  		// 解密后去除填充
   374  		out, _ = pkcs7UnPadding(out)
   375  	}
   376  
   377  	return out, nil
   378  }
   379  
   380  // Sm4Cbc sm4加密(CBC模式),需要IV,有PKCS#7填充
   381  func Sm4Cbc(key []byte, iv []byte, in []byte, encrypt bool) (out []byte, err error) {
   382  	if len(key) != BlockSize {
   383  		return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key)))
   384  	}
   385  	if iv == nil {
   386  		iv = make([]byte, BlockSize)
   387  		copy(iv, IVDefault)
   388  	}
   389  	if len(iv) != BlockSize {
   390  		return nil, errors.New("SM4: invalid iv size " + strconv.Itoa(len(iv)))
   391  	}
   392  	var inData []byte
   393  	if encrypt {
   394  		// 加密前填充明文
   395  		inData = pkcs7Padding(in)
   396  	} else {
   397  		inData = in
   398  	}
   399  	// iv := make([]byte, BlockSize)
   400  	// copy(iv, IV)
   401  	out = make([]byte, len(inData))
   402  	c, err := NewCipher(key)
   403  	if err != nil {
   404  		return nil, err
   405  	}
   406  	if encrypt {
   407  		// 加密
   408  		for i := 0; i < len(inData)/16; i++ {
   409  			// 本组明文块和前一组密文块做异或运算
   410  			inTmp := xor(inData[i*16:i*16+16], iv)
   411  			outTmp := make([]byte, 16)
   412  			// 对异或结果做块加密
   413  			c.Encrypt(outTmp, inTmp)
   414  			copy(out[i*16:i*16+16], outTmp)
   415  			// 本组密文块作为下组块的异或运算参数
   416  			iv = outTmp
   417  		}
   418  	} else {
   419  		// 解密
   420  		for i := 0; i < len(inData)/16; i++ {
   421  			inTmp := inData[i*16 : i*16+16]
   422  			outTmp := make([]byte, 16)
   423  			// 对本组密文块做块解密
   424  			c.Decrypt(outTmp, inTmp)
   425  			// 本组块解密结果与前一组密文块做异或运算
   426  			outTmp = xor(outTmp, iv)
   427  			copy(out[i*16:i*16+16], outTmp)
   428  			// 本组密文块作为下组块的异或运算参数
   429  			iv = inTmp
   430  		}
   431  		// 解密后去除填充
   432  		out, _ = pkcs7UnPadding(out)
   433  	}
   434  
   435  	return out, nil
   436  }
   437  
   438  //密码反馈模式(Cipher FeedBack (CFB))
   439  //https://blog.csdn.net/zy_strive_2012/article/details/102520356
   440  //https://blog.csdn.net/sinat_23338865/article/details/72869841
   441  
   442  // Sm4CFB sm4加密(CFB模式),需要IV,没有PKCS#7填充
   443  func Sm4CFB(key []byte, iv []byte, in []byte, encrypt bool) (out []byte, err error) {
   444  	// 检查密钥长度
   445  	if len(key) != BlockSize {
   446  		return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key)))
   447  	}
   448  	// 如果没有传iv,就采用默认iv
   449  	if iv == nil {
   450  		iv = make([]byte, BlockSize)
   451  		copy(iv, IVDefault)
   452  	}
   453  	// 检查iv长度
   454  	if len(iv) != BlockSize {
   455  		return nil, errors.New("SM4: invalid iv size " + strconv.Itoa(len(iv)))
   456  	}
   457  	var inData = in
   458  	// 计算明文块长度
   459  	inLength := len(inData)
   460  	// 计算最后一个明文块的长度
   461  	lastBlockLen := inLength % BlockSize
   462  	// 计算明文块数量
   463  	blockCnt := inLength / BlockSize
   464  	if lastBlockLen > 0 {
   465  		blockCnt = blockCnt + 1
   466  	}
   467  	// 准备密文块数组
   468  	out = make([]byte, len(inData))
   469  	c, err := NewCipher(key)
   470  	if err != nil {
   471  		return nil, err
   472  	}
   473  	// 异或参数K
   474  	K := make([]byte, BlockSize)
   475  	if encrypt {
   476  		// 加密分支
   477  		// 当前密文块
   478  		cipherBlock := make([]byte, BlockSize)
   479  		for i := 0; i < blockCnt; i++ {
   480  			// 判断本次循环对应明文块的长度
   481  			curBlockSize := BlockSize
   482  			if i == blockCnt-1 {
   483  				curBlockSize = lastBlockLen
   484  			}
   485  			if i == 0 {
   486  				// 使用块加密计算首组异或参数K
   487  				c.Encrypt(K, iv)
   488  				// 本组明文块与本组异或参数K做异或运算得到本组密文块
   489  				cipherBlock = xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize])
   490  				copy(out[i*BlockSize:i*BlockSize+curBlockSize], cipherBlock)
   491  				continue
   492  			}
   493  			// 利用前一组密文块计算本组异或参数K
   494  			c.Encrypt(K, cipherBlock)
   495  			// 本组明文块与本组异或参数K做异或运算得到本组密文块
   496  			cipherBlock = xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize])
   497  			copy(out[i*BlockSize:i*BlockSize+curBlockSize], cipherBlock)
   498  		}
   499  	} else {
   500  		// 解密分支
   501  		var i = 0
   502  		for ; i < blockCnt; i++ {
   503  			// 判断本次循环对应密文块的长度
   504  			curBlockSize := BlockSize
   505  			if i == blockCnt-1 {
   506  				curBlockSize = lastBlockLen
   507  			}
   508  			if i == 0 {
   509  				// 使用块加密计算首组异或参数K
   510  				c.Encrypt(K, iv)
   511  				// 本组密文块与本组异或参数K做异或运算得到本组明文块
   512  				plainBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize])
   513  				copy(out[i*BlockSize:i*BlockSize+curBlockSize], plainBlock)
   514  				continue
   515  			}
   516  			// 利用前一组密文块计算本组异或参数K
   517  			c.Encrypt(K, inData[(i-1)*BlockSize:i*BlockSize])
   518  			// 本组密文块与本组异或参数K做异或运算得到本组明文块
   519  			plainBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize])
   520  			copy(out[i*BlockSize:i*BlockSize+curBlockSize], plainBlock)
   521  		}
   522  	}
   523  
   524  	return out, nil
   525  }
   526  
   527  //输出反馈模式(Output feedback, OFB)
   528  //https://blog.csdn.net/chengqiuming/article/details/82390910
   529  //https://blog.csdn.net/sinat_23338865/article/details/72869841
   530  
   531  // Sm4OFB sm4加密(OFB模式),需要IV,没有PKCS#7填充
   532  func Sm4OFB(key []byte, iv []byte, in []byte, encrypt bool) (out []byte, err error) {
   533  	if len(key) != BlockSize {
   534  		return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key)))
   535  	}
   536  	if iv == nil {
   537  		iv = make([]byte, BlockSize)
   538  		copy(iv, IVDefault)
   539  	}
   540  	if len(iv) != BlockSize {
   541  		return nil, errors.New("SM4: invalid iv size " + strconv.Itoa(len(iv)))
   542  	}
   543  	var inData = in
   544  	// 计算明文块长度
   545  	inLength := len(inData)
   546  	// 计算最后一个明文块的长度
   547  	lastBlockLen := inLength % BlockSize
   548  	// 计算明文块数量
   549  	blockCnt := inLength / BlockSize
   550  	if lastBlockLen > 0 {
   551  		blockCnt = blockCnt + 1
   552  	}
   553  
   554  	out = make([]byte, len(inData))
   555  	c, err := NewCipher(key)
   556  	if err != nil {
   557  		return nil, err
   558  	}
   559  
   560  	K := make([]byte, BlockSize)
   561  	shiftIV := make([]byte, BlockSize)
   562  	if encrypt {
   563  		// 加密
   564  		for i := 0; i < blockCnt; i++ {
   565  			// 判断本次循环对应明文块的长度
   566  			curBlockSize := BlockSize
   567  			if i == blockCnt-1 {
   568  				curBlockSize = lastBlockLen
   569  			}
   570  			if i == 0 {
   571  				// 使用块加密计算首组异或参数K
   572  				c.Encrypt(K, iv)
   573  				// 本组明文与异或参数K做异或运算
   574  				cipherBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize])
   575  				copy(out[i*BlockSize:i*BlockSize+curBlockSize], cipherBlock)
   576  				// 本组异或参数K作为下一组块加密参数
   577  				copy(shiftIV, K[:BlockSize])
   578  				continue
   579  			}
   580  			// 使用块加密,利用前一组异或参数计算本组异或参数K
   581  			c.Encrypt(K, shiftIV)
   582  			// 本组明文与异或参数K做异或运算
   583  			cipherBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize])
   584  			copy(out[i*BlockSize:i*BlockSize+curBlockSize], cipherBlock)
   585  			// 本组异或参数K作为下一组块加密参数
   586  			copy(shiftIV, K[:BlockSize])
   587  		}
   588  	} else {
   589  		// 解密
   590  		for i := 0; i < blockCnt; i++ {
   591  			// 判断本次循环对应密文块的长度
   592  			curBlockSize := BlockSize
   593  			if i == blockCnt-1 {
   594  				curBlockSize = lastBlockLen
   595  			}
   596  			if i == 0 {
   597  				// 使用块加密计算首组异或参数K
   598  				c.Encrypt(K, iv)
   599  				// 本组密文与异或参数K做异或运算
   600  				plainBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize])
   601  				copy(out[i*BlockSize:i*BlockSize+curBlockSize], plainBlock)
   602  				// 本组异或参数K作为下一组块加密参数
   603  				copy(shiftIV, K[:BlockSize])
   604  				continue
   605  			}
   606  			// 使用块加密,利用前一组异或参数计算本组异或参数K
   607  			c.Encrypt(K, shiftIV)
   608  			// 本组密文与异或参数K做异或运算
   609  			plainBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize])
   610  			copy(out[i*BlockSize:i*BlockSize+curBlockSize], plainBlock)
   611  			// 本组异或参数K作为下一组块加密参数
   612  			copy(shiftIV, K[:BlockSize])
   613  		}
   614  	}
   615  
   616  	return out, nil
   617  }
   618  
   619  // EncryptBlock 分组加密
   620  //
   621  //goland:noinspection GoUnusedExportedFunction
   622  func EncryptBlock(key SM4Key, dst, src []byte) {
   623  	subkeys := generateSubKeys(key)
   624  	cryptBlock(subkeys, make([]uint32, 4), make([]byte, 16), dst, src, false)
   625  }
   626  
   627  // DecryptBlock 分组解密
   628  //
   629  //goland:noinspection GoUnusedExportedFunction
   630  func DecryptBlock(key SM4Key, dst, src []byte) {
   631  	subkeys := generateSubKeys(key)
   632  	cryptBlock(subkeys, make([]uint32, 4), make([]byte, 16), dst, src, true)
   633  }