github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/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 ExampleNewGCMEncrypter() { 18 // The key argument should be the AES key, either 16 or 32 bytes 19 // to select AES-128 or AES-256. 20 key := []byte("AES256Key-32Characters1234567890") 21 plaintext := []byte("exampleplaintext") 22 23 block, err := aes.NewCipher(key) 24 if err != nil { 25 panic(err.Error()) 26 } 27 28 // Never use more than 2^32 random nonces with a given key because of the risk of a repeat. 29 nonce := make([]byte, 12) 30 if _, err := io.ReadFull(rand.Reader, nonce); err != nil { 31 panic(err.Error()) 32 } 33 34 aesgcm, err := cipher.NewGCM(block) 35 if err != nil { 36 panic(err.Error()) 37 } 38 39 ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil) 40 fmt.Printf("%x\n", ciphertext) 41 } 42 43 func ExampleNewGCMDecrypter() { 44 // The key argument should be the AES key, either 16 or 32 bytes 45 // to select AES-128 or AES-256. 46 key := []byte("AES256Key-32Characters1234567890") 47 ciphertext, _ := hex.DecodeString("f90fbef747e7212ad7410d0eee2d965de7e890471695cddd2a5bc0ef5da1d04ad8147b62141ad6e4914aee8c512f64fba9037603d41de0d50b718bd665f019cdcd") 48 49 nonce, _ := hex.DecodeString("bb8ef84243d2ee95a41c6c57") 50 51 block, err := aes.NewCipher(key) 52 if err != nil { 53 panic(err.Error()) 54 } 55 56 aesgcm, err := cipher.NewGCM(block) 57 if err != nil { 58 panic(err.Error()) 59 } 60 61 plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil) 62 if err != nil { 63 panic(err.Error()) 64 } 65 66 fmt.Printf("%s\n", string(plaintext)) 67 } 68 69 func ExampleNewCBCDecrypter() { 70 key := []byte("example key 1234") 71 ciphertext, _ := hex.DecodeString("f363f3ccdcb12bb883abf484ba77d9cd7d32b5baecb3d4b1b3e0e4beffdb3ded") 72 73 block, err := aes.NewCipher(key) 74 if err != nil { 75 panic(err) 76 } 77 78 // The IV needs to be unique, but not secure. Therefore it's common to 79 // include it at the beginning of the ciphertext. 80 if len(ciphertext) < aes.BlockSize { 81 panic("ciphertext too short") 82 } 83 iv := ciphertext[:aes.BlockSize] 84 ciphertext = ciphertext[aes.BlockSize:] 85 86 // CBC mode always works in whole blocks. 87 if len(ciphertext)%aes.BlockSize != 0 { 88 panic("ciphertext is not a multiple of the block size") 89 } 90 91 mode := cipher.NewCBCDecrypter(block, iv) 92 93 // CryptBlocks can work in-place if the two arguments are the same. 94 mode.CryptBlocks(ciphertext, ciphertext) 95 96 // If the original plaintext lengths are not a multiple of the block 97 // size, padding would have to be added when encrypting, which would be 98 // removed at this point. For an example, see 99 // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's 100 // critical to note that ciphertexts must be authenticated (i.e. by 101 // using crypto/hmac) before being decrypted in order to avoid creating 102 // a padding oracle. 103 104 fmt.Printf("%s\n", ciphertext) 105 // Output: exampleplaintext 106 } 107 108 func ExampleNewCBCEncrypter() { 109 key := []byte("example key 1234") 110 plaintext := []byte("exampleplaintext") 111 112 // CBC mode works on blocks so plaintexts may need to be padded to the 113 // next whole block. For an example of such padding, see 114 // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll 115 // assume that the plaintext is already of the correct length. 116 if len(plaintext)%aes.BlockSize != 0 { 117 panic("plaintext is not a multiple of the block size") 118 } 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 mode := cipher.NewCBCEncrypter(block, iv) 134 mode.CryptBlocks(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 fmt.Printf("%x\n", ciphertext) 141 } 142 143 func ExampleNewCFBDecrypter() { 144 key := []byte("example key 1234") 145 ciphertext, _ := hex.DecodeString("22277966616d9bc47177bd02603d08c9a67d5380d0fe8cf3b44438dff7b9") 146 147 block, err := aes.NewCipher(key) 148 if err != nil { 149 panic(err) 150 } 151 152 // The IV needs to be unique, but not secure. Therefore it's common to 153 // include it at the beginning of the ciphertext. 154 if len(ciphertext) < aes.BlockSize { 155 panic("ciphertext too short") 156 } 157 iv := ciphertext[:aes.BlockSize] 158 ciphertext = ciphertext[aes.BlockSize:] 159 160 stream := cipher.NewCFBDecrypter(block, iv) 161 162 // XORKeyStream can work in-place if the two arguments are the same. 163 stream.XORKeyStream(ciphertext, ciphertext) 164 fmt.Printf("%s", ciphertext) 165 // Output: some plaintext 166 } 167 168 func ExampleNewCFBEncrypter() { 169 key := []byte("example key 1234") 170 plaintext := []byte("some plaintext") 171 172 block, err := aes.NewCipher(key) 173 if err != nil { 174 panic(err) 175 } 176 177 // The IV needs to be unique, but not secure. Therefore it's common to 178 // include it at the beginning of the ciphertext. 179 ciphertext := make([]byte, aes.BlockSize+len(plaintext)) 180 iv := ciphertext[:aes.BlockSize] 181 if _, err := io.ReadFull(rand.Reader, iv); err != nil { 182 panic(err) 183 } 184 185 stream := cipher.NewCFBEncrypter(block, iv) 186 stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) 187 188 // It's important to remember that ciphertexts must be authenticated 189 // (i.e. by using crypto/hmac) as well as being encrypted in order to 190 // be secure. 191 } 192 193 func ExampleNewCTR() { 194 key := []byte("example key 1234") 195 plaintext := []byte("some plaintext") 196 197 block, err := aes.NewCipher(key) 198 if err != nil { 199 panic(err) 200 } 201 202 // The IV needs to be unique, but not secure. Therefore it's common to 203 // include it at the beginning of the ciphertext. 204 ciphertext := make([]byte, aes.BlockSize+len(plaintext)) 205 iv := ciphertext[:aes.BlockSize] 206 if _, err := io.ReadFull(rand.Reader, iv); err != nil { 207 panic(err) 208 } 209 210 stream := cipher.NewCTR(block, iv) 211 stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) 212 213 // It's important to remember that ciphertexts must be authenticated 214 // (i.e. by using crypto/hmac) as well as being encrypted in order to 215 // be secure. 216 217 // CTR mode is the same for both encryption and decryption, so we can 218 // also decrypt that ciphertext with NewCTR. 219 220 plaintext2 := make([]byte, len(plaintext)) 221 stream = cipher.NewCTR(block, iv) 222 stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:]) 223 224 fmt.Printf("%s\n", plaintext2) 225 // Output: some plaintext 226 } 227 228 func ExampleNewOFB() { 229 key := []byte("example key 1234") 230 plaintext := []byte("some plaintext") 231 232 block, err := aes.NewCipher(key) 233 if err != nil { 234 panic(err) 235 } 236 237 // The IV needs to be unique, but not secure. Therefore it's common to 238 // include it at the beginning of the ciphertext. 239 ciphertext := make([]byte, aes.BlockSize+len(plaintext)) 240 iv := ciphertext[:aes.BlockSize] 241 if _, err := io.ReadFull(rand.Reader, iv); err != nil { 242 panic(err) 243 } 244 245 stream := cipher.NewOFB(block, iv) 246 stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) 247 248 // It's important to remember that ciphertexts must be authenticated 249 // (i.e. by using crypto/hmac) as well as being encrypted in order to 250 // be secure. 251 252 // OFB mode is the same for both encryption and decryption, so we can 253 // also decrypt that ciphertext with NewOFB. 254 255 plaintext2 := make([]byte, len(plaintext)) 256 stream = cipher.NewOFB(block, iv) 257 stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:]) 258 259 fmt.Printf("%s\n", plaintext2) 260 // Output: some plaintext 261 } 262 263 func ExampleStreamReader() { 264 key := []byte("example key 1234") 265 266 inFile, err := os.Open("encrypted-file") 267 if err != nil { 268 panic(err) 269 } 270 defer inFile.Close() 271 272 block, err := aes.NewCipher(key) 273 if err != nil { 274 panic(err) 275 } 276 277 // If the key is unique for each ciphertext, then it's ok to use a zero 278 // IV. 279 var iv [aes.BlockSize]byte 280 stream := cipher.NewOFB(block, iv[:]) 281 282 outFile, err := os.OpenFile("decrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 283 if err != nil { 284 panic(err) 285 } 286 defer outFile.Close() 287 288 reader := &cipher.StreamReader{S: stream, R: inFile} 289 // Copy the input file to the output file, decrypting as we go. 290 if _, err := io.Copy(outFile, reader); err != nil { 291 panic(err) 292 } 293 294 // Note that this example is simplistic in that it omits any 295 // authentication of the encrypted data. If you were actually to use 296 // StreamReader in this manner, an attacker could flip arbitrary bits in 297 // the output. 298 } 299 300 func ExampleStreamWriter() { 301 key := []byte("example key 1234") 302 303 inFile, err := os.Open("plaintext-file") 304 if err != nil { 305 panic(err) 306 } 307 defer inFile.Close() 308 309 block, err := aes.NewCipher(key) 310 if err != nil { 311 panic(err) 312 } 313 314 // If the key is unique for each ciphertext, then it's ok to use a zero 315 // IV. 316 var iv [aes.BlockSize]byte 317 stream := cipher.NewOFB(block, iv[:]) 318 319 outFile, err := os.OpenFile("encrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 320 if err != nil { 321 panic(err) 322 } 323 defer outFile.Close() 324 325 writer := &cipher.StreamWriter{S: stream, W: outFile} 326 // Copy the input file to the output file, encrypting as we go. 327 if _, err := io.Copy(writer, inFile); err != nil { 328 panic(err) 329 } 330 331 // Note that this example is simplistic in that it omits any 332 // authentication of the encrypted data. If you were actually to use 333 // StreamReader in this manner, an attacker could flip arbitrary bits in 334 // the decrypted result. 335 }