1
17 package sm4
18
19 import (
20 "errors"
21 "strconv"
22 )
23
24
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
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 {
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
133 X=make([]byte,BlockSize*(m+n+2))
134 for i:=0;i<BlockSize;i++{
135 X[i]=0x00
136 }
137
138
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))
141 }
142
143
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
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
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
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++{
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 {
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
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
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 {
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