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