// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package cipher_test import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/des" "crypto/internal/cryptotest" "crypto/rand" "encoding/hex" "fmt" "testing" ) // cfbTests contains the test vectors from // https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section // F.3.13. var cfbTests = []struct { key, iv, plaintext, ciphertext string }{ { "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090a0b0c0d0e0f", "6bc1bee22e409f96e93d7e117393172a", "3b3fd92eb72dad20333449f8e83cfb4a", }, { "2b7e151628aed2a6abf7158809cf4f3c", "3B3FD92EB72DAD20333449F8E83CFB4A", "ae2d8a571e03ac9c9eb76fac45af8e51", "c8a64537a0b3a93fcde3cdad9f1ce58b", }, { "2b7e151628aed2a6abf7158809cf4f3c", "C8A64537A0B3A93FCDE3CDAD9F1CE58B", "30c81c46a35ce411e5fbc1191a0a52ef", "26751f67a3cbb140b1808cf187a4f4df", }, { "2b7e151628aed2a6abf7158809cf4f3c", "26751F67A3CBB140B1808CF187A4F4DF", "f69f2445df4f9b17ad2b417be66c3710", "c04b05357c5d1c0eeac4c66f9ff7f2e6", }, } func TestCFBVectors(t *testing.T) { for i, test := range cfbTests { key, err := hex.DecodeString(test.key) if err != nil { t.Fatal(err) } iv, err := hex.DecodeString(test.iv) if err != nil { t.Fatal(err) } plaintext, err := hex.DecodeString(test.plaintext) if err != nil { t.Fatal(err) } expected, err := hex.DecodeString(test.ciphertext) if err != nil { t.Fatal(err) } block, err := aes.NewCipher(key) if err != nil { t.Fatal(err) } ciphertext := make([]byte, len(plaintext)) cfb := cipher.NewCFBEncrypter(block, iv) cfb.XORKeyStream(ciphertext, plaintext) if !bytes.Equal(ciphertext, expected) { t.Errorf("#%d: wrong output: got %x, expected %x", i, ciphertext, expected) } cfbdec := cipher.NewCFBDecrypter(block, iv) plaintextCopy := make([]byte, len(ciphertext)) cfbdec.XORKeyStream(plaintextCopy, ciphertext) if !bytes.Equal(plaintextCopy, plaintext) { t.Errorf("#%d: wrong plaintext: got %x, expected %x", i, plaintextCopy, plaintext) } } } func TestCFBInverse(t *testing.T) { block, err := aes.NewCipher(commonKey128) if err != nil { t.Error(err) return } plaintext := []byte("this is the plaintext. this is the plaintext.") iv := make([]byte, block.BlockSize()) rand.Reader.Read(iv) cfb := cipher.NewCFBEncrypter(block, iv) ciphertext := make([]byte, len(plaintext)) copy(ciphertext, plaintext) cfb.XORKeyStream(ciphertext, ciphertext) cfbdec := cipher.NewCFBDecrypter(block, iv) plaintextCopy := make([]byte, len(plaintext)) copy(plaintextCopy, ciphertext) cfbdec.XORKeyStream(plaintextCopy, plaintextCopy) if !bytes.Equal(plaintextCopy, plaintext) { t.Errorf("got: %x, want: %x", plaintextCopy, plaintext) } } func TestCFBStream(t *testing.T) { for _, keylen := range []int{128, 192, 256} { t.Run(fmt.Sprintf("AES-%d", keylen), func(t *testing.T) { rng := newRandReader(t) key := make([]byte, keylen/8) rng.Read(key) block, err := aes.NewCipher(key) if err != nil { panic(err) } t.Run("Encrypter", func(t *testing.T) { cryptotest.TestStreamFromBlock(t, block, cipher.NewCFBEncrypter) }) t.Run("Decrypter", func(t *testing.T) { cryptotest.TestStreamFromBlock(t, block, cipher.NewCFBDecrypter) }) }) } t.Run("DES", func(t *testing.T) { rng := newRandReader(t) key := make([]byte, 8) rng.Read(key) block, err := des.NewCipher(key) if err != nil { panic(err) } t.Run("Encrypter", func(t *testing.T) { cryptotest.TestStreamFromBlock(t, block, cipher.NewCFBEncrypter) }) t.Run("Decrypter", func(t *testing.T) { cryptotest.TestStreamFromBlock(t, block, cipher.NewCFBDecrypter) }) }) }