github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/sm4/block.go (about) 1 package sm4 2 3 // [GM/T] SM4 GB/T 32907-2016 4 5 import ( 6 "encoding/binary" 7 "math/bits" 8 ) 9 10 /* 11 sm4/block.go sm4块加密与块解密 12 */ 13 14 type convert func(uint32) uint32 15 16 // sm4块加密 17 // 18 // Encrypt one block from src into dst, using the expanded key xk. 19 func encryptBlockGo(xk []uint32, dst, src []byte) { 20 _ = src[15] // early bounds check 21 _ = dst[15] // early bounds check 22 var b0, b1, b2, b3 uint32 23 // 切分明文块,获取4个字 24 b0 = binary.BigEndian.Uint32(src[0:4]) 25 b1 = binary.BigEndian.Uint32(src[4:8]) 26 b2 = binary.BigEndian.Uint32(src[8:12]) 27 b3 = binary.BigEndian.Uint32(src[12:16]) 28 // 1~4轮 29 b0 ^= t(b1 ^ b2 ^ b3 ^ xk[0]) 30 b1 ^= t(b2 ^ b3 ^ b0 ^ xk[1]) 31 b2 ^= t(b3 ^ b0 ^ b1 ^ xk[2]) 32 b3 ^= t(b0 ^ b1 ^ b2 ^ xk[3]) 33 // 5~8轮 34 b0 ^= precomputeT(b1 ^ b2 ^ b3 ^ xk[4]) 35 b1 ^= precomputeT(b2 ^ b3 ^ b0 ^ xk[5]) 36 b2 ^= precomputeT(b3 ^ b0 ^ b1 ^ xk[6]) 37 b3 ^= precomputeT(b0 ^ b1 ^ b2 ^ xk[7]) 38 // 9~12轮 39 b0 ^= precomputeT(b1 ^ b2 ^ b3 ^ xk[8]) 40 b1 ^= precomputeT(b2 ^ b3 ^ b0 ^ xk[9]) 41 b2 ^= precomputeT(b3 ^ b0 ^ b1 ^ xk[10]) 42 b3 ^= precomputeT(b0 ^ b1 ^ b2 ^ xk[11]) 43 // 13~16轮 44 b0 ^= precomputeT(b1 ^ b2 ^ b3 ^ xk[12]) 45 b1 ^= precomputeT(b2 ^ b3 ^ b0 ^ xk[13]) 46 b2 ^= precomputeT(b3 ^ b0 ^ b1 ^ xk[14]) 47 b3 ^= precomputeT(b0 ^ b1 ^ b2 ^ xk[15]) 48 // 17~20轮 49 b0 ^= precomputeT(b1 ^ b2 ^ b3 ^ xk[16]) 50 b1 ^= precomputeT(b2 ^ b3 ^ b0 ^ xk[17]) 51 b2 ^= precomputeT(b3 ^ b0 ^ b1 ^ xk[18]) 52 b3 ^= precomputeT(b0 ^ b1 ^ b2 ^ xk[19]) 53 // 21~24轮 54 b0 ^= precomputeT(b1 ^ b2 ^ b3 ^ xk[20]) 55 b1 ^= precomputeT(b2 ^ b3 ^ b0 ^ xk[21]) 56 b2 ^= precomputeT(b3 ^ b0 ^ b1 ^ xk[22]) 57 b3 ^= precomputeT(b0 ^ b1 ^ b2 ^ xk[23]) 58 // 24~28轮 59 b0 ^= precomputeT(b1 ^ b2 ^ b3 ^ xk[24]) 60 b1 ^= precomputeT(b2 ^ b3 ^ b0 ^ xk[25]) 61 b2 ^= precomputeT(b3 ^ b0 ^ b1 ^ xk[26]) 62 b3 ^= precomputeT(b0 ^ b1 ^ b2 ^ xk[27]) 63 // 29~32轮 64 b0 ^= t(b1 ^ b2 ^ b3 ^ xk[28]) 65 b1 ^= t(b2 ^ b3 ^ b0 ^ xk[29]) 66 b2 ^= t(b3 ^ b0 ^ b1 ^ xk[30]) 67 b3 ^= t(b0 ^ b1 ^ b2 ^ xk[31]) 68 // 反序拼接 69 binary.BigEndian.PutUint32(dst[:], b3) 70 binary.BigEndian.PutUint32(dst[4:], b2) 71 binary.BigEndian.PutUint32(dst[8:], b1) 72 binary.BigEndian.PutUint32(dst[12:], b0) 73 } 74 75 // sm4密钥扩展 76 // 77 // Key expansion algorithm. 78 func expandKeyGo(key []byte, enc, dec []uint32) { 79 // Encryption key setup. 80 var i int 81 var mk []uint32 82 var k [rounds + 4]uint32 83 nk := len(key) / 4 84 mk = make([]uint32, nk) 85 for i = 0; i < nk; i++ { 86 mk[i] = binary.BigEndian.Uint32(key[4*i:]) 87 k[i] = mk[i] ^ fk[i] 88 } 89 90 for i = 0; i < rounds; i++ { 91 // 合成置换再异或 92 k[i+4] = k[i] ^ t2(k[i+1]^k[i+2]^k[i+3]^ck[i]) 93 enc[i] = k[i+4] 94 } 95 96 // Derive decryption key from encryption key. 97 if dec == nil { 98 return 99 } 100 for i = 0; i < rounds; i++ { 101 dec[i] = enc[rounds-1-i] 102 } 103 } 104 105 // sm4块解密 106 // 107 // 外部调用时需保证xk是逆序的轮密钥 108 // Decrypt one block from src into dst, using the expanded key xk. 109 func decryptBlockGo(xk []uint32, dst, src []byte) { 110 encryptBlockGo(xk, dst, src) 111 } 112 113 // 轮函数用线性变换函数 114 // 115 // L(B) 116 func l(b uint32) uint32 { 117 return b ^ bits.RotateLeft32(b, 2) ^ bits.RotateLeft32(b, 10) ^ bits.RotateLeft32(b, 18) ^ bits.RotateLeft32(b, 24) 118 } 119 120 // 密钥扩展用线性变换函数 121 // 122 // L'(B) 123 func l2(b uint32) uint32 { 124 return b ^ bits.RotateLeft32(b, 13) ^ bits.RotateLeft32(b, 23) 125 } 126 127 // 合成置换函数 128 func _t(in uint32, fn convert) uint32 { 129 var bytes [4]byte 130 binary.BigEndian.PutUint32(bytes[:], in) 131 // 使用s盒映射实现非线性变换 132 for i := 0; i < 4; i++ { 133 bytes[i] = sbox[bytes[i]] 134 } 135 // 调用线性变换函数 136 return fn(binary.BigEndian.Uint32(bytes[:])) 137 } 138 139 // 轮函数用合成置换函数 140 // 141 // T 142 func t(in uint32) uint32 { 143 return _t(in, l) 144 } 145 146 // 密钥扩展用合成置换函数 147 // 148 // T' 149 func t2(in uint32) uint32 { 150 return _t(in, l2) 151 } 152 153 // 优化的轮函数用合成置换函数 154 // 155 // 5~28轮使用 156 func precomputeT(in uint32) uint32 { 157 return sboxT0[byte(in>>24)] ^ 158 sboxT1[byte(in>>16)] ^ 159 sboxT2[byte(in>>8)] ^ 160 sboxT3[byte(in)] 161 }