/
ctrOnce.go
53 lines (47 loc) · 1013 Bytes
/
ctrOnce.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package AesCtr
import (
"crypto/cipher"
)
type CtrForAesOnceXORKeyStreamRequest struct {
AesBlock cipher.Block
Dst []byte
Src []byte
Iv []byte
TmpBuf []byte
}
type ctrOnceInterface interface {
ctrOnce(req CtrForAesOnceXORKeyStreamRequest)
}
func CtrForAesOnceXORKeyStream(req CtrForAesOnceXORKeyStreamRequest) {
ctrOnce, ok := req.AesBlock.(ctrOnceInterface)
if ok {
ctrOnce.ctrOnce(req)
return
}
if len(req.TmpBuf) < 32 {
req.TmpBuf = make([]byte, 32)
}
const blockSize = 16
ctr := req.TmpBuf[:16]
blockOutBuf := req.TmpBuf[16:32]
copy(ctr[:], req.Iv)
pos := 0
for {
if pos >= len(req.Src) {
return
}
req.AesBlock.Encrypt(blockOutBuf[:], ctr[:])
for i := blockSize - 1; i >= 0; i-- {
ctr[i]++
if ctr[i] != 0 {
break
}
}
thisXorSize := len(req.Src) - pos
if thisXorSize > blockSize {
thisXorSize = blockSize
}
xorBytes(req.Dst[pos:pos+thisXorSize], req.Src[pos:pos+thisXorSize], blockOutBuf[:thisXorSize])
pos += blockSize
}
}