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 5package salsa20 6 7import ( 8 "bytes" 9 "encoding/hex" 10 "testing" 11) 12 13func fromHex(s string) []byte { 14 ret, err := hex.DecodeString(s) 15 if err != nil { 16 panic(err) 17 } 18 return ret 19} 20 21// testVectors was taken from set 6 of the ECRYPT test vectors: 22// http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?logsort=rev&rev=210&view=markup 23var testVectors = []struct { 24 key []byte 25 iv []byte 26 numBytes int 27 xor []byte 28}{ 29 { 30 fromHex("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D"), 31 fromHex("0D74DB42A91077DE"), 32 131072, 33 fromHex("C349B6A51A3EC9B712EAED3F90D8BCEE69B7628645F251A996F55260C62EF31FD6C6B0AEA94E136C9D984AD2DF3578F78E457527B03A0450580DD874F63B1AB9"), 34 }, 35 { 36 fromHex("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12"), 37 fromHex("167DE44BB21980E7"), 38 131072, 39 fromHex("C3EAAF32836BACE32D04E1124231EF47E101367D6305413A0EEB07C60698A2876E4D031870A739D6FFDDD208597AFF0A47AC17EDB0167DD67EBA84F1883D4DFD"), 40 }, 41 { 42 fromHex("0A5DB00356A9FC4FA2F5489BEE4194E73A8DE03386D92C7FD22578CB1E71C417"), 43 fromHex("1F86ED54BB2289F0"), 44 131072, 45 fromHex("3CD23C3DC90201ACC0CF49B440B6C417F0DC8D8410A716D5314C059E14B1A8D9A9FB8EA3D9C8DAE12B21402F674AA95C67B1FC514E994C9D3F3A6E41DFF5BBA6"), 46 }, 47 { 48 fromHex("0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C"), 49 fromHex("288FF65DC42B92F9"), 50 131072, 51 fromHex("E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A"), 52 }, 53} 54 55func TestSalsa20(t *testing.T) { 56 var inBuf, outBuf []byte 57 var key [32]byte 58 59 for i, test := range testVectors { 60 if test.numBytes%64 != 0 { 61 t.Errorf("#%d: numBytes is not a multiple of 64", i) 62 continue 63 } 64 65 if test.numBytes > len(inBuf) { 66 inBuf = make([]byte, test.numBytes) 67 outBuf = make([]byte, test.numBytes) 68 } 69 in := inBuf[:test.numBytes] 70 out := outBuf[:test.numBytes] 71 copy(key[:], test.key) 72 XORKeyStream(out, in, test.iv, &key) 73 74 var xor [64]byte 75 for len(out) > 0 { 76 for i := 0; i < 64; i++ { 77 xor[i] ^= out[i] 78 } 79 out = out[64:] 80 } 81 82 if !bytes.Equal(xor[:], test.xor) { 83 t.Errorf("#%d: bad result", i) 84 } 85 } 86} 87 88var xSalsa20TestData = []struct { 89 in, nonce, key, out []byte 90}{ 91 { 92 []byte("Hello world!"), 93 []byte("24-byte nonce for xsalsa"), 94 []byte("this is 32-byte key for xsalsa20"), 95 []byte{0x00, 0x2d, 0x45, 0x13, 0x84, 0x3f, 0xc2, 0x40, 0xc4, 0x01, 0xe5, 0x41}, 96 }, 97 { 98 make([]byte, 64), 99 []byte("24-byte nonce for xsalsa"), 100 []byte("this is 32-byte key for xsalsa20"), 101 []byte{0x48, 0x48, 0x29, 0x7f, 0xeb, 0x1f, 0xb5, 0x2f, 0xb6, 102 0x6d, 0x81, 0x60, 0x9b, 0xd5, 0x47, 0xfa, 0xbc, 0xbe, 0x70, 103 0x26, 0xed, 0xc8, 0xb5, 0xe5, 0xe4, 0x49, 0xd0, 0x88, 0xbf, 104 0xa6, 0x9c, 0x08, 0x8f, 0x5d, 0x8d, 0xa1, 0xd7, 0x91, 0x26, 105 0x7c, 0x2c, 0x19, 0x5a, 0x7f, 0x8c, 0xae, 0x9c, 0x4b, 0x40, 106 0x50, 0xd0, 0x8c, 0xe6, 0xd3, 0xa1, 0x51, 0xec, 0x26, 0x5f, 107 0x3a, 0x58, 0xe4, 0x76, 0x48}, 108 }, 109} 110 111func TestXSalsa20(t *testing.T) { 112 var key [32]byte 113 114 for i, test := range xSalsa20TestData { 115 out := make([]byte, len(test.in)) 116 copy(key[:], test.key) 117 XORKeyStream(out, test.in, test.nonce, &key) 118 if !bytes.Equal(out, test.out) { 119 t.Errorf("%d: expected %x, got %x", i, test.out, out) 120 } 121 } 122} 123 124var ( 125 keyArray [32]byte 126 key = &keyArray 127 nonce [8]byte 128 msg = make([]byte, 1<<10) 129) 130 131func BenchmarkXOR1K(b *testing.B) { 132 b.StopTimer() 133 out := make([]byte, 1024) 134 b.StartTimer() 135 for i := 0; i < b.N; i++ { 136 XORKeyStream(out, msg[:1024], nonce[:], key) 137 } 138 b.SetBytes(1024) 139} 140