SM4 介绍
SM4 算法是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012年3月21日发布。相关标准为“GM/T 0002-2012《SM4分组密码算法》”。本质是一个对称分组加密算法,类似于 DES 或者 AES。它的的分组长度为 128bit,密钥长度为 128bit。算法先由已知秘钥生成轮秘钥 rk,然后与被 S-box 加密后的明文 X 进行 32 轮轮变换,生成密文。解密只需将轮秘钥倒序再进行 32 轮轮变换即可,代码仓库
具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| func S(a uint32) uint32 { var aArr [4]byte var bArr [4]byte binary.BigEndian.PutUint32(aArr[:], a) bArr[0] = sBox[aArr[0]] bArr[1] = sBox[aArr[1]] bArr[2] = sBox[aArr[2]] bArr[3] = sBox[aArr[3]] return binary.BigEndian.Uint32(bArr[:]) }
func L(b uint32) uint32 { return b ^ bits.RotateLeft32(b, 2) ^ bits.RotateLeft32(b, 10) ^ bits.RotateLeft32(b, 18) ^ bits.RotateLeft32(b, 24) }
func T(z uint32) uint32 { return L(S(z)) }
func lRk(b uint32) uint32 { return b ^ bits.RotateLeft32(b, 13) ^ bits.RotateLeft32(b, 23) }
func tRk(z uint32) uint32 { return lRk(S(z)) }
func reverse(a []uint32) { a[0], a[3] = a[3], a[0] a[1], a[2] = a[2], a[1] }
func expandKey(key []byte) []uint32 { mK := make([]uint32, 4) mK[0] = binary.BigEndian.Uint32(key[0:4]) mK[1] = binary.BigEndian.Uint32(key[4:8]) mK[2] = binary.BigEndian.Uint32(key[8:12]) mK[3] = binary.BigEndian.Uint32(key[12:16])
k := make([]uint32, 36) k[0] = mK[0] ^ fK[0] k[1] = mK[1] ^ fK[1] k[2] = mK[2] ^ fK[2] k[3] = mK[3] ^ fK[3]
rk := make([]uint32, 32) for i := 0; i < 32; i++ { k[i+4] = k[i] ^ tRk(k[i+1]^k[i+2]^k[i+3]^cK[i]) rk[i] = k[i+4] } return rk }
func initX(text []byte) []uint32 { x := make([]uint32, 36) x[0] = binary.BigEndian.Uint32(text[0:4]) x[1] = binary.BigEndian.Uint32(text[4:8]) x[2] = binary.BigEndian.Uint32(text[8:12]) x[3] = binary.BigEndian.Uint32(text[12:16]) return x }
func encrypt(x []uint32, rk []uint32) []uint32 { for i := 0; i < 32; i++ { x[i+4] = x[i] ^ T(x[i+1]^x[i+2]^x[i+3]^rk[i]) } reverse(x[32:]) return x[32:] }
func decrypt(res []uint32, rk []uint32) []uint32 { x := make([]uint32, 36) x[0] = res[0] x[1] = res[1] x[2] = res[2] x[3] = res[3] for i := 0; i < 32; i++ { x[i+4] = x[i] ^ T(x[i+1]^x[i+2]^x[i+3]^rk[31-i]) } reverse(x[32:]) return x[32:] }
func Padding(text []byte, blockSize int) []byte { length := blockSize - len(text)%blockSize padText := bytes.Repeat([]byte{byte(length)}, length) return append(text, padText...) }
func UnPadding(text []byte) []byte { length := len(text) padLength := int(text[length-1]) return text[:(length - padLength)] } © 2020 GitHub, Inc.
|