github.com/Hyperledger-TWGC/tjfoc-gm@v1.4.0/sm4/sm4_gcm.go (about)

     1  /*
     2  Copyright Hyperledger-TWGC 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  writed by Zhiwei Yan, 2020 Oct
    16  */
    17  package sm4
    18  
    19  import (
    20  	"errors"
    21  	"strconv"
    22  )
    23  
    24  //Paper: The Galois/Counter Mode of Operation (GCM) David A. Mcgrew,John Viega .2004.
    25  func Sm4GCM(key []byte, IV ,in, A []byte, mode bool) ([]byte, []byte, error) {
    26  	if len(key) != BlockSize {
    27  		return nil,nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key)))
    28  	}
    29  	if mode {
    30  		C,T:=GCMEncrypt(key,IV,in,A)
    31  		return C,T,nil
    32  	}else{
    33  		P,_T:=GCMDecrypt(key,IV,in,A)
    34  		return P,_T,nil
    35  	}
    36  }
    37  
    38  func GetH(key []byte) (H []byte){
    39  	c,err := NewCipher(key)
    40  	if err != nil {
    41  		panic(err)
    42  	}
    43  
    44  	zores:=make([]byte, BlockSize)
    45  	H =make([]byte, BlockSize)
    46  	c.Encrypt(H,zores)
    47  	return H
    48  }
    49  
    50  //ut = a + b
    51  func addition(a ,b  []byte) (out []byte){
    52  	Len:=len(a)
    53  	if Len != len(b) {
    54  		return nil
    55  	}
    56  	out = make([]byte, Len)
    57  	for i := 0; i < Len; i++ {
    58  		out[i] = a[i] ^ b[i]
    59  	}
    60  	return out
    61  }
    62  
    63  func Rightshift(V []byte){
    64  	n:=len(V)
    65  	for i:=n-1;i>=0;i-- {
    66  		V[i]=V[i]>>1
    67  		if i!=0{
    68  			V[i]=((V[i-1]&0x01)<<7)|V[i]
    69  		}
    70  	}
    71  }
    72  
    73  func findYi( Y []byte,index int) int{
    74  	var temp byte
    75  	temp=Y[index/8]
    76  	temp=temp>>(7-index%8)
    77  	if temp & 0x01 == 1{
    78  		return 1
    79  	}else{
    80  		return 0
    81  	}
    82  }
    83  
    84  
    85  func multiplication(X,Y []byte) (Z []byte){
    86  
    87  	R:=make([]byte,BlockSize)
    88  	R[0]=0xe1
    89  	Z=make([]byte,BlockSize)
    90  	V:=make([]byte,BlockSize)
    91  	copy(V,X)
    92  	for i:=0;i<=127;i++{
    93  		if findYi(Y,i)==1{
    94  			Z=addition(Z,V)
    95  		}
    96  		if V[BlockSize-1]&0x01==0{
    97  			Rightshift(V)
    98  		}else{
    99  			Rightshift(V)
   100  			V=addition(V,R)
   101  		}
   102  	}
   103  	return Z
   104  }
   105  
   106  func GHASH(H []byte,A []byte,C []byte) (X[]byte){
   107  
   108  	calculm_v:=func(m ,v int) (int,int) {
   109  		if(m==0 && v!=0){
   110  			m=1
   111  			v=v*8
   112  		}else if(m!=0 && v==0) {
   113  			v=BlockSize*8
   114  		}else if(m!=0 && v!=0){
   115  			m=m+1
   116  			v=v*8
   117  		}else { //m==0 && v==0
   118  			m=1
   119  			v=0
   120  		}
   121  		return m,v
   122  	}
   123  	m:=len(A)/BlockSize
   124  	v:=len(A)%BlockSize
   125  	m,v=calculm_v(m,v)
   126  
   127  	n:=len(C)/BlockSize
   128  	u:=(len(C)%BlockSize)
   129  	n,u=calculm_v(n,u)
   130  
   131  	//i=0
   132  	X=make([]byte,BlockSize*(m+n+2)) //X0 = 0
   133  	for i:=0;i<BlockSize;i++{
   134  		X[i]=0x00
   135  	}
   136  
   137  	//i=1...m-1
   138  	for i:=1;i<=m-1;i++{
   139  		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
   140  	}
   141  
   142  	//i=m
   143  	zeros:=make([]byte,(128-v)/8)
   144  	Am:=make([]byte,v/8)
   145  	copy(Am[:],A[(m-1)*BlockSize:])
   146  	Am=append(Am,zeros...)
   147  	copy(X[m*BlockSize:m*BlockSize+BlockSize],multiplication( addition(X[(m-1)*BlockSize:(m-1)*BlockSize+BlockSize],Am),H))
   148  
   149  	//i=m+1...m+n-1
   150  	for i:=m+1;i<=(m+n-1);i++{
   151  		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))
   152  	}
   153  
   154  	//i=m+n
   155  	zeros =make([]byte,(128-u)/8)
   156  	Cn:=make([]byte,u/8)
   157  	copy(Cn[:],C[(n-1)*BlockSize:])
   158  	Cn=append(Cn,zeros...)
   159  	copy(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize],multiplication( addition(X[(m+n-1)*BlockSize:(m+n-1)*BlockSize+BlockSize],Cn),H))
   160  
   161  	//i=m+n+1
   162  	var lenAB []byte
   163  	calculateLenToBytes :=func(len int) []byte{
   164  		data:=make([]byte,8)
   165  		data[0]=byte((len>>56)&0xff)
   166  		data[1]=byte((len>>48)&0xff)
   167  		data[2]=byte((len>>40)&0xff)
   168  		data[3]=byte((len>>32)&0xff)
   169  		data[4]=byte((len>>24)&0xff)
   170  		data[5]=byte((len>>16)&0xff)
   171  		data[6]=byte((len>>8)&0xff)
   172  		data[7]=byte((len>>0)&0xff)
   173  		return data
   174  	}
   175  	lenAB=append(lenAB,calculateLenToBytes(len(A))...)
   176  	lenAB=append(lenAB,calculateLenToBytes(len(C))...)
   177  	copy(X[(m+n+1)*BlockSize:(m+n+1)*BlockSize+BlockSize],multiplication(addition(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize],lenAB),H))
   178  	return  X[(m+n+1)*BlockSize:(m+n+1)*BlockSize+BlockSize]
   179  }
   180  
   181  
   182  func GetY0(H,IV []byte) []byte{
   183  	if len(IV)*8 == 96 {
   184  		zero31one1:=[]byte{0x00,0x00,0x00,0x01}
   185  		IV=append(IV,zero31one1...)
   186  		return IV
   187  	}else{
   188  		return GHASH(H,[]byte{},IV)
   189  
   190  	}
   191  
   192  }
   193  
   194  func incr(n int ,Y_i []byte) (Y_ii []byte) {
   195  
   196  	Y_ii=make([]byte,BlockSize*n)
   197  	copy(Y_ii,Y_i)
   198  
   199  	addYone:=func(yi,yii []byte){
   200  		copy(yii[:],yi[:])
   201  
   202  		Len:=len(yi)
   203  		var rc byte=0x00
   204  		for i:=Len-1;i>=0;i--{
   205  			if(i==Len-1){
   206  				if(yii[i]<0xff){
   207  					yii[i]=yii[i]+0x01
   208  					rc=0x00
   209  				}else{
   210  					yii[i]=0x00
   211  					rc=0x01
   212  				}
   213  			}else{
   214  				if yii[i]+rc<0xff {
   215  					yii[i]=yii[i]+rc
   216  					rc=0x00
   217  				}else{
   218  					yii[i]=0x00
   219  					rc=0x01
   220  				}
   221  			}
   222  		}
   223  	}
   224  	for i:=1;i<n;i++{ //2^32
   225  		addYone(Y_ii[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],Y_ii[i*BlockSize:i*BlockSize+BlockSize])
   226  	}
   227  	return Y_ii
   228  }
   229  
   230  func MSB(len int, S []byte) (out []byte){
   231  	return S[:len/8]
   232  }
   233  func GCMEncrypt(K,IV,P,A []byte) (C,T []byte){
   234  	calculm_v:=func(m ,v int) (int,int) {
   235  		if(m==0 && v!=0){
   236  			m=1
   237  			v=v*8
   238  		}else if(m!=0 && v==0) {
   239  			v=BlockSize*8
   240  		}else if(m!=0 && v!=0){
   241  			m=m+1
   242  			v=v*8
   243  		}else { //m==0 && v==0
   244  			m=1
   245  			v=0
   246  		}
   247  		return m,v
   248  	}
   249  	n:=len(P)/BlockSize
   250  	u:=len(P)%BlockSize
   251  	n,u=calculm_v(n,u)
   252  
   253  	H:=GetH(K)
   254  
   255  	Y0:=GetY0(H,IV)
   256  
   257  	Y:=make([]byte,BlockSize*(n+1))
   258  	Y=incr(n+1,Y0)
   259  	c,err := NewCipher(K)
   260  	if err != nil {
   261  		panic(err)
   262  	}
   263  	Enc:=make([]byte,BlockSize)
   264  	C =make([]byte,len(P))
   265  
   266  	//i=1...n-1
   267  	for i:=1;i<=n-1;i++{
   268  		c.Encrypt(Enc,Y[i*BlockSize:i*BlockSize+BlockSize])
   269  
   270  		copy(C[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],addition(P[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],Enc))
   271  	}
   272  
   273  	//i=n
   274  	c.Encrypt(Enc,Y[n*BlockSize:n*BlockSize+BlockSize])
   275  	out:=MSB(u,Enc)
   276  	copy(C[(n-1)*BlockSize:],addition(P[(n-1)*BlockSize:],out))
   277  
   278  	c.Encrypt(Enc,Y0)
   279  
   280  	t:=128
   281  	T =MSB(t,addition(Enc,GHASH(H,A,C)))
   282  	return C,T
   283  }
   284  
   285  func GCMDecrypt(K,IV,C,A []byte)(P,_T []byte){
   286  	calculm_v:=func(m ,v int) (int,int) {
   287  		if(m==0 && v!=0){
   288  			m=1
   289  			v=v*8
   290  		}else if(m!=0 && v==0) {
   291  			v=BlockSize*8
   292  		}else if(m!=0 && v!=0){
   293  			m=m+1
   294  			v=v*8
   295  		}else { //m==0 && v==0
   296  			m=1
   297  			v=0
   298  		}
   299  		return m,v
   300  	}
   301  
   302  	H:=GetH(K)
   303  
   304  	Y0:=GetY0(H,IV)
   305  
   306  	Enc:=make([]byte,BlockSize)
   307  	c,err := NewCipher(K)
   308  	if err != nil{
   309  		panic(err)
   310  	}
   311  	c.Encrypt(Enc,Y0)
   312  	t:=128
   313  	_T=MSB(t,addition(Enc,GHASH(H,A,C)))
   314  
   315  	n:=len(C)/BlockSize
   316  	u:=len(C)%BlockSize
   317  	n,u=calculm_v(n,u)
   318  	Y:=make([]byte,BlockSize*(n+1))
   319  	Y=incr(n+1,Y0)
   320  
   321  	P =make([]byte,len(C))
   322  	for i:=1;i<=n;i++{
   323  		c.Encrypt(Enc,Y[i*BlockSize:i*BlockSize+BlockSize])
   324  		copy(P[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],addition(C[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],Enc))
   325  	}
   326  
   327  	c.Encrypt(Enc,Y[n*BlockSize:n*BlockSize+BlockSize])
   328  	out:=MSB(u,Enc)
   329  	copy(P[(n-1)*BlockSize:],addition(C[(n-1)*BlockSize:],out))
   330  
   331  	return P,_T
   332  }