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 }