Commit a9aef26a authored by Rob Pike's avatar Rob Pike

effective_go: fix up the description of cipher blocks and streams

R=golang-dev, r, agl, dsymonds
CC=golang-dev
https://golang.org/cl/5374046
parent 217408ab
...@@ -1915,42 +1915,53 @@ the rest of the code is unaffected by the change of algorithm. ...@@ -1915,42 +1915,53 @@ the rest of the code is unaffected by the change of algorithm.
</p> </p>
<p> <p>
A similar approach allows the streaming cipher algorithms A similar approach allows the streaming cipher algorithms
in the <code>crypto/block</code> package to be in the various <code>crypto</code> packages to be
separated from the block ciphers they chain together. separated from the block ciphers they chain together.
By analogy with the <code>bufio</code> package, The <code>Block</code> interface
they wrap a <code>Cipher</code> interface in the <code>crypto/cipher</code>package specifies the
and return <code>hash.Hash</code>, behavior of a block cipher, which provides encryption
<code>io.Reader</code>, or <code>io.Writer</code> of a single block of data.
interface values, not specific implementations. Then, by analogy with the <code>bufio</code> package,
cipher packages that implement this interface
can be used to construct streaming ciphers, represented
by the <code>Stream</code> interface, without
knowing the details of the block encryption.
</p> </p>
<p> <p>
The interface to <code>crypto/block</code> includes: The <code>crypto/cipher</code> interfaces look like this:
</p> </p>
<pre> <pre>
type Cipher interface { type Block interface {
BlockSize() int BlockSize() int
Encrypt(src, dst []byte) Encrypt(src, dst []byte)
Decrypt(src, dst []byte) Decrypt(src, dst []byte)
} }
// NewECBDecrypter returns a reader that reads data type Stream interface {
// from r and decrypts it using c in electronic codebook (ECB) mode. XORKeyStream(dst, src []byte)
func NewECBDecrypter(c Cipher, r io.Reader) io.Reader }
</pre>
<p>
Here's the definition of the counter mode (CTR) stream,
which turns a block cipher into a streaming cipher; notice
that the block cipher's details are abstracted away:
</p>
// NewCBCDecrypter returns a reader that reads data <pre>
// from r and decrypts it using c in cipher block chaining (CBC) mode // NewCTR returns a Stream that encrypts/decrypts using the given Block in
// with the initialization vector iv. // counter mode. The length of iv must be the same as the Block's block size.
func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader func NewCTR(block Block, iv []byte) Stream
</pre> </pre>
<p> <p>
<code>NewECBDecrypter</code> and <code>NewCBCReader</code> apply not <code>NewCTR</code> applies not
just to one specific encryption algorithm and data source but to any just to one specific encryption algorithm and data source but to any
implementation of the <code>Cipher</code> interface and any implementation of the <code>Block</code> interface and any
<code>io.Reader</code>. Because they return <code>io.Reader</code> <code>Stream</code>. Because they return
interface values, replacing ECB interface values, replacing CTR
encryption with CBC encryption is a localized change. The constructor encryption with other encryption modes is a localized change. The constructor
calls must be edited, but because the surrounding code must treat the result only calls must be edited, but because the surrounding code must treat the result only
as an <code>io.Reader</code>, it won't notice the difference. as a <code>Stream</code>, it won't notice the difference.
</p> </p>
<h3 id="interface_methods">Interfaces and methods</h3> <h3 id="interface_methods">Interfaces and methods</h3>
...@@ -2930,8 +2941,7 @@ import ( ...@@ -2930,8 +2941,7 @@ import (
&#34;text/template&#34; &#34;text/template&#34;
) )
var // Q=17, R=18 var addr = flag.String(&#34;addr&#34;, &#34;:1718&#34;, &#34;http service address&#34;) // Q=17, R=18
addr = flag.String(&#34;addr&#34;, &#34;:1718&#34;, &#34;http service address&#34;)
var templ = template.Must(template.New(&#34;qr&#34;).Parse(templateStr)) var templ = template.Must(template.New(&#34;qr&#34;).Parse(templateStr))
......
...@@ -1853,42 +1853,53 @@ the rest of the code is unaffected by the change of algorithm. ...@@ -1853,42 +1853,53 @@ the rest of the code is unaffected by the change of algorithm.
</p> </p>
<p> <p>
A similar approach allows the streaming cipher algorithms A similar approach allows the streaming cipher algorithms
in the <code>crypto/block</code> package to be in the various <code>crypto</code> packages to be
separated from the block ciphers they chain together. separated from the block ciphers they chain together.
By analogy with the <code>bufio</code> package, The <code>Block</code> interface
they wrap a <code>Cipher</code> interface in the <code>crypto/cipher</code>package specifies the
and return <code>hash.Hash</code>, behavior of a block cipher, which provides encryption
<code>io.Reader</code>, or <code>io.Writer</code> of a single block of data.
interface values, not specific implementations. Then, by analogy with the <code>bufio</code> package,
cipher packages that implement this interface
can be used to construct streaming ciphers, represented
by the <code>Stream</code> interface, without
knowing the details of the block encryption.
</p> </p>
<p> <p>
The interface to <code>crypto/block</code> includes: The <code>crypto/cipher</code> interfaces look like this:
</p> </p>
<pre> <pre>
type Cipher interface { type Block interface {
BlockSize() int BlockSize() int
Encrypt(src, dst []byte) Encrypt(src, dst []byte)
Decrypt(src, dst []byte) Decrypt(src, dst []byte)
} }
// NewECBDecrypter returns a reader that reads data type Stream interface {
// from r and decrypts it using c in electronic codebook (ECB) mode. XORKeyStream(dst, src []byte)
func NewECBDecrypter(c Cipher, r io.Reader) io.Reader }
</pre>
<p>
Here's the definition of the counter mode (CTR) stream,
which turns a block cipher into a streaming cipher; notice
that the block cipher's details are abstracted away:
</p>
// NewCBCDecrypter returns a reader that reads data <pre>
// from r and decrypts it using c in cipher block chaining (CBC) mode // NewCTR returns a Stream that encrypts/decrypts using the given Block in
// with the initialization vector iv. // counter mode. The length of iv must be the same as the Block's block size.
func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader func NewCTR(block Block, iv []byte) Stream
</pre> </pre>
<p> <p>
<code>NewECBDecrypter</code> and <code>NewCBCReader</code> apply not <code>NewCTR</code> applies not
just to one specific encryption algorithm and data source but to any just to one specific encryption algorithm and data source but to any
implementation of the <code>Cipher</code> interface and any implementation of the <code>Block</code> interface and any
<code>io.Reader</code>. Because they return <code>io.Reader</code> <code>Stream</code>. Because they return
interface values, replacing ECB interface values, replacing CTR
encryption with CBC encryption is a localized change. The constructor encryption with other encryption modes is a localized change. The constructor
calls must be edited, but because the surrounding code must treat the result only calls must be edited, but because the surrounding code must treat the result only
as an <code>io.Reader</code>, it won't notice the difference. as a <code>Stream</code>, it won't notice the difference.
</p> </p>
<h3 id="interface_methods">Interfaces and methods</h3> <h3 id="interface_methods">Interfaces and methods</h3>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment