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  }