Home | History | Annotate | Download | only in cipher
      1 // Copyright 2012 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 package cipher_test
      6 
      7 import (
      8 	"crypto/aes"
      9 	"crypto/cipher"
     10 	"crypto/rand"
     11 	"encoding/hex"
     12 	"fmt"
     13 	"io"
     14 	"os"
     15 )
     16 
     17 func ExampleNewCBCDecrypter() {
     18 	key := []byte("example key 1234")
     19 	ciphertext, _ := hex.DecodeString("f363f3ccdcb12bb883abf484ba77d9cd7d32b5baecb3d4b1b3e0e4beffdb3ded")
     20 
     21 	block, err := aes.NewCipher(key)
     22 	if err != nil {
     23 		panic(err)
     24 	}
     25 
     26 	// The IV needs to be unique, but not secure. Therefore it's common to
     27 	// include it at the beginning of the ciphertext.
     28 	if len(ciphertext) < aes.BlockSize {
     29 		panic("ciphertext too short")
     30 	}
     31 	iv := ciphertext[:aes.BlockSize]
     32 	ciphertext = ciphertext[aes.BlockSize:]
     33 
     34 	// CBC mode always works in whole blocks.
     35 	if len(ciphertext)%aes.BlockSize != 0 {
     36 		panic("ciphertext is not a multiple of the block size")
     37 	}
     38 
     39 	mode := cipher.NewCBCDecrypter(block, iv)
     40 
     41 	// CryptBlocks can work in-place if the two arguments are the same.
     42 	mode.CryptBlocks(ciphertext, ciphertext)
     43 
     44 	// If the original plaintext lengths are not a multiple of the block
     45 	// size, padding would have to be added when encrypting, which would be
     46 	// removed at this point. For an example, see
     47 	// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's
     48 	// critical to note that ciphertexts must be authenticated (i.e. by
     49 	// using crypto/hmac) before being decrypted in order to avoid creating
     50 	// a padding oracle.
     51 
     52 	fmt.Printf("%s\n", ciphertext)
     53 	// Output: exampleplaintext
     54 }
     55 
     56 func ExampleNewCBCEncrypter() {
     57 	key := []byte("example key 1234")
     58 	plaintext := []byte("exampleplaintext")
     59 
     60 	// CBC mode works on blocks so plaintexts may need to be padded to the
     61 	// next whole block. For an example of such padding, see
     62 	// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
     63 	// assume that the plaintext is already of the correct length.
     64 	if len(plaintext)%aes.BlockSize != 0 {
     65 		panic("plaintext is not a multiple of the block size")
     66 	}
     67 
     68 	block, err := aes.NewCipher(key)
     69 	if err != nil {
     70 		panic(err)
     71 	}
     72 
     73 	// The IV needs to be unique, but not secure. Therefore it's common to
     74 	// include it at the beginning of the ciphertext.
     75 	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
     76 	iv := ciphertext[:aes.BlockSize]
     77 	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
     78 		panic(err)
     79 	}
     80 
     81 	mode := cipher.NewCBCEncrypter(block, iv)
     82 	mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
     83 
     84 	// It's important to remember that ciphertexts must be authenticated
     85 	// (i.e. by using crypto/hmac) as well as being encrypted in order to
     86 	// be secure.
     87 
     88 	fmt.Printf("%x\n", ciphertext)
     89 }
     90 
     91 func ExampleNewCFBDecrypter() {
     92 	key := []byte("example key 1234")
     93 	ciphertext, _ := hex.DecodeString("22277966616d9bc47177bd02603d08c9a67d5380d0fe8cf3b44438dff7b9")
     94 
     95 	block, err := aes.NewCipher(key)
     96 	if err != nil {
     97 		panic(err)
     98 	}
     99 
    100 	// The IV needs to be unique, but not secure. Therefore it's common to
    101 	// include it at the beginning of the ciphertext.
    102 	if len(ciphertext) < aes.BlockSize {
    103 		panic("ciphertext too short")
    104 	}
    105 	iv := ciphertext[:aes.BlockSize]
    106 	ciphertext = ciphertext[aes.BlockSize:]
    107 
    108 	stream := cipher.NewCFBDecrypter(block, iv)
    109 
    110 	// XORKeyStream can work in-place if the two arguments are the same.
    111 	stream.XORKeyStream(ciphertext, ciphertext)
    112 	fmt.Printf("%s", ciphertext)
    113 	// Output: some plaintext
    114 }
    115 
    116 func ExampleNewCFBEncrypter() {
    117 	key := []byte("example key 1234")
    118 	plaintext := []byte("some plaintext")
    119 
    120 	block, err := aes.NewCipher(key)
    121 	if err != nil {
    122 		panic(err)
    123 	}
    124 
    125 	// The IV needs to be unique, but not secure. Therefore it's common to
    126 	// include it at the beginning of the ciphertext.
    127 	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
    128 	iv := ciphertext[:aes.BlockSize]
    129 	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    130 		panic(err)
    131 	}
    132 
    133 	stream := cipher.NewCFBEncrypter(block, iv)
    134 	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
    135 
    136 	// It's important to remember that ciphertexts must be authenticated
    137 	// (i.e. by using crypto/hmac) as well as being encrypted in order to
    138 	// be secure.
    139 }
    140 
    141 func ExampleNewCTR() {
    142 	key := []byte("example key 1234")
    143 	plaintext := []byte("some plaintext")
    144 
    145 	block, err := aes.NewCipher(key)
    146 	if err != nil {
    147 		panic(err)
    148 	}
    149 
    150 	// The IV needs to be unique, but not secure. Therefore it's common to
    151 	// include it at the beginning of the ciphertext.
    152 	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
    153 	iv := ciphertext[:aes.BlockSize]
    154 	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    155 		panic(err)
    156 	}
    157 
    158 	stream := cipher.NewCTR(block, iv)
    159 	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
    160 
    161 	// It's important to remember that ciphertexts must be authenticated
    162 	// (i.e. by using crypto/hmac) as well as being encrypted in order to
    163 	// be secure.
    164 
    165 	// CTR mode is the same for both encryption and decryption, so we can
    166 	// also decrypt that ciphertext with NewCTR.
    167 
    168 	plaintext2 := make([]byte, len(plaintext))
    169 	stream = cipher.NewCTR(block, iv)
    170 	stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
    171 
    172 	fmt.Printf("%s\n", plaintext2)
    173 	// Output: some plaintext
    174 }
    175 
    176 func ExampleNewOFB() {
    177 	key := []byte("example key 1234")
    178 	plaintext := []byte("some plaintext")
    179 
    180 	block, err := aes.NewCipher(key)
    181 	if err != nil {
    182 		panic(err)
    183 	}
    184 
    185 	// The IV needs to be unique, but not secure. Therefore it's common to
    186 	// include it at the beginning of the ciphertext.
    187 	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
    188 	iv := ciphertext[:aes.BlockSize]
    189 	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    190 		panic(err)
    191 	}
    192 
    193 	stream := cipher.NewOFB(block, iv)
    194 	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
    195 
    196 	// It's important to remember that ciphertexts must be authenticated
    197 	// (i.e. by using crypto/hmac) as well as being encrypted in order to
    198 	// be secure.
    199 
    200 	// OFB mode is the same for both encryption and decryption, so we can
    201 	// also decrypt that ciphertext with NewOFB.
    202 
    203 	plaintext2 := make([]byte, len(plaintext))
    204 	stream = cipher.NewOFB(block, iv)
    205 	stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
    206 
    207 	fmt.Printf("%s\n", plaintext2)
    208 	// Output: some plaintext
    209 }
    210 
    211 func ExampleStreamReader() {
    212 	key := []byte("example key 1234")
    213 
    214 	inFile, err := os.Open("encrypted-file")
    215 	if err != nil {
    216 		panic(err)
    217 	}
    218 	defer inFile.Close()
    219 
    220 	block, err := aes.NewCipher(key)
    221 	if err != nil {
    222 		panic(err)
    223 	}
    224 
    225 	// If the key is unique for each ciphertext, then it's ok to use a zero
    226 	// IV.
    227 	var iv [aes.BlockSize]byte
    228 	stream := cipher.NewOFB(block, iv[:])
    229 
    230 	outFile, err := os.OpenFile("decrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    231 	if err != nil {
    232 		panic(err)
    233 	}
    234 	defer outFile.Close()
    235 
    236 	reader := &cipher.StreamReader{S: stream, R: inFile}
    237 	// Copy the input file to the output file, decrypting as we go.
    238 	if _, err := io.Copy(outFile, reader); err != nil {
    239 		panic(err)
    240 	}
    241 
    242 	// Note that this example is simplistic in that it omits any
    243 	// authentication of the encrypted data. If you were actually to use
    244 	// StreamReader in this manner, an attacker could flip arbitrary bits in
    245 	// the output.
    246 }
    247 
    248 func ExampleStreamWriter() {
    249 	key := []byte("example key 1234")
    250 
    251 	inFile, err := os.Open("plaintext-file")
    252 	if err != nil {
    253 		panic(err)
    254 	}
    255 	defer inFile.Close()
    256 
    257 	block, err := aes.NewCipher(key)
    258 	if err != nil {
    259 		panic(err)
    260 	}
    261 
    262 	// If the key is unique for each ciphertext, then it's ok to use a zero
    263 	// IV.
    264 	var iv [aes.BlockSize]byte
    265 	stream := cipher.NewOFB(block, iv[:])
    266 
    267 	outFile, err := os.OpenFile("encrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    268 	if err != nil {
    269 		panic(err)
    270 	}
    271 	defer outFile.Close()
    272 
    273 	writer := &cipher.StreamWriter{S: stream, W: outFile}
    274 	// Copy the input file to the output file, encrypting as we go.
    275 	if _, err := io.Copy(writer, inFile); err != nil {
    276 		panic(err)
    277 	}
    278 
    279 	// Note that this example is simplistic in that it omits any
    280 	// authentication of the encrypted data. If you were actually to use
    281 	// StreamReader in this manner, an attacker could flip arbitrary bits in
    282 	// the decrypted result.
    283 }
    284