gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/sm4soft/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 /* 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 // 根据较短的入参,按字节单位异或 292 func xor(in, iv []byte) (out []byte) { 293 n := len(in) 294 if len(iv) < n { 295 n = len(iv) 296 } 297 if n == 0 { 298 return nil 299 } 300 out = make([]byte, n) 301 for i := 0; i < n; i++ { 302 out[i] = in[i] ^ iv[i] 303 } 304 return 305 } 306 307 // 根据pkcs7标准填充明文 308 func pkcs7Padding(src []byte) []byte { 309 padding := BlockSize - len(src)%BlockSize 310 padtext := bytes.Repeat([]byte{byte(padding)}, padding) 311 return append(src, padtext...) 312 } 313 314 // 根据pkcs7标准去除填充 315 func pkcs7UnPadding(src []byte) ([]byte, error) { 316 length := len(src) 317 if length == 0 { 318 return nil, errors.New("invalid pkcs7 padding (len(padtext) == 0)") 319 } 320 unpadding := int(src[length-1]) 321 if unpadding > BlockSize || unpadding == 0 { 322 return nil, errors.New("invalid pkcs7 padding (unpadding > BlockSize || unpadding == 0)") 323 } 324 325 pad := src[len(src)-unpadding:] 326 for i := 0; i < unpadding; i++ { 327 if pad[i] != byte(unpadding) { 328 return nil, errors.New("invalid pkcs7 padding (pad[i] != unpadding)") 329 } 330 } 331 332 return src[:(length - unpadding)], nil 333 } 334 335 //goland:noinspection GoUnusedExportedFunction 336 func SetIVDefault(iv []byte) error { 337 if len(iv) != BlockSize { 338 return errors.New("SM4: invalid iv size") 339 } 340 IVDefault = iv 341 return nil 342 } 343 344 // Sm4Ecb sm4加密(ECB模式),不需要IV,有PKCS#7填充 345 func Sm4Ecb(key []byte, in []byte, encrypt bool) (out []byte, err error) { 346 if len(key) != BlockSize { 347 return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) 348 } 349 var inData []byte 350 if encrypt { 351 // 加密前填充明文 352 inData = pkcs7Padding(in) 353 } else { 354 inData = in 355 } 356 out = make([]byte, len(inData)) 357 c, err := NewCipher(key) 358 if err != nil { 359 return nil, err 360 } 361 if encrypt { 362 // 加密 363 for i := 0; i < len(inData)/16; i++ { 364 inTmp := inData[i*16 : i*16+16] 365 outTmp := make([]byte, 16) 366 // 本组明文块加密 367 c.Encrypt(outTmp, inTmp) 368 copy(out[i*16:i*16+16], outTmp) 369 } 370 } else { 371 for i := 0; i < len(inData)/16; i++ { 372 inTmp := inData[i*16 : i*16+16] 373 outTmp := make([]byte, 16) 374 // 本组密文块解密 375 c.Decrypt(outTmp, inTmp) 376 copy(out[i*16:i*16+16], outTmp) 377 } 378 // 解密后去除填充 379 out, _ = pkcs7UnPadding(out) 380 } 381 382 return out, nil 383 } 384 385 // Sm4Cbc sm4加密(CBC模式),需要IV,有PKCS#7填充 386 func Sm4Cbc(key []byte, iv []byte, in []byte, encrypt bool) (out []byte, err error) { 387 if len(key) != BlockSize { 388 return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) 389 } 390 if iv == nil { 391 iv = make([]byte, BlockSize) 392 copy(iv, IVDefault) 393 } 394 if len(iv) != BlockSize { 395 return nil, errors.New("SM4: invalid iv size " + strconv.Itoa(len(iv))) 396 } 397 var inData []byte 398 if encrypt { 399 // 加密前填充明文 400 inData = pkcs7Padding(in) 401 } else { 402 inData = in 403 } 404 // iv := make([]byte, BlockSize) 405 // copy(iv, IV) 406 out = make([]byte, len(inData)) 407 c, err := NewCipher(key) 408 if err != nil { 409 return nil, err 410 } 411 if encrypt { 412 // 加密 413 for i := 0; i < len(inData)/16; i++ { 414 // 本组明文块和前一组密文块做异或运算 415 inTmp := xor(inData[i*16:i*16+16], iv) 416 outTmp := make([]byte, 16) 417 // 对异或结果做块加密 418 c.Encrypt(outTmp, inTmp) 419 copy(out[i*16:i*16+16], outTmp) 420 // 本组密文块作为下组块的异或运算参数 421 iv = outTmp 422 } 423 } else { 424 // 解密 425 for i := 0; i < len(inData)/16; i++ { 426 inTmp := inData[i*16 : i*16+16] 427 outTmp := make([]byte, 16) 428 // 对本组密文块做块解密 429 c.Decrypt(outTmp, inTmp) 430 // 本组块解密结果与前一组密文块做异或运算 431 outTmp = xor(outTmp, iv) 432 copy(out[i*16:i*16+16], outTmp) 433 // 本组密文块作为下组块的异或运算参数 434 iv = inTmp 435 } 436 // 解密后去除填充 437 out, _ = pkcs7UnPadding(out) 438 } 439 440 return out, nil 441 } 442 443 //密码反馈模式(Cipher FeedBack (CFB)) 444 //https://blog.csdn.net/zy_strive_2012/article/details/102520356 445 //https://blog.csdn.net/sinat_23338865/article/details/72869841 446 447 // Sm4CFB sm4加密(CFB模式),需要IV,没有PKCS#7填充 448 func Sm4CFB(key []byte, iv []byte, in []byte, encrypt bool) (out []byte, err error) { 449 // 检查密钥长度 450 if len(key) != BlockSize { 451 return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) 452 } 453 // 如果没有传iv,就采用默认iv 454 if iv == nil { 455 iv = make([]byte, BlockSize) 456 copy(iv, IVDefault) 457 } 458 // 检查iv长度 459 if len(iv) != BlockSize { 460 return nil, errors.New("SM4: invalid iv size " + strconv.Itoa(len(iv))) 461 } 462 var inData = in 463 // 计算明文块长度 464 inLength := len(inData) 465 // 计算最后一个明文块的长度 466 lastBlockLen := inLength % BlockSize 467 // 计算明文块数量 468 blockCnt := inLength / BlockSize 469 if lastBlockLen > 0 { 470 blockCnt = blockCnt + 1 471 } 472 // 准备密文块数组 473 out = make([]byte, len(inData)) 474 c, err := NewCipher(key) 475 if err != nil { 476 return nil, err 477 } 478 // 异或参数K 479 K := make([]byte, BlockSize) 480 if encrypt { 481 // 加密分支 482 // 当前密文块 483 cipherBlock := make([]byte, BlockSize) 484 for i := 0; i < blockCnt; i++ { 485 // 判断本次循环对应明文块的长度 486 curBlockSize := BlockSize 487 if i == blockCnt-1 { 488 curBlockSize = lastBlockLen 489 } 490 if i == 0 { 491 // 使用块加密计算首组异或参数K 492 c.Encrypt(K, iv) 493 // 本组明文块与本组异或参数K做异或运算得到本组密文块 494 cipherBlock = xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize]) 495 copy(out[i*BlockSize:i*BlockSize+curBlockSize], cipherBlock) 496 continue 497 } 498 // 利用前一组密文块计算本组异或参数K 499 c.Encrypt(K, cipherBlock) 500 // 本组明文块与本组异或参数K做异或运算得到本组密文块 501 cipherBlock = xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize]) 502 copy(out[i*BlockSize:i*BlockSize+curBlockSize], cipherBlock) 503 } 504 } else { 505 // 解密分支 506 var i = 0 507 for ; i < blockCnt; i++ { 508 // 判断本次循环对应密文块的长度 509 curBlockSize := BlockSize 510 if i == blockCnt-1 { 511 curBlockSize = lastBlockLen 512 } 513 if i == 0 { 514 // 使用块加密计算首组异或参数K 515 c.Encrypt(K, iv) 516 // 本组密文块与本组异或参数K做异或运算得到本组明文块 517 plainBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize]) 518 copy(out[i*BlockSize:i*BlockSize+curBlockSize], plainBlock) 519 continue 520 } 521 // 利用前一组密文块计算本组异或参数K 522 c.Encrypt(K, inData[(i-1)*BlockSize:i*BlockSize]) 523 // 本组密文块与本组异或参数K做异或运算得到本组明文块 524 plainBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize]) 525 copy(out[i*BlockSize:i*BlockSize+curBlockSize], plainBlock) 526 } 527 } 528 529 return out, nil 530 } 531 532 //输出反馈模式(Output feedback, OFB) 533 //https://blog.csdn.net/chengqiuming/article/details/82390910 534 //https://blog.csdn.net/sinat_23338865/article/details/72869841 535 536 // Sm4OFB sm4加密(OFB模式),需要IV,没有PKCS#7填充 537 func Sm4OFB(key []byte, iv []byte, in []byte, encrypt bool) (out []byte, err error) { 538 if len(key) != BlockSize { 539 return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) 540 } 541 if iv == nil { 542 iv = make([]byte, BlockSize) 543 copy(iv, IVDefault) 544 } 545 if len(iv) != BlockSize { 546 return nil, errors.New("SM4: invalid iv size " + strconv.Itoa(len(iv))) 547 } 548 var inData = in 549 // 计算明文块长度 550 inLength := len(inData) 551 // 计算最后一个明文块的长度 552 lastBlockLen := inLength % BlockSize 553 // 计算明文块数量 554 blockCnt := inLength / BlockSize 555 if lastBlockLen > 0 { 556 blockCnt = blockCnt + 1 557 } 558 559 out = make([]byte, len(inData)) 560 c, err := NewCipher(key) 561 if err != nil { 562 return nil, err 563 } 564 565 K := make([]byte, BlockSize) 566 shiftIV := make([]byte, BlockSize) 567 if encrypt { 568 // 加密 569 for i := 0; i < blockCnt; i++ { 570 // 判断本次循环对应明文块的长度 571 curBlockSize := BlockSize 572 if i == blockCnt-1 { 573 curBlockSize = lastBlockLen 574 } 575 if i == 0 { 576 // 使用块加密计算首组异或参数K 577 c.Encrypt(K, iv) 578 // 本组明文与异或参数K做异或运算 579 cipherBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize]) 580 copy(out[i*BlockSize:i*BlockSize+curBlockSize], cipherBlock) 581 // 本组异或参数K作为下一组块加密参数 582 copy(shiftIV, K[:BlockSize]) 583 continue 584 } 585 // 使用块加密,利用前一组异或参数计算本组异或参数K 586 c.Encrypt(K, shiftIV) 587 // 本组明文与异或参数K做异或运算 588 cipherBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize]) 589 copy(out[i*BlockSize:i*BlockSize+curBlockSize], cipherBlock) 590 // 本组异或参数K作为下一组块加密参数 591 copy(shiftIV, K[:BlockSize]) 592 } 593 } else { 594 // 解密 595 for i := 0; i < blockCnt; i++ { 596 // 判断本次循环对应密文块的长度 597 curBlockSize := BlockSize 598 if i == blockCnt-1 { 599 curBlockSize = lastBlockLen 600 } 601 if i == 0 { 602 // 使用块加密计算首组异或参数K 603 c.Encrypt(K, iv) 604 // 本组密文与异或参数K做异或运算 605 plainBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize]) 606 copy(out[i*BlockSize:i*BlockSize+curBlockSize], plainBlock) 607 // 本组异或参数K作为下一组块加密参数 608 copy(shiftIV, K[:BlockSize]) 609 continue 610 } 611 // 使用块加密,利用前一组异或参数计算本组异或参数K 612 c.Encrypt(K, shiftIV) 613 // 本组密文与异或参数K做异或运算 614 plainBlock := xor(K[:BlockSize], inData[i*BlockSize:i*BlockSize+curBlockSize]) 615 copy(out[i*BlockSize:i*BlockSize+curBlockSize], plainBlock) 616 // 本组异或参数K作为下一组块加密参数 617 copy(shiftIV, K[:BlockSize]) 618 } 619 } 620 621 return out, nil 622 } 623 624 // EncryptBlock 分组加密 625 // 626 //goland:noinspection GoUnusedExportedFunction 627 func EncryptBlock(key SM4Key, dst, src []byte) { 628 subkeys := generateSubKeys(key) 629 cryptBlock(subkeys, make([]uint32, 4), make([]byte, 16), dst, src, false) 630 } 631 632 // DecryptBlock 分组解密 633 // 634 //goland:noinspection GoUnusedExportedFunction 635 func DecryptBlock(key SM4Key, dst, src []byte) { 636 subkeys := generateSubKeys(key) 637 cryptBlock(subkeys, make([]uint32, 4), make([]byte, 16), dst, src, true) 638 }