github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/src/crypto/cipher/example_test.go (about) 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 }