summaryrefslogtreecommitdiff
path: root/libgo/go/crypto/cipher/cfb.go
blob: d14165a865661a0fee40bb5f727856cb869140d4 (plain)
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
54
55
56
57
58
59
60
61
62
63
64
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// CFB (Cipher Feedback) Mode.

package cipher

type cfb struct {
	b       Block
	out     []byte
	outUsed int
	decrypt bool
}

// NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode,
// using the given Block. The iv must be the same length as the Block's block
// size.
func NewCFBEncrypter(block Block, iv []byte) Stream {
	return newCFB(block, iv, false)
}

// NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode,
// using the given Block. The iv must be the same length as the Block's block
// size.
func NewCFBDecrypter(block Block, iv []byte) Stream {
	return newCFB(block, iv, true)
}

func newCFB(block Block, iv []byte, decrypt bool) Stream {
	blockSize := block.BlockSize()
	if len(iv) != blockSize {
		return nil
	}

	x := &cfb{
		b:       block,
		out:     make([]byte, blockSize),
		outUsed: 0,
		decrypt: decrypt,
	}
	block.Encrypt(x.out, iv)

	return x
}

func (x *cfb) XORKeyStream(dst, src []byte) {
	for i := 0; i < len(src); i++ {
		if x.outUsed == len(x.out) {
			x.b.Encrypt(x.out, x.out)
			x.outUsed = 0
		}

		if x.decrypt {
			t := src[i]
			dst[i] = src[i] ^ x.out[x.outUsed]
			x.out[x.outUsed] = t
		} else {
			x.out[x.outUsed] ^= src[i]
			dst[i] = x.out[x.outUsed]
		}
		x.outUsed++
	}
}