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 }