We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
1 parent 06264b7 commit ed98478Copy full SHA for ed98478
src/crypto/cipher/ctr.go
@@ -19,10 +19,11 @@ import (
19
)
20
21
type ctr struct {
22
- b Block
23
- ctr []byte
24
- out []byte
25
- outUsed int
+ b Block
+ ctr []byte
+ out []byte
+ outUsed int
26
+ offsetPos int
27
}
28
29
const streamBufferSize = 512
@@ -36,7 +37,12 @@ type ctrAble interface {
36
37
38
// NewCTR returns a Stream which encrypts/decrypts using the given Block in
39
// counter mode. The length of iv must be the same as the Block's block size.
40
+
41
func NewCTR(block Block, iv []byte) Stream {
42
+ return NewCTRWithOffset(block, iv, 0)
43
+}
44
45
+func NewCTRWithOffset(block Block, iv []byte, offsetPos int) Stream {
46
if ctr, ok := block.(ctrAble); ok {
47
return ctr.NewCTR(iv)
48
@@ -48,13 +54,48 @@ func NewCTR(block Block, iv []byte) Stream {
54
bufSize = block.BlockSize()
49
55
50
56
return &ctr{
51
- b: block,
52
- ctr: bytes.Clone(iv),
53
- out: make([]byte, 0, bufSize),
- outUsed: 0,
57
+ offsetPos: offsetPos,
58
+ b: block,
59
+ ctr: IncreaseCtr(offsetPos, block.BlockSize(), iv),
60
+ out: make([]byte, 0, bufSize),
61
+ outUsed: 0,
62
63
64
65
+func IncreaseCtr(offsetPos, BlockSize int, iv []byte) []byte {
66
+ iv = bytes.Clone(iv)
67
+ if offsetPos <= 0 {
68
+ return iv
69
+ }
70
+ needAdd := offsetPos / BlockSize
71
+ var addItems []byte
72
73
+ for {
74
+ currentNum := needAdd & 0xff
75
+ addItems = append(addItems, byte(currentNum))
76
+ needAdd >>= 8
77
+ if needAdd <= 0 {
78
+ break
79
80
81
+ for index, add := range addItems {
82
+ tmpIv := iv[:len(iv)-index]
83
84
+ for i := len(tmpIv) - 1; i >= 0; i-- {
85
+ if i == len(tmpIv)-1 && int(tmpIv[i])+int(add) > 255 {
86
+ tmpIv[i] = byte((int(tmpIv[i]) + int(add)) % 256)
87
+ add = 1
88
+ continue
89
90
+ tmpIv[i] += add
91
+ if tmpIv[i] != 0 {
92
93
94
95
96
97
98
99
func (x *ctr) refill() {
100
remain := len(x.out) - x.outUsed
101
copy(x.out, x.out[x.outUsed:])
@@ -74,6 +115,12 @@ func (x *ctr) refill() {
115
116
x.out = x.out[:remain]
117
x.outUsed = 0
118
119
+ if x.offsetPos > 0 {
120
+ offset := x.offsetPos % x.b.BlockSize()
121
+ x.out = x.out[offset:]
122
+ x.offsetPos = 0
123
124
125
126
func (x *ctr) XORKeyStream(dst, src []byte) {
src/crypto/cipher/ctr_aes_test.go
@@ -100,3 +100,40 @@ func TestCTR_AES(t *testing.T) {
102
103
104
+func TestCTRWithOffset_AES(t *testing.T) {
105
+ for _, tt := range ctrAESTests {
106
+ test := tt.name
107
108
+ c, err := aes.NewCipher(tt.key)
109
+ if err != nil {
110
+ t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
111
112
113
114
+ for j := 0; j <= 5; j += 5 {
+ in := tt.in[j : len(tt.in)-j]
+ ctr := cipher.NewCTRWithOffset(c, tt.iv, j)
+ encrypted := make([]byte, len(in))
+ ctr.XORKeyStream(encrypted, in)
+ if out := tt.out[j : len(in)+j]; !bytes.Equal(out, encrypted) {
+ t.Errorf("%s/%d: CTR\ninpt %x\nhave %x\nwant %x", test, len(in), in, encrypted, out)
+ for j := 0; j <= 7; j += 7 {
+ in := tt.out[j : len(tt.out)-j]
127
+ plain := make([]byte, len(in))
128
+ ctr.XORKeyStream(plain, in)
129
+ if out := tt.in[j : len(in)+j]; !bytes.Equal(out, plain) {
130
+ t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), plain, out)
131
132
133
134
+ if t.Failed() {
135
136
137
138
139
src/crypto/cipher/ctr_test.go
@@ -53,3 +53,36 @@ func TestCTR(t *testing.T) {
+var ctrAESIncreaseTests = []struct {
+ iv []byte
+ offset int
+ ivWant []byte
+}{
+ {
+ []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ 100*16,
+ []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100},
+ },
+ (100*256+100)*16,
+ []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100},
+ []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ (100*256*256*256)*16,
+ []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0},
+func TestIncreaseCtr(t *testing.T) {
+ for _, item :=range ctrAESIncreaseTests{
+ ivNext:=cipher.IncreaseCtr(item.offset, 16, item.iv)
+ if !bytes.Equal(ivNext, item.ivWant) {
+ t.Errorf("for iv %d\noffset %x\nwant %x", item.iv, item.offset, item.ivWant)
0 commit comments