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