github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/src/crypto/cipher/ctr.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Counter (CTR) mode. 6 7 // CTR converts a block cipher into a stream cipher by 8 // repeatedly encrypting an incrementing counter and 9 // xoring the resulting stream of data with the input. 10 11 // See NIST SP 800-38A, pp 13-15 12 13 package cipher 14 15 type ctr struct { 16 b Block 17 ctr []byte 18 out []byte 19 outUsed int 20 } 21 22 const streamBufferSize = 512 23 24 // NewCTR returns a Stream which encrypts/decrypts using the given Block in 25 // counter mode. The length of iv must be the same as the Block's block size. 26 func NewCTR(block Block, iv []byte) Stream { 27 if len(iv) != block.BlockSize() { 28 panic("cipher.NewCTR: IV length must equal block size") 29 } 30 bufSize := streamBufferSize 31 if bufSize < block.BlockSize() { 32 bufSize = block.BlockSize() 33 } 34 return &ctr{ 35 b: block, 36 ctr: dup(iv), 37 out: make([]byte, 0, bufSize), 38 outUsed: 0, 39 } 40 } 41 42 func (x *ctr) refill() { 43 remain := len(x.out) - x.outUsed 44 copy(x.out, x.out[x.outUsed:]) 45 x.out = x.out[:cap(x.out)] 46 bs := x.b.BlockSize() 47 for remain <= len(x.out)-bs { 48 x.b.Encrypt(x.out[remain:], x.ctr) 49 remain += bs 50 51 // Increment counter 52 for i := len(x.ctr) - 1; i >= 0; i-- { 53 x.ctr[i]++ 54 if x.ctr[i] != 0 { 55 break 56 } 57 } 58 } 59 x.out = x.out[:remain] 60 x.outUsed = 0 61 } 62 63 func (x *ctr) XORKeyStream(dst, src []byte) { 64 for len(src) > 0 { 65 if x.outUsed >= len(x.out)-x.b.BlockSize() { 66 x.refill() 67 } 68 n := xorBytes(dst, src, x.out[x.outUsed:]) 69 dst = dst[n:] 70 src = src[n:] 71 x.outUsed += n 72 } 73 }