| // Copyright 2009 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. |
| |
| // Counter (CTR) mode. |
| |
| // CTR converts a block cipher into a stream cipher by |
| // repeatedly encrypting an incrementing counter and |
| // xoring the resulting stream of data with the input. |
| |
| // See NIST SP 800-38A, pp 13-15 |
| |
| package block |
| |
| import ( |
| "crypto/block"; |
| "io"; |
| ) |
| |
| type ctrStream struct { |
| c Cipher; |
| ctr []byte; |
| out []byte; |
| } |
| |
| func newCTRStream(c Cipher, ctr []byte) *ctrStream { |
| x := new(ctrStream); |
| x.c = c; |
| x.ctr = copy(ctr); |
| x.out = make([]byte, len(ctr)); |
| return x; |
| } |
| |
| func (x *ctrStream) Next() []byte { |
| // Next block is encryption of counter. |
| x.c.Encrypt(x.ctr, x.out); |
| |
| // Increment counter |
| for i := len(x.ctr) - 1; i >= 0; i-- { |
| x.ctr[i]++; |
| if x.ctr[i] != 0 { |
| break; |
| } |
| } |
| |
| return x.out; |
| } |
| |
| // NewCTRReader returns a reader that reads data from r, decrypts (or encrypts) |
| // it using c in counter (CTR) mode with the initialization vector iv. |
| // The returned Reader does not buffer and has no block size. |
| // In CTR mode, encryption and decryption are the same operation: |
| // a CTR reader applied to an encrypted stream produces a decrypted |
| // stream and vice versa. |
| func NewCTRReader(c Cipher, iv []byte, r io.Reader) io.Reader { |
| return newXorReader(newCTRStream(c, iv), r); |
| } |
| |
| // NewCTRWriter returns a writer that encrypts (or decrypts) data using c |
| // in counter (CTR) mode with the initialization vector iv |
| // and writes the encrypted data to w. |
| // The returned Writer does not buffer and has no block size. |
| // In CTR mode, encryption and decryption are the same operation: |
| // a CTR writer applied to an decrypted stream produces an encrypted |
| // stream and vice versa. |
| func NewCTRWriter(c Cipher, iv []byte, w io.Writer) io.Writer { |
| return newXorWriter(newCTRStream(c, iv), w); |
| } |
| |