1
2
3
4
5
6
7 package cipher
8
9 import (
10 "crypto/internal/alias"
11 "crypto/subtle"
12 )
13
14 type ofb struct {
15 b Block
16 cipher []byte
17 out []byte
18 outUsed int
19 }
20
21
22
23
24 func NewOFB(b Block, iv []byte) Stream {
25 blockSize := b.BlockSize()
26 if len(iv) != blockSize {
27 panic("cipher.NewOFB: IV length must equal block size")
28 }
29 bufSize := streamBufferSize
30 if bufSize < blockSize {
31 bufSize = blockSize
32 }
33 x := &ofb{
34 b: b,
35 cipher: make([]byte, blockSize),
36 out: make([]byte, 0, bufSize),
37 outUsed: 0,
38 }
39
40 copy(x.cipher, iv)
41 return x
42 }
43
44 func (x *ofb) refill() {
45 bs := x.b.BlockSize()
46 remain := len(x.out) - x.outUsed
47 if remain > x.outUsed {
48 return
49 }
50 copy(x.out, x.out[x.outUsed:])
51 x.out = x.out[:cap(x.out)]
52 for remain < len(x.out)-bs {
53 x.b.Encrypt(x.cipher, x.cipher)
54 copy(x.out[remain:], x.cipher)
55 remain += bs
56 }
57 x.out = x.out[:remain]
58 x.outUsed = 0
59 }
60
61 func (x *ofb) XORKeyStream(dst, src []byte) {
62 if len(dst) < len(src) {
63 panic("crypto/cipher: output smaller than input")
64 }
65 if alias.InexactOverlap(dst[:len(src)], src) {
66 panic("crypto/cipher: invalid buffer overlap")
67 }
68 for len(src) > 0 {
69 if x.outUsed >= len(x.out)-x.b.BlockSize() {
70 x.refill()
71 }
72 n := subtle.XORBytes(dst, src, x.out[x.outUsed:])
73 dst = dst[n:]
74 src = src[n:]
75 x.outUsed += n
76 }
77 }
78
View as plain text