| // 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. |
| |
| // Electronic codebook (ECB) mode. |
| // ECB is a fancy name for ``encrypt and decrypt each block separately.'' |
| // It's a pretty bad thing to do for any large amount of data (more than one block), |
| // because the individual blocks can still be identified, duplicated, and reordered. |
| // The ECB implementation exists mainly to provide buffering for |
| // the other modes, which wrap it by providing modified Ciphers. |
| |
| // See NIST SP 800-38A, pp 9-10 |
| |
| package block |
| |
| import ( |
| "io"; |
| "os"; |
| "strconv"; |
| ) |
| |
| type ecbDecrypter struct { |
| c Cipher; |
| r io.Reader; |
| blockSize int; // block size |
| |
| // Buffered data. |
| // The buffer buf is used as storage for both |
| // plain or crypt; at least one of those is nil at any given time. |
| buf []byte; |
| plain []byte; // plain text waiting to be read |
| crypt []byte; // ciphertext waiting to be decrypted |
| } |
| |
| // Read into x.crypt until it has a full block or EOF or an error happens. |
| func (x *ecbDecrypter) fillCrypt() os.Error { |
| var err os.Error; |
| for len(x.crypt) < x.blockSize { |
| off := len(x.crypt); |
| var m int; |
| m, err = x.r.Read(x.crypt[off:x.blockSize]); |
| x.crypt = x.crypt[0:off+m]; |
| if m == 0 { |
| break; |
| } |
| |
| // If an error happened but we got enough |
| // data to do some decryption, we can decrypt |
| // first and report the error (with some data) later. |
| // But if we don't have enough to decrypt, |
| // have to stop now. |
| if err != nil && len(x.crypt) < x.blockSize { |
| break; |
| } |
| } |
| return err; |
| } |
| |
| // Read from plain text buffer into p. |
| func (x *ecbDecrypter) readPlain(p []byte) int { |
| n := len(x.plain); |
| if n > len(p) { |
| n = len(p); |
| } |
| for i := 0; i < n; i++ { |
| p[i] = x.plain[i]; |
| } |
| if n < len(x.plain) { |
| x.plain = x.plain[n:len(x.plain)]; |
| } else { |
| x.plain = nil; |
| } |
| return n; |
| } |
| |
| type ecbFragmentError int |
| func (n ecbFragmentError) String() string { |
| return "crypto/block: " + strconv.Itoa(int(n)) + "-byte fragment at EOF"; |
| } |
| |
| func (x *ecbDecrypter) Read(p []byte) (n int, err os.Error) { |
| if len(p) == 0 { |
| return; |
| } |
| |
| // If there's no plaintext waiting and p is not big enough |
| // to hold a whole cipher block, we'll have to work in the |
| // cipher text buffer. Set it to non-nil so that the |
| // code below will fill it. |
| if x.plain == nil && len(p) < x.blockSize && x.crypt == nil { |
| x.crypt = x.buf[0:0]; |
| } |
| |
| // If there is a leftover cipher text buffer, |
| // try to accumulate a full block. |
| if x.crypt != nil { |
| err = x.fillCrypt(); |
| if err != nil || len(x.crypt) == 0 { |
| return; |
| } |
| x.c.Decrypt(x.crypt, x.crypt); |
| x.plain = x.crypt; |
| x.crypt = nil; |
| } |
| |
| // If there is a leftover plain text buffer, read from it. |
| if x.plain != nil { |
| n = x.readPlain(p); |
| return; |
| } |
| |
| // Read and decrypt directly in caller's buffer. |
| n, err = io.ReadAtLeast(x.r, p, x.blockSize); |
| if err == os.EOF && n > 0 { |
| // EOF is only okay on block boundary |
| err = os.ErrorString("block fragment at EOF during decryption"); |
| return; |
| } |
| var i int; |
| for i = 0; i+x.blockSize <= n; i += x.blockSize { |
| a := p[i:i+x.blockSize]; |
| x.c.Decrypt(a, a); |
| } |
| |
| // There might be an encrypted fringe remaining. |
| // Save it for next time. |
| if i < n { |
| p = p[i:n]; |
| for j, v := range p { |
| x.buf[j] = v; |
| } |
| x.crypt = x.buf[0:len(p)]; |
| n = i; |
| } |
| |
| return; |
| } |
| |
| // NewECBDecrypter returns a reader that reads data from r and decrypts it using c. |
| // It decrypts by calling c.Decrypt on each block in sequence; |
| // this mode is known as electronic codebook mode, or ECB. |
| // The returned Reader does not buffer or read ahead except |
| // as required by the cipher's block size. |
| func NewECBDecrypter(c Cipher, r io.Reader) io.Reader { |
| x := new(ecbDecrypter); |
| x.c = c; |
| x.r = r; |
| x.blockSize = c.BlockSize(); |
| x.buf = make([]byte, x.blockSize); |
| return x; |
| } |
| |
| type ecbEncrypter struct { |
| c Cipher; |
| w io.Writer; |
| blockSize int; |
| |
| // Buffered data. |
| // The buffer buf is used as storage for both |
| // plain or crypt. If both are non-nil, plain |
| // follows crypt in buf. |
| buf []byte; |
| plain []byte; // plain text waiting to be encrypted |
| crypt []byte; // encrypted text waiting to be written |
| } |
| |
| // Flush the x.crypt buffer to x.w. |
| func (x *ecbEncrypter) flushCrypt() os.Error { |
| if len(x.crypt) == 0 { |
| return nil; |
| } |
| n, err := x.w.Write(x.crypt); |
| if n < len(x.crypt) { |
| x.crypt = x.crypt[n:len(x.crypt)]; |
| if err == nil { |
| err = io.ErrShortWrite; |
| } |
| } |
| if err != nil { |
| return err; |
| } |
| x.crypt = nil; |
| return nil; |
| } |
| |
| // Slide x.plain down to the beginning of x.buf. |
| // Plain is known to have less than one block of data, |
| // so this is cheap enough. |
| func (x *ecbEncrypter) slidePlain() { |
| if len(x.plain) == 0 { |
| x.plain = x.buf[0:0]; |
| } else if cap(x.plain) < cap(x.buf) { |
| // plain and buf share same data, |
| // but buf is before plain, so forward loop is correct |
| for i := 0; i < len(x.plain); i++ { |
| x.buf[i] = x.plain[i]; |
| } |
| x.plain = x.buf[0:len(x.plain)]; |
| } |
| } |
| |
| // Fill x.plain from the data in p. |
| // Return the number of bytes copied. |
| func (x *ecbEncrypter) fillPlain(p []byte) int { |
| off := len(x.plain); |
| n := len(p); |
| if max := cap(x.plain) - off; n > max { |
| n = max; |
| } |
| x.plain = x.plain[0:off+n]; |
| for i := 0; i < n; i++ { |
| x.plain[off + i] = p[i]; |
| } |
| return n; |
| } |
| |
| // Encrypt x.plain; record encrypted range as x.crypt. |
| func (x *ecbEncrypter) encrypt() { |
| var i int; |
| n := len(x.plain); |
| for i = 0; i+x.blockSize <= n; i += x.blockSize { |
| a := x.plain[i:i+x.blockSize]; |
| x.c.Encrypt(a, a); |
| } |
| x.crypt = x.plain[0:i]; |
| x.plain = x.plain[i:n]; |
| } |
| |
| func (x *ecbEncrypter) Write(p []byte) (n int, err os.Error) { |
| for { |
| // If there is data waiting to be written, write it. |
| // This can happen on the first iteration |
| // if a write failed in an earlier call. |
| if err = x.flushCrypt(); err != nil { |
| return; |
| } |
| |
| // Now that encrypted data is gone (flush ran), |
| // perhaps we need to slide the plaintext down. |
| x.slidePlain(); |
| |
| // Fill plaintext buffer from p. |
| m := x.fillPlain(p); |
| if m == 0 { |
| break; |
| } |
| n += m; |
| p = p[m:len(p)]; |
| |
| // Encrypt, adjusting crypt and plain. |
| x.encrypt(); |
| |
| // Write x.crypt. |
| if err = x.flushCrypt(); err != nil { |
| break; |
| } |
| } |
| return; |
| } |
| |
| // NewECBEncrypter returns a writer that encrypts data using c and writes it to w. |
| // It encrypts by calling c.Encrypt on each block in sequence; |
| // this mode is known as electronic codebook mode, or ECB. |
| // The returned Writer does no buffering except as required |
| // by the cipher's block size, so there is no need for a Flush method. |
| func NewECBEncrypter(c Cipher, w io.Writer) io.Writer { |
| x := new(ecbEncrypter); |
| x.c = c; |
| x.w = w; |
| x.blockSize = c.BlockSize(); |
| |
| // Create a buffer that is an integral number of blocks. |
| x.buf = make([]byte, 8192/x.blockSize * x.blockSize); |
| return x; |
| } |
| |