gitlab.com/yawning/chacha20.git@v0.0.0-20230427033715-7877545b1b37/chacha20_test.go (about)

     1  // Copryright (C) 2019 Yawning Angel
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package chacha20
    17  
    18  import (
    19  	"crypto/rand"
    20  	"crypto/sha512"
    21  	"math"
    22  	"strconv"
    23  	"testing"
    24  
    25  	"github.com/stretchr/testify/require"
    26  
    27  	"gitlab.com/yawning/chacha20.git/internal/api"
    28  )
    29  
    30  // Test vectors taken from:
    31  // https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01
    32  var draftTestVectors = []struct {
    33  	name       string
    34  	key        []byte
    35  	iv         []byte
    36  	stream     []byte
    37  	seekOffset uint64
    38  }{
    39  	{
    40  		name: "IETF Draft: TC1: All zero key and IV.",
    41  		key: []byte{
    42  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    43  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    44  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    45  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    46  		},
    47  		iv: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    48  		stream: []byte{
    49  			0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
    50  			0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
    51  			0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
    52  			0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
    53  			0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
    54  			0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
    55  			0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
    56  			0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
    57  			0x9f, 0x07, 0xe7, 0xbe, 0x55, 0x51, 0x38, 0x7a,
    58  			0x98, 0xba, 0x97, 0x7c, 0x73, 0x2d, 0x08, 0x0d,
    59  			0xcb, 0x0f, 0x29, 0xa0, 0x48, 0xe3, 0x65, 0x69,
    60  			0x12, 0xc6, 0x53, 0x3e, 0x32, 0xee, 0x7a, 0xed,
    61  			0x29, 0xb7, 0x21, 0x76, 0x9c, 0xe6, 0x4e, 0x43,
    62  			0xd5, 0x71, 0x33, 0xb0, 0x74, 0xd8, 0x39, 0xd5,
    63  			0x31, 0xed, 0x1f, 0x28, 0x51, 0x0a, 0xfb, 0x45,
    64  			0xac, 0xe1, 0x0a, 0x1f, 0x4b, 0x79, 0x4d, 0x6f,
    65  		},
    66  	},
    67  	{
    68  		name: "IETF Draft: TC2: Single bit in key set. All zero IV.",
    69  		key: []byte{
    70  			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    71  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    72  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    73  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    74  		},
    75  		iv: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    76  		stream: []byte{
    77  			0xc5, 0xd3, 0x0a, 0x7c, 0xe1, 0xec, 0x11, 0x93,
    78  			0x78, 0xc8, 0x4f, 0x48, 0x7d, 0x77, 0x5a, 0x85,
    79  			0x42, 0xf1, 0x3e, 0xce, 0x23, 0x8a, 0x94, 0x55,
    80  			0xe8, 0x22, 0x9e, 0x88, 0x8d, 0xe8, 0x5b, 0xbd,
    81  			0x29, 0xeb, 0x63, 0xd0, 0xa1, 0x7a, 0x5b, 0x99,
    82  			0x9b, 0x52, 0xda, 0x22, 0xbe, 0x40, 0x23, 0xeb,
    83  			0x07, 0x62, 0x0a, 0x54, 0xf6, 0xfa, 0x6a, 0xd8,
    84  			0x73, 0x7b, 0x71, 0xeb, 0x04, 0x64, 0xda, 0xc0,
    85  			0x10, 0xf6, 0x56, 0xe6, 0xd1, 0xfd, 0x55, 0x05,
    86  			0x3e, 0x50, 0xc4, 0x87, 0x5c, 0x99, 0x30, 0xa3,
    87  			0x3f, 0x6d, 0x02, 0x63, 0xbd, 0x14, 0xdf, 0xd6,
    88  			0xab, 0x8c, 0x70, 0x52, 0x1c, 0x19, 0x33, 0x8b,
    89  			0x23, 0x08, 0xb9, 0x5c, 0xf8, 0xd0, 0xbb, 0x7d,
    90  			0x20, 0x2d, 0x21, 0x02, 0x78, 0x0e, 0xa3, 0x52,
    91  			0x8f, 0x1c, 0xb4, 0x85, 0x60, 0xf7, 0x6b, 0x20,
    92  			0xf3, 0x82, 0xb9, 0x42, 0x50, 0x0f, 0xce, 0xac,
    93  		},
    94  	},
    95  	{
    96  		name: "IETF Draft: TC3: Single bit in IV set. All zero key.",
    97  		key: []byte{
    98  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    99  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   100  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   101  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   102  		},
   103  		iv: []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
   104  		stream: []byte{
   105  			0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
   106  			0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
   107  			0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
   108  			0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
   109  			0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
   110  			0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
   111  			0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
   112  			0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
   113  			0x53, 0x05, 0xe5, 0xe4, 0x4a, 0xff, 0x19, 0xb2,
   114  			0x35, 0x93, 0x61, 0x44, 0x67, 0x5e, 0xfb, 0xe4,
   115  			0x40, 0x9e, 0xb7, 0xe8, 0xe5, 0xf1, 0x43, 0x0f,
   116  			0x5f, 0x58, 0x36, 0xae, 0xb4, 0x9b, 0xb5, 0x32,
   117  			0x8b, 0x01, 0x7c, 0x4b, 0x9d, 0xc1, 0x1f, 0x8a,
   118  			0x03, 0x86, 0x3f, 0xa8, 0x03, 0xdc, 0x71, 0xd5,
   119  			0x72, 0x6b, 0x2b, 0x6b, 0x31, 0xaa, 0x32, 0x70,
   120  			0x8a, 0xfe, 0x5a, 0xf1, 0xd6, 0xb6, 0x90, 0x58,
   121  		},
   122  	},
   123  	{
   124  		name: "IETF Draft: TC4: All bits in key and IV are set.",
   125  		key: []byte{
   126  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   127  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   128  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   129  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   130  		},
   131  		iv: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
   132  		stream: []byte{
   133  			0xd9, 0xbf, 0x3f, 0x6b, 0xce, 0x6e, 0xd0, 0xb5,
   134  			0x42, 0x54, 0x55, 0x77, 0x67, 0xfb, 0x57, 0x44,
   135  			0x3d, 0xd4, 0x77, 0x89, 0x11, 0xb6, 0x06, 0x05,
   136  			0x5c, 0x39, 0xcc, 0x25, 0xe6, 0x74, 0xb8, 0x36,
   137  			0x3f, 0xea, 0xbc, 0x57, 0xfd, 0xe5, 0x4f, 0x79,
   138  			0x0c, 0x52, 0xc8, 0xae, 0x43, 0x24, 0x0b, 0x79,
   139  			0xd4, 0x90, 0x42, 0xb7, 0x77, 0xbf, 0xd6, 0xcb,
   140  			0x80, 0xe9, 0x31, 0x27, 0x0b, 0x7f, 0x50, 0xeb,
   141  			0x5b, 0xac, 0x2a, 0xcd, 0x86, 0xa8, 0x36, 0xc5,
   142  			0xdc, 0x98, 0xc1, 0x16, 0xc1, 0x21, 0x7e, 0xc3,
   143  			0x1d, 0x3a, 0x63, 0xa9, 0x45, 0x13, 0x19, 0xf0,
   144  			0x97, 0xf3, 0xb4, 0xd6, 0xda, 0xb0, 0x77, 0x87,
   145  			0x19, 0x47, 0x7d, 0x24, 0xd2, 0x4b, 0x40, 0x3a,
   146  			0x12, 0x24, 0x1d, 0x7c, 0xca, 0x06, 0x4f, 0x79,
   147  			0x0f, 0x1d, 0x51, 0xcc, 0xaf, 0xf6, 0xb1, 0x66,
   148  			0x7d, 0x4b, 0xbc, 0xa1, 0x95, 0x8c, 0x43, 0x06,
   149  		},
   150  	},
   151  	{
   152  		name: "IETF Draft: TC5: Every even bit set in key and IV.",
   153  		key: []byte{
   154  			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
   155  			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
   156  			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
   157  			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
   158  		},
   159  		iv: []byte{0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55},
   160  		stream: []byte{
   161  			0xbe, 0xa9, 0x41, 0x1a, 0xa4, 0x53, 0xc5, 0x43,
   162  			0x4a, 0x5a, 0xe8, 0xc9, 0x28, 0x62, 0xf5, 0x64,
   163  			0x39, 0x68, 0x55, 0xa9, 0xea, 0x6e, 0x22, 0xd6,
   164  			0xd3, 0xb5, 0x0a, 0xe1, 0xb3, 0x66, 0x33, 0x11,
   165  			0xa4, 0xa3, 0x60, 0x6c, 0x67, 0x1d, 0x60, 0x5c,
   166  			0xe1, 0x6c, 0x3a, 0xec, 0xe8, 0xe6, 0x1e, 0xa1,
   167  			0x45, 0xc5, 0x97, 0x75, 0x01, 0x7b, 0xee, 0x2f,
   168  			0xa6, 0xf8, 0x8a, 0xfc, 0x75, 0x80, 0x69, 0xf7,
   169  			0xe0, 0xb8, 0xf6, 0x76, 0xe6, 0x44, 0x21, 0x6f,
   170  			0x4d, 0x2a, 0x34, 0x22, 0xd7, 0xfa, 0x36, 0xc6,
   171  			0xc4, 0x93, 0x1a, 0xca, 0x95, 0x0e, 0x9d, 0xa4,
   172  			0x27, 0x88, 0xe6, 0xd0, 0xb6, 0xd1, 0xcd, 0x83,
   173  			0x8e, 0xf6, 0x52, 0xe9, 0x7b, 0x14, 0x5b, 0x14,
   174  			0x87, 0x1e, 0xae, 0x6c, 0x68, 0x04, 0xc7, 0x00,
   175  			0x4d, 0xb5, 0xac, 0x2f, 0xce, 0x4c, 0x68, 0xc7,
   176  			0x26, 0xd0, 0x04, 0xb1, 0x0f, 0xca, 0xba, 0x86,
   177  		},
   178  	},
   179  	{
   180  		name: "IETF Draft: TC6: Every odd bit set in key and IV.",
   181  		key: []byte{
   182  			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
   183  			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
   184  			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
   185  			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
   186  		},
   187  		iv: []byte{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa},
   188  		stream: []byte{
   189  			0x9a, 0xa2, 0xa9, 0xf6, 0x56, 0xef, 0xde, 0x5a,
   190  			0xa7, 0x59, 0x1c, 0x5f, 0xed, 0x4b, 0x35, 0xae,
   191  			0xa2, 0x89, 0x5d, 0xec, 0x7c, 0xb4, 0x54, 0x3b,
   192  			0x9e, 0x9f, 0x21, 0xf5, 0xe7, 0xbc, 0xbc, 0xf3,
   193  			0xc4, 0x3c, 0x74, 0x8a, 0x97, 0x08, 0x88, 0xf8,
   194  			0x24, 0x83, 0x93, 0xa0, 0x9d, 0x43, 0xe0, 0xb7,
   195  			0xe1, 0x64, 0xbc, 0x4d, 0x0b, 0x0f, 0xb2, 0x40,
   196  			0xa2, 0xd7, 0x21, 0x15, 0xc4, 0x80, 0x89, 0x06,
   197  			0x72, 0x18, 0x44, 0x89, 0x44, 0x05, 0x45, 0xd0,
   198  			0x21, 0xd9, 0x7e, 0xf6, 0xb6, 0x93, 0xdf, 0xe5,
   199  			0xb2, 0xc1, 0x32, 0xd4, 0x7e, 0x6f, 0x04, 0x1c,
   200  			0x90, 0x63, 0x65, 0x1f, 0x96, 0xb6, 0x23, 0xe6,
   201  			0x2a, 0x11, 0x99, 0x9a, 0x23, 0xb6, 0xf7, 0xc4,
   202  			0x61, 0xb2, 0x15, 0x30, 0x26, 0xad, 0x5e, 0x86,
   203  			0x6a, 0x2e, 0x59, 0x7e, 0xd0, 0x7b, 0x84, 0x01,
   204  			0xde, 0xc6, 0x3a, 0x09, 0x34, 0xc6, 0xb2, 0xa9,
   205  		},
   206  	},
   207  	{
   208  		name: "IETF Draft: TC7: Sequence patterns in key and IV.",
   209  		key: []byte{
   210  			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
   211  			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
   212  			0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
   213  			0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
   214  		},
   215  		iv: []byte{0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78},
   216  		stream: []byte{
   217  			0x9f, 0xad, 0xf4, 0x09, 0xc0, 0x08, 0x11, 0xd0,
   218  			0x04, 0x31, 0xd6, 0x7e, 0xfb, 0xd8, 0x8f, 0xba,
   219  			0x59, 0x21, 0x8d, 0x5d, 0x67, 0x08, 0xb1, 0xd6,
   220  			0x85, 0x86, 0x3f, 0xab, 0xbb, 0x0e, 0x96, 0x1e,
   221  			0xea, 0x48, 0x0f, 0xd6, 0xfb, 0x53, 0x2b, 0xfd,
   222  			0x49, 0x4b, 0x21, 0x51, 0x01, 0x50, 0x57, 0x42,
   223  			0x3a, 0xb6, 0x0a, 0x63, 0xfe, 0x4f, 0x55, 0xf7,
   224  			0xa2, 0x12, 0xe2, 0x16, 0x7c, 0xca, 0xb9, 0x31,
   225  			0xfb, 0xfd, 0x29, 0xcf, 0x7b, 0xc1, 0xd2, 0x79,
   226  			0xed, 0xdf, 0x25, 0xdd, 0x31, 0x6b, 0xb8, 0x84,
   227  			0x3d, 0x6e, 0xde, 0xe0, 0xbd, 0x1e, 0xf1, 0x21,
   228  			0xd1, 0x2f, 0xa1, 0x7c, 0xbc, 0x2c, 0x57, 0x4c,
   229  			0xcc, 0xab, 0x5e, 0x27, 0x51, 0x67, 0xb0, 0x8b,
   230  			0xd6, 0x86, 0xf8, 0xa0, 0x9d, 0xf8, 0x7e, 0xc3,
   231  			0xff, 0xb3, 0x53, 0x61, 0xb9, 0x4e, 0xbf, 0xa1,
   232  			0x3f, 0xec, 0x0e, 0x48, 0x89, 0xd1, 0x8d, 0xa5,
   233  		},
   234  	},
   235  	{
   236  		name: "IETF Draft: TC8: key: 'All your base are belong to us!, IV: 'IETF2013'",
   237  		key: []byte{
   238  			0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78,
   239  			0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35,
   240  			0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb,
   241  			0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d,
   242  		},
   243  		iv: []byte{0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21},
   244  		stream: []byte{
   245  			0xf6, 0x3a, 0x89, 0xb7, 0x5c, 0x22, 0x71, 0xf9,
   246  			0x36, 0x88, 0x16, 0x54, 0x2b, 0xa5, 0x2f, 0x06,
   247  			0xed, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2b, 0x00,
   248  			0xb5, 0xe8, 0xf8, 0x0a, 0xe9, 0xa4, 0x73, 0xaf,
   249  			0xc2, 0x5b, 0x21, 0x8f, 0x51, 0x9a, 0xf0, 0xfd,
   250  			0xd4, 0x06, 0x36, 0x2e, 0x8d, 0x69, 0xde, 0x7f,
   251  			0x54, 0xc6, 0x04, 0xa6, 0xe0, 0x0f, 0x35, 0x3f,
   252  			0x11, 0x0f, 0x77, 0x1b, 0xdc, 0xa8, 0xab, 0x92,
   253  			0xe5, 0xfb, 0xc3, 0x4e, 0x60, 0xa1, 0xd9, 0xa9,
   254  			0xdb, 0x17, 0x34, 0x5b, 0x0a, 0x40, 0x27, 0x36,
   255  			0x85, 0x3b, 0xf9, 0x10, 0xb0, 0x60, 0xbd, 0xf1,
   256  			0xf8, 0x97, 0xb6, 0x29, 0x0f, 0x01, 0xd1, 0x38,
   257  			0xae, 0x2c, 0x4c, 0x90, 0x22, 0x5b, 0xa9, 0xea,
   258  			0x14, 0xd5, 0x18, 0xf5, 0x59, 0x29, 0xde, 0xa0,
   259  			0x98, 0xca, 0x7a, 0x6c, 0xcf, 0xe6, 0x12, 0x27,
   260  			0x05, 0x3c, 0x84, 0xe4, 0x9a, 0x4a, 0x33, 0x32,
   261  		},
   262  	},
   263  	{
   264  		name: "XChaCha20 Test",
   265  		key: []byte{
   266  			0x54, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70,
   267  			0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
   268  			0x68, 0x65, 0x20, 0x70, 0x69, 0x73, 0x74, 0x6f,
   269  			0x6c, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20,
   270  		},
   271  		iv: []byte{
   272  			0x73, 0x74, 0x6f, 0x70, 0x20, 0x61, 0x20, 0x66,
   273  			0x69, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x61,
   274  			0x74, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x62, 0x6f,
   275  		},
   276  		stream: []byte{
   277  			0xfa, 0x27, 0xe8, 0x54, 0xba, 0x9f, 0x74, 0xf0,
   278  			0x7f, 0xa3, 0x85, 0x03, 0x65, 0x1b, 0xc9, 0xbf,
   279  			0xe8, 0x80, 0xed, 0x2b, 0xf7, 0x20, 0xed, 0xc5,
   280  			0xb4, 0x82, 0xc9, 0xea, 0x95, 0x32, 0x59, 0x20,
   281  			0xb9, 0xf5, 0x86, 0x93, 0xf1, 0xf7, 0xa6, 0x67,
   282  			0x4e, 0xc4, 0xf3, 0xfa, 0x93, 0x14, 0x4d, 0xe2,
   283  			0xe9, 0x6d, 0x0d, 0x4a, 0xe7, 0x70, 0x32, 0xae,
   284  			0x88, 0xb7, 0x58, 0x3b, 0xd5, 0x5f, 0x16, 0xa6,
   285  			0xd5, 0x0e, 0x8d, 0x53, 0x0c, 0x60, 0x8e, 0x41,
   286  			0x5c, 0xda, 0x0c, 0xe9, 0xc7, 0xde, 0xc6, 0x71,
   287  			0x9d, 0x8a, 0xe5, 0xcb, 0xde, 0x45, 0x5b, 0x98,
   288  			0xf6, 0x57, 0xca, 0x9d, 0xd1, 0xa1, 0xe3, 0x5c,
   289  			0x01, 0xe6, 0x29, 0x38, 0x9e, 0xf5, 0x97, 0x38,
   290  			0x75, 0x61, 0x0e, 0x71, 0xfc, 0xd1, 0xa1, 0x11,
   291  			0x29, 0x47, 0x37, 0x6b, 0xac, 0x09, 0xd6, 0xee,
   292  			0xf7, 0x61, 0x62, 0x24, 0x00, 0x58, 0xac, 0x1d,
   293  			0xcf, 0x42, 0xef, 0x50, 0xfa, 0x54, 0x14, 0x49,
   294  			0x31, 0xd2, 0x62,
   295  		},
   296  	},
   297  	{
   298  		name: "RFC 7539 Test Vector (96 bit nonce)",
   299  		key: []byte{
   300  			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   301  			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   302  			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
   303  			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   304  		},
   305  		iv: []byte{
   306  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a,
   307  			0x00, 0x00, 0x00, 0x00,
   308  		},
   309  		stream: []byte{
   310  			0x22, 0x4f, 0x51, 0xf3, 0x40, 0x1b, 0xd9, 0xe1,
   311  			0x2f, 0xde, 0x27, 0x6f, 0xb8, 0x63, 0x1d, 0xed,
   312  			0x8c, 0x13, 0x1f, 0x82, 0x3d, 0x2c, 0x06, 0xe2,
   313  			0x7e, 0x4f, 0xca, 0xec, 0x9e, 0xf3, 0xcf, 0x78,
   314  			0x8a, 0x3b, 0x0a, 0xa3, 0x72, 0x60, 0x0a, 0x92,
   315  			0xb5, 0x79, 0x74, 0xcd, 0xed, 0x2b, 0x93, 0x34,
   316  			0x79, 0x4c, 0xba, 0x40, 0xc6, 0x3e, 0x34, 0xcd,
   317  			0xea, 0x21, 0x2c, 0x4c, 0xf0, 0x7d, 0x41, 0xb7,
   318  			0x69, 0xa6, 0x74, 0x9f, 0x3f, 0x63, 0x0f, 0x41,
   319  			0x22, 0xca, 0xfe, 0x28, 0xec, 0x4d, 0xc4, 0x7e,
   320  			0x26, 0xd4, 0x34, 0x6d, 0x70, 0xb9, 0x8c, 0x73,
   321  			0xf3, 0xe9, 0xc5, 0x3a, 0xc4, 0x0c, 0x59, 0x45,
   322  			0x39, 0x8b, 0x6e, 0xda, 0x1a, 0x83, 0x2c, 0x89,
   323  			0xc1, 0x67, 0xea, 0xcd, 0x90, 0x1d, 0x7e, 0x2b,
   324  			0xf3, 0x63,
   325  		},
   326  		seekOffset: 1,
   327  	},
   328  }
   329  
   330  func TestChaCha20(t *testing.T) {
   331  	for _, v := range supportedImpls {
   332  		testWithImpl := func(t *testing.T, impl api.Implementation) {
   333  			oldImpl := activeImpl
   334  			defer func() {
   335  				activeImpl = oldImpl
   336  			}()
   337  
   338  			activeImpl = impl
   339  
   340  			t.Run("Basic", doTestBasic)
   341  			t.Run("TestVectors", doTestVectors)
   342  		}
   343  
   344  		t.Run(v.Name(), func(t *testing.T) {
   345  			testWithImpl(t, v)
   346  		})
   347  	}
   348  }
   349  
   350  func doTestBasic(t *testing.T) {
   351  	t.Run("RoundTrip", doTestBasicRoundTrip)
   352  	t.Run("Counter", doTestBasicCounter)
   353  	t.Run("IETFCounter", doTestBasicIETFCounter)
   354  	t.Run("Incremental", doTestBasicIncremental)
   355  }
   356  
   357  func doTestBasicRoundTrip(t *testing.T) {
   358  	require := require.New(t)
   359  
   360  	var (
   361  		key   [KeySize]byte
   362  		nonce [NonceSize]byte
   363  	)
   364  
   365  	c, err := New(key[:], nonce[:])
   366  	require.NoError(err, "New")
   367  
   368  	plaintext := []byte("The smallest minority on earth is the individual.  Those who deny individual rights cannot claim to be defenders of minorities.")
   369  	ciphertext := make([]byte, len(plaintext))
   370  	c.XORKeyStream(ciphertext, plaintext)
   371  
   372  	require.NotEqual(plaintext, ciphertext, "XORKeyStream - output")
   373  
   374  	err = c.Seek(0)
   375  	require.NoError(err, "Seek")
   376  	c.XORKeyStream(ciphertext, ciphertext)
   377  
   378  	require.Equal(plaintext, ciphertext, "XORKeyStream - round trip output")
   379  }
   380  
   381  func doTestBasicCounter(t *testing.T) {
   382  	require := require.New(t)
   383  
   384  	var (
   385  		key   [KeySize]byte
   386  		nonce [NonceSize]byte
   387  
   388  		block, block2 [api.BlockSize]byte
   389  	)
   390  
   391  	c, err := New(key[:], nonce[:])
   392  	require.NoError(err, "New")
   393  
   394  	c.KeyStream(block[:]) // Block: 0
   395  
   396  	err = c.Seek(math.MaxUint32 + 1)
   397  	require.NoError(err, "Seek")
   398  	c.KeyStream(block2[:]) // Block: 0x100000000
   399  
   400  	require.NotEqual(block, block2, "KeyStream - 32 bit counter would wrap")
   401  }
   402  
   403  func doTestBasicIETFCounter(t *testing.T) {
   404  	require := require.New(t)
   405  
   406  	var (
   407  		key   [KeySize]byte
   408  		nonce [INonceSize]byte
   409  
   410  		block [api.BlockSize]byte
   411  	)
   412  
   413  	c, err := New(key[:], nonce[:])
   414  	require.NoError(err, "New")
   415  
   416  	err = c.Seek(math.MaxUint32 - 1)
   417  	require.NoError(err, "Seek")
   418  	c.KeyStream(block[:])
   419  
   420  	require.Panics(func() {
   421  		c.KeyStream(block[:])
   422  	}, "KeyStream - counter would wrap")
   423  }
   424  
   425  func doTestBasicIncremental(t *testing.T) {
   426  	require := require.New(t)
   427  
   428  	var (
   429  		key   [KeySize]byte
   430  		nonce [NonceSize]byte
   431  
   432  		buf [2048]byte
   433  
   434  		expectedDigest = []byte{
   435  			0xcf, 0xd6, 0xe9, 0x49, 0x22, 0x5b, 0x85, 0x4f,
   436  			0xe0, 0x49, 0x46, 0x49, 0x1e, 0x69, 0x35, 0xff,
   437  			0x05, 0xff, 0x98, 0x3d, 0x15, 0x54, 0xbc, 0x88,
   438  			0x5b, 0xca, 0x0e, 0xc8, 0x08, 0x2d, 0xd5, 0xb8,
   439  		}
   440  	)
   441  
   442  	c, err := New(key[:], nonce[:])
   443  	require.NoError(err, "New")
   444  
   445  	h := sha512.New512_256()
   446  	for i := 1; i <= 2048; i++ {
   447  		c.KeyStream(buf[:i])
   448  		_, _ = h.Write(buf[:i])
   449  	}
   450  
   451  	digest := h.Sum(nil)
   452  
   453  	require.Equal(expectedDigest, digest, "KeyStream digest matches")
   454  }
   455  
   456  func doTestVectors(t *testing.T) {
   457  	for _, v := range draftTestVectors {
   458  		t.Run(v.name, func(t *testing.T) {
   459  			require := require.New(t)
   460  			c, err := New(v.key, v.iv)
   461  			require.NoError(err, "New")
   462  
   463  			if v.seekOffset != 0 {
   464  				err = c.Seek(v.seekOffset)
   465  				require.NoErrorf(err, "Seek(%d)", v.seekOffset)
   466  			}
   467  
   468  			out := make([]byte, len(v.stream))
   469  			c.XORKeyStream(out, out)
   470  			require.EqualValues(v.stream, out, "XORKeyStream")
   471  
   472  			// Ensure that KeyStream tramples over dst.
   473  			_, err = rand.Read(out)
   474  			require.NoError(err, "rand.Read")
   475  
   476  			err = c.Seek(v.seekOffset)
   477  			require.NoErrorf(err, "Seek(%d) - resetting", v.seekOffset)
   478  			c.KeyStream(out)
   479  			require.EqualValues(v.stream, out, "KeyStream")
   480  		})
   481  	}
   482  }
   483  
   484  func BenchmarkChaCha20(b *testing.B) {
   485  	for _, v := range supportedImpls {
   486  		benchWithImpl := func(b *testing.B, impl api.Implementation) {
   487  			oldImpl := activeImpl
   488  			defer func() {
   489  				activeImpl = oldImpl
   490  			}()
   491  
   492  			activeImpl = impl
   493  			for _, vv := range []int{
   494  				1, 8, 32, 64, 576, 1536, 4096, 1024768,
   495  			} {
   496  				b.Run(strconv.Itoa(vv), func(b *testing.B) {
   497  					doBenchN(b, vv)
   498  				})
   499  			}
   500  		}
   501  
   502  		b.Run(v.Name(), func(b *testing.B) {
   503  			benchWithImpl(b, v)
   504  		})
   505  	}
   506  }
   507  
   508  func doBenchN(b *testing.B, n int) {
   509  	var (
   510  		key   [KeySize]byte
   511  		nonce [NonceSize]byte
   512  	)
   513  
   514  	s := make([]byte, n)
   515  	c, err := New(key[:], nonce[:])
   516  	if err != nil {
   517  		b.Fatal(err)
   518  	}
   519  	b.SetBytes(int64(n))
   520  
   521  	b.ResetTimer()
   522  	for i := 0; i < b.N; i++ {
   523  		c.XORKeyStream(s, s)
   524  	}
   525  }