github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/sm4soft/sm4_gcm.go (about)

     1  // Copyright 2022 s1ren@github.com/hxx258456.
     2  
     3  /*
     4  sm4soft 是sm4的纯软实现,基于tjfoc国密算法库`tjfoc/gmsm`做了少量修改。
     5  对应版权声明: thrid_licenses/github.com/tjfoc/gmsm/版权声明
     6  */
     7  
     8  package sm4soft
     9  
    10  import (
    11  	"errors"
    12  	"strconv"
    13  )
    14  
    15  // Sm4GCM SM4 GCM 加解密模式
    16  // Paper: The Galois/Counter Mode of Operation (GCM) David A. Mcgrew,John Viega .2004.
    17  // key: 对称加密密钥
    18  // IV: IV向量
    19  // in:
    20  // A: 附加的可鉴别数据(ADD)
    21  // mode: true - 加密; false - 解密验证
    22  //
    23  // return: 密文C, 鉴别标签T, 错误
    24  func Sm4GCM(key []byte, IV, in, A []byte, mode bool) ([]byte, []byte, error) {
    25  	if len(key) != BlockSize {
    26  		return nil, nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key)))
    27  	}
    28  	if mode {
    29  		C, T := GCMEncrypt(key, IV, in, A)
    30  		return C, T, nil
    31  	} else {
    32  		P, _T := GCMDecrypt(key, IV, in, A)
    33  		return P, _T, nil
    34  	}
    35  }
    36  
    37  // GetH 对“0”分组的加密得到 GHASH泛杂凑函数的子密钥
    38  // key: 对称密钥
    39  // return: GHASH泛杂凑函数的子密钥
    40  func GetH(key []byte) (H []byte) {
    41  	c, err := NewCipher(key)
    42  	if err != nil {
    43  		panic(err)
    44  	}
    45  
    46  	zores := make([]byte, BlockSize)
    47  	H = make([]byte, BlockSize)
    48  	c.Encrypt(H, zores)
    49  	return H
    50  }
    51  
    52  // ut = a + b
    53  func addition(a, b []byte) (out []byte) {
    54  	Len := len(a)
    55  	if Len != len(b) {
    56  		return nil
    57  	}
    58  	out = make([]byte, Len)
    59  	for i := 0; i < Len; i++ {
    60  		out[i] = a[i] ^ b[i]
    61  	}
    62  	return out
    63  }
    64  
    65  func Rightshift(V []byte) {
    66  	n := len(V)
    67  	for i := n - 1; i >= 0; i-- {
    68  		V[i] = V[i] >> 1
    69  		if i != 0 {
    70  			V[i] = ((V[i-1] & 0x01) << 7) | V[i]
    71  		}
    72  	}
    73  }
    74  
    75  func findYi(Y []byte, index int) int {
    76  	var temp byte
    77  	i := uint(index)
    78  	temp = Y[i/8]
    79  	temp = temp >> (7 - i%8)
    80  	if temp&0x01 == 1 {
    81  		return 1
    82  	} else {
    83  		return 0
    84  	}
    85  }
    86  
    87  func multiplication(X, Y []byte) (Z []byte) {
    88  
    89  	R := make([]byte, BlockSize)
    90  	R[0] = 0xe1
    91  	Z = make([]byte, BlockSize)
    92  	V := make([]byte, BlockSize)
    93  	copy(V, X)
    94  	for i := 0; i <= 127; i++ {
    95  		if findYi(Y, i) == 1 {
    96  			Z = addition(Z, V)
    97  		}
    98  		if V[BlockSize-1]&0x01 == 0 {
    99  			Rightshift(V)
   100  		} else {
   101  			Rightshift(V)
   102  			V = addition(V, R)
   103  		}
   104  	}
   105  	return Z
   106  }
   107  
   108  func GHASH(H []byte, A []byte, C []byte) (X []byte) {
   109  
   110  	calculmV := func(m, v int) (int, int) {
   111  		if m == 0 && v != 0 {
   112  			m = 1
   113  			v = v * 8
   114  		} else if m != 0 && v == 0 {
   115  			v = BlockSize * 8
   116  		} else if m != 0 && v != 0 {
   117  			m = m + 1
   118  			v = v * 8
   119  		} else { //m==0 && v==0
   120  			m = 1
   121  			v = 0
   122  		}
   123  		return m, v
   124  	}
   125  	m := len(A) / BlockSize
   126  	v := len(A) % BlockSize
   127  	m, v = calculmV(m, v)
   128  
   129  	n := len(C) / BlockSize
   130  	u := len(C) % BlockSize
   131  	n, u = calculmV(n, u)
   132  
   133  	//i=0
   134  	X = make([]byte, BlockSize*(m+n+2)) //X0 = 0
   135  	for i := 0; i < BlockSize; i++ {
   136  		X[i] = 0x00
   137  	}
   138  
   139  	//i=1...m-1
   140  	for i := 1; i <= m-1; i++ {
   141  		copy(X[i*BlockSize:i*BlockSize+BlockSize], multiplication(addition(X[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], A[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize]), H)) //A 1-->m-1 对于数组来说是 0-->m-2
   142  	}
   143  
   144  	//i=m
   145  	zeros := make([]byte, (128-v)/8)
   146  	Am := make([]byte, v/8)
   147  	copy(Am[:], A[(m-1)*BlockSize:])
   148  	Am = append(Am, zeros...)
   149  	copy(X[m*BlockSize:m*BlockSize+BlockSize], multiplication(addition(X[(m-1)*BlockSize:(m-1)*BlockSize+BlockSize], Am), H))
   150  
   151  	//i=m+1...m+n-1
   152  	for i := m + 1; i <= (m + n - 1); i++ {
   153  		copy(X[i*BlockSize:i*BlockSize+BlockSize], multiplication(addition(X[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], C[(i-m-1)*BlockSize:(i-m-1)*BlockSize+BlockSize]), H))
   154  	}
   155  
   156  	//i=m+n
   157  	zeros = make([]byte, (128-u)/8)
   158  	Cn := make([]byte, u/8)
   159  	copy(Cn[:], C[(n-1)*BlockSize:])
   160  	Cn = append(Cn, zeros...)
   161  	copy(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize], multiplication(addition(X[(m+n-1)*BlockSize:(m+n-1)*BlockSize+BlockSize], Cn), H))
   162  
   163  	//i=m+n+1
   164  	var lenAB []byte
   165  	calculateLenToBytes := func(len int) []byte {
   166  		data := make([]byte, 8)
   167  		data[0] = byte((len >> 56) & 0xff)
   168  		data[1] = byte((len >> 48) & 0xff)
   169  		data[2] = byte((len >> 40) & 0xff)
   170  		data[3] = byte((len >> 32) & 0xff)
   171  		data[4] = byte((len >> 24) & 0xff)
   172  		data[5] = byte((len >> 16) & 0xff)
   173  		data[6] = byte((len >> 8) & 0xff)
   174  		data[7] = byte((len >> 0) & 0xff)
   175  		return data
   176  	}
   177  	lenAB = append(lenAB, calculateLenToBytes(len(A))...)
   178  	lenAB = append(lenAB, calculateLenToBytes(len(C))...)
   179  	copy(X[(m+n+1)*BlockSize:(m+n+1)*BlockSize+BlockSize], multiplication(addition(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize], lenAB), H))
   180  	return X[(m+n+1)*BlockSize : (m+n+1)*BlockSize+BlockSize]
   181  }
   182  
   183  // GetY0 生成初始的计数器时钟J0
   184  //
   185  // H: GHASH自密钥
   186  // IV: IV向量
   187  // return: 初始的计数器时钟(J0)
   188  func GetY0(H, IV []byte) []byte {
   189  	if len(IV)*8 == 96 {
   190  		zero31one1 := []byte{0x00, 0x00, 0x00, 0x01}
   191  		IV = append(IV, zero31one1...)
   192  		return IV
   193  	} else {
   194  		return GHASH(H, []byte{}, IV)
   195  	}
   196  }
   197  
   198  func incr(n int, YI []byte) (YIi []byte) {
   199  
   200  	YIi = make([]byte, BlockSize*n)
   201  	copy(YIi, YI)
   202  
   203  	addYone := func(yi, yii []byte) {
   204  		copy(yii[:], yi[:])
   205  
   206  		Len := len(yi)
   207  		var rc byte = 0x00
   208  		for i := Len - 1; i >= 0; i-- {
   209  			if i == Len-1 {
   210  				if yii[i] < 0xff {
   211  					yii[i] = yii[i] + 0x01
   212  					rc = 0x00
   213  				} else {
   214  					yii[i] = 0x00
   215  					rc = 0x01
   216  				}
   217  			} else {
   218  				if yii[i]+rc < 0xff {
   219  					yii[i] = yii[i] + rc
   220  					rc = 0x00
   221  				} else {
   222  					yii[i] = 0x00
   223  					rc = 0x01
   224  				}
   225  			}
   226  		}
   227  	}
   228  	for i := 1; i < n; i++ { //2^32
   229  		addYone(YIi[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], YIi[i*BlockSize:i*BlockSize+BlockSize])
   230  	}
   231  	return YIi
   232  }
   233  
   234  func MSB(len int, S []byte) (out []byte) {
   235  	return S[:len/8]
   236  }
   237  
   238  // GCMEncrypt 可鉴别加密函数 (GCM-AE(k))
   239  // K: 对称密钥
   240  // IV: IV向量
   241  // P: 明文
   242  // A: 附加的鉴别数据
   243  //
   244  // return: 密文, 鉴别标签
   245  func GCMEncrypt(K, IV, P, A []byte) (C, T []byte) {
   246  	calculmV := func(m, v int) (int, int) {
   247  		if m == 0 && v != 0 {
   248  			m = 1
   249  			v = v * 8
   250  		} else if m != 0 && v == 0 {
   251  			v = BlockSize * 8
   252  		} else if m != 0 && v != 0 {
   253  			m = m + 1
   254  			v = v * 8
   255  		} else { //m==0 && v==0
   256  			m = 1
   257  			v = 0
   258  		}
   259  		return m, v
   260  	}
   261  	n := len(P) / BlockSize
   262  	u := len(P) % BlockSize
   263  	n, u = calculmV(n, u)
   264  
   265  	// a) 通过对“0”分组的加密得到 GHASH泛杂凑函数的子密钥
   266  	H := GetH(K)
   267  
   268  	Y0 := GetY0(H, IV)
   269  
   270  	// Y := make([]byte, BlockSize*(n+1))
   271  	Y := incr(n+1, Y0)
   272  	c, err := NewCipher(K)
   273  	if err != nil {
   274  		panic(err)
   275  	}
   276  	Enc := make([]byte, BlockSize)
   277  	C = make([]byte, len(P))
   278  
   279  	//i=1...n-1
   280  	for i := 1; i <= n-1; i++ {
   281  		c.Encrypt(Enc, Y[i*BlockSize:i*BlockSize+BlockSize])
   282  
   283  		copy(C[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], addition(P[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], Enc))
   284  	}
   285  
   286  	//i=n
   287  	c.Encrypt(Enc, Y[n*BlockSize:n*BlockSize+BlockSize])
   288  	out := MSB(u, Enc)
   289  	copy(C[(n-1)*BlockSize:], addition(P[(n-1)*BlockSize:], out))
   290  
   291  	c.Encrypt(Enc, Y0)
   292  
   293  	t := 128
   294  	T = MSB(t, addition(Enc, GHASH(H, A, C)))
   295  	return C, T
   296  }
   297  
   298  func GCMDecrypt(K, IV, C, A []byte) (P, _T []byte) {
   299  	calculmV := func(m, v int) (int, int) {
   300  		if m == 0 && v != 0 {
   301  			m = 1
   302  			v = v * 8
   303  		} else if m != 0 && v == 0 {
   304  			v = BlockSize * 8
   305  		} else if m != 0 && v != 0 {
   306  			m = m + 1
   307  			v = v * 8
   308  		} else { //m==0 && v==0
   309  			m = 1
   310  			v = 0
   311  		}
   312  		return m, v
   313  	}
   314  
   315  	H := GetH(K)
   316  
   317  	Y0 := GetY0(H, IV)
   318  
   319  	Enc := make([]byte, BlockSize)
   320  	c, err := NewCipher(K)
   321  	if err != nil {
   322  		panic(err)
   323  	}
   324  	c.Encrypt(Enc, Y0)
   325  	t := 128
   326  	_T = MSB(t, addition(Enc, GHASH(H, A, C)))
   327  
   328  	n := len(C) / BlockSize
   329  	u := len(C) % BlockSize
   330  	n, u = calculmV(n, u)
   331  	// Y := make([]byte, BlockSize*(n+1))
   332  	Y := incr(n+1, Y0)
   333  
   334  	P = make([]byte, BlockSize*n)
   335  	for i := 1; i <= n; i++ {
   336  		c.Encrypt(Enc, Y[i*BlockSize:i*BlockSize+BlockSize])
   337  		copy(P[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], addition(C[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize], Enc))
   338  	}
   339  
   340  	c.Encrypt(Enc, Y[n*BlockSize:n*BlockSize+BlockSize])
   341  	out := MSB(u, Enc)
   342  	copy(P[(n-1)*BlockSize:], addition(C[(n-1)*BlockSize:], out))
   343  
   344  	return P, _T
   345  }