github.com/Hyperledger-TWGC/tjfoc-gm@v1.4.0/sm4/sm4.go (about)

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