diff options
Diffstat (limited to 'src/crypto/cipher/ofb.go')
-rw-r--r-- | src/crypto/cipher/ofb.go | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/crypto/cipher/ofb.go b/src/crypto/cipher/ofb.go new file mode 100644 index 0000000..1195fdd --- /dev/null +++ b/src/crypto/cipher/ofb.go @@ -0,0 +1,77 @@ +// Copyright 2011 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. + +// OFB (Output Feedback) Mode. + +package cipher + +import ( + "crypto/internal/alias" + "crypto/subtle" +) + +type ofb struct { + b Block + cipher []byte + out []byte + outUsed int +} + +// NewOFB returns a Stream that encrypts or decrypts using the block cipher b +// in output feedback mode. The initialization vector iv's length must be equal +// to b's block size. +func NewOFB(b Block, iv []byte) Stream { + blockSize := b.BlockSize() + if len(iv) != blockSize { + panic("cipher.NewOFB: IV length must equal block size") + } + bufSize := streamBufferSize + if bufSize < blockSize { + bufSize = blockSize + } + x := &ofb{ + b: b, + cipher: make([]byte, blockSize), + out: make([]byte, 0, bufSize), + outUsed: 0, + } + + copy(x.cipher, iv) + return x +} + +func (x *ofb) refill() { + bs := x.b.BlockSize() + remain := len(x.out) - x.outUsed + if remain > x.outUsed { + return + } + copy(x.out, x.out[x.outUsed:]) + x.out = x.out[:cap(x.out)] + for remain < len(x.out)-bs { + x.b.Encrypt(x.cipher, x.cipher) + copy(x.out[remain:], x.cipher) + remain += bs + } + x.out = x.out[:remain] + x.outUsed = 0 +} + +func (x *ofb) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if alias.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + for len(src) > 0 { + if x.outUsed >= len(x.out)-x.b.BlockSize() { + x.refill() + } + n := subtle.XORBytes(dst, src, x.out[x.outUsed:]) + dst = dst[n:] + src = src[n:] + x.outUsed += n + } +} |