...

Source file src/github.com/tjfoc/gmsm/sm4/sm4_gcm.go

Documentation: github.com/tjfoc/gmsm/sm4

     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  	i := uint(index)
    76  	temp=Y[i/8]
    77  	temp=temp>>(7-i%8)
    78  	if temp & 0x01 == 1{
    79  		return 1
    80  	}else{
    81  		return 0
    82  	}
    83  }
    84  
    85  
    86  func multiplication(X,Y []byte) (Z []byte){
    87  
    88  	R:=make([]byte,BlockSize)
    89  	R[0]=0xe1
    90  	Z=make([]byte,BlockSize)
    91  	V:=make([]byte,BlockSize)
    92  	copy(V,X)
    93  	for i:=0;i<=127;i++{
    94  		if findYi(Y,i)==1{
    95  			Z=addition(Z,V)
    96  		}
    97  		if V[BlockSize-1]&0x01==0{
    98  			Rightshift(V)
    99  		}else{
   100  			Rightshift(V)
   101  			V=addition(V,R)
   102  		}
   103  	}
   104  	return Z
   105  }
   106  
   107  func GHASH(H []byte,A []byte,C []byte) (X[]byte){
   108  
   109  	calculm_v:=func(m ,v int) (int,int) {
   110  		if(m==0 && v!=0){
   111  			m=1
   112  			v=v*8
   113  		}else if(m!=0 && v==0) {
   114  			v=BlockSize*8
   115  		}else if(m!=0 && v!=0){
   116  			m=m+1
   117  			v=v*8
   118  		}else { //m==0 && v==0
   119  			m=1
   120  			v=0
   121  		}
   122  		return m,v
   123  	}
   124  	m:=len(A)/BlockSize
   125  	v:=len(A)%BlockSize
   126  	m,v=calculm_v(m,v)
   127  
   128  	n:=len(C)/BlockSize
   129  	u:=(len(C)%BlockSize)
   130  	n,u=calculm_v(n,u)
   131  
   132  	//i=0
   133  	X=make([]byte,BlockSize*(m+n+2)) //X0 = 0
   134  	for i:=0;i<BlockSize;i++{
   135  		X[i]=0x00
   136  	}
   137  
   138  	//i=1...m-1
   139  	for i:=1;i<=m-1;i++{
   140  		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
   141  	}
   142  
   143  	//i=m
   144  	zeros:=make([]byte,(128-v)/8)
   145  	Am:=make([]byte,v/8)
   146  	copy(Am[:],A[(m-1)*BlockSize:])
   147  	Am=append(Am,zeros...)
   148  	copy(X[m*BlockSize:m*BlockSize+BlockSize],multiplication( addition(X[(m-1)*BlockSize:(m-1)*BlockSize+BlockSize],Am),H))
   149  
   150  	//i=m+1...m+n-1
   151  	for i:=m+1;i<=(m+n-1);i++{
   152  		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))
   153  	}
   154  
   155  	//i=m+n
   156  	zeros =make([]byte,(128-u)/8)
   157  	Cn:=make([]byte,u/8)
   158  	copy(Cn[:],C[(n-1)*BlockSize:])
   159  	Cn=append(Cn,zeros...)
   160  	copy(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize],multiplication( addition(X[(m+n-1)*BlockSize:(m+n-1)*BlockSize+BlockSize],Cn),H))
   161  
   162  	//i=m+n+1
   163  	var lenAB []byte
   164  	calculateLenToBytes :=func(len int) []byte{
   165  		data:=make([]byte,8)
   166  		data[0]=byte((len>>56)&0xff)
   167  		data[1]=byte((len>>48)&0xff)
   168  		data[2]=byte((len>>40)&0xff)
   169  		data[3]=byte((len>>32)&0xff)
   170  		data[4]=byte((len>>24)&0xff)
   171  		data[5]=byte((len>>16)&0xff)
   172  		data[6]=byte((len>>8)&0xff)
   173  		data[7]=byte((len>>0)&0xff)
   174  		return data
   175  	}
   176  	lenAB=append(lenAB,calculateLenToBytes(len(A))...)
   177  	lenAB=append(lenAB,calculateLenToBytes(len(C))...)
   178  	copy(X[(m+n+1)*BlockSize:(m+n+1)*BlockSize+BlockSize],multiplication(addition(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize],lenAB),H))
   179  	return  X[(m+n+1)*BlockSize:(m+n+1)*BlockSize+BlockSize]
   180  }
   181  
   182  
   183  func GetY0(H,IV []byte) []byte{
   184  	if len(IV)*8 == 96 {
   185  		zero31one1:=[]byte{0x00,0x00,0x00,0x01}
   186  		IV=append(IV,zero31one1...)
   187  		return IV
   188  	}else{
   189  		return GHASH(H,[]byte{},IV)
   190  
   191  	}
   192  
   193  }
   194  
   195  func incr(n int ,Y_i []byte) (Y_ii []byte) {
   196  
   197  	Y_ii=make([]byte,BlockSize*n)
   198  	copy(Y_ii,Y_i)
   199  
   200  	addYone:=func(yi,yii []byte){
   201  		copy(yii[:],yi[:])
   202  
   203  		Len:=len(yi)
   204  		var rc byte=0x00
   205  		for i:=Len-1;i>=0;i--{
   206  			if(i==Len-1){
   207  				if(yii[i]<0xff){
   208  					yii[i]=yii[i]+0x01
   209  					rc=0x00
   210  				}else{
   211  					yii[i]=0x00
   212  					rc=0x01
   213  				}
   214  			}else{
   215  				if yii[i]+rc<0xff {
   216  					yii[i]=yii[i]+rc
   217  					rc=0x00
   218  				}else{
   219  					yii[i]=0x00
   220  					rc=0x01
   221  				}
   222  			}
   223  		}
   224  	}
   225  	for i:=1;i<n;i++{ //2^32
   226  		addYone(Y_ii[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],Y_ii[i*BlockSize:i*BlockSize+BlockSize])
   227  	}
   228  	return Y_ii
   229  }
   230  
   231  func MSB(len int, S []byte) (out []byte){
   232  	return S[:len/8]
   233  }
   234  func GCMEncrypt(K,IV,P,A []byte) (C,T []byte){
   235  	calculm_v:=func(m ,v int) (int,int) {
   236  		if(m==0 && v!=0){
   237  			m=1
   238  			v=v*8
   239  		}else if(m!=0 && v==0) {
   240  			v=BlockSize*8
   241  		}else if(m!=0 && v!=0){
   242  			m=m+1
   243  			v=v*8
   244  		}else { //m==0 && v==0
   245  			m=1
   246  			v=0
   247  		}
   248  		return m,v
   249  	}
   250  	n:=len(P)/BlockSize
   251  	u:=len(P)%BlockSize
   252  	n,u=calculm_v(n,u)
   253  
   254  	H:=GetH(K)
   255  
   256  	Y0:=GetY0(H,IV)
   257  
   258  	Y:=make([]byte,BlockSize*(n+1))
   259  	Y=incr(n+1,Y0)
   260  	c,err := NewCipher(K)
   261  	if err != nil {
   262  		panic(err)
   263  	}
   264  	Enc:=make([]byte,BlockSize)
   265  	C =make([]byte,len(P))
   266  
   267  	//i=1...n-1
   268  	for i:=1;i<=n-1;i++{
   269  		c.Encrypt(Enc,Y[i*BlockSize:i*BlockSize+BlockSize])
   270  
   271  		copy(C[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],addition(P[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],Enc))
   272  	}
   273  
   274  	//i=n
   275  	c.Encrypt(Enc,Y[n*BlockSize:n*BlockSize+BlockSize])
   276  	out:=MSB(u,Enc)
   277  	copy(C[(n-1)*BlockSize:],addition(P[(n-1)*BlockSize:],out))
   278  
   279  	c.Encrypt(Enc,Y0)
   280  
   281  	t:=128
   282  	T =MSB(t,addition(Enc,GHASH(H,A,C)))
   283  	return C,T
   284  }
   285  
   286  func GCMDecrypt(K,IV,C,A []byte)(P,_T []byte){
   287  	calculm_v:=func(m ,v int) (int,int) {
   288  		if(m==0 && v!=0){
   289  			m=1
   290  			v=v*8
   291  		}else if(m!=0 && v==0) {
   292  			v=BlockSize*8
   293  		}else if(m!=0 && v!=0){
   294  			m=m+1
   295  			v=v*8
   296  		}else { //m==0 && v==0
   297  			m=1
   298  			v=0
   299  		}
   300  		return m,v
   301  	}
   302  
   303  	H:=GetH(K)
   304  
   305  	Y0:=GetY0(H,IV)
   306  
   307  	Enc:=make([]byte,BlockSize)
   308  	c,err := NewCipher(K)
   309  	if err != nil{
   310  		panic(err)
   311  	}
   312  	c.Encrypt(Enc,Y0)
   313  	t:=128
   314  	_T=MSB(t,addition(Enc,GHASH(H,A,C)))
   315  
   316  	n:=len(C)/BlockSize
   317  	u:=len(C)%BlockSize
   318  	n,u=calculm_v(n,u)
   319  	Y:=make([]byte,BlockSize*(n+1))
   320  	Y=incr(n+1,Y0)
   321  
   322  	P = make([]byte, BlockSize*n)
   323  	for i:=1;i<=n;i++{
   324  		c.Encrypt(Enc,Y[i*BlockSize:i*BlockSize+BlockSize])
   325  		copy(P[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],addition(C[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],Enc))
   326  	}
   327  
   328  	c.Encrypt(Enc,Y[n*BlockSize:n*BlockSize+BlockSize])
   329  	out:=MSB(u,Enc)
   330  	copy(P[(n-1)*BlockSize:],addition(C[(n-1)*BlockSize:],out))
   331  
   332  	return P,_T
   333  }
   334  

View as plain text