Salsa20
Struktur

Secara internal, penyandian ini menggunakan penjumlahan per bit dengan (⊕ atau XOR), penjumlahan 32 bit dengan mod 232 (⊞), dan operasi geseran melingkar berjarak tetap (<<<). Penggunaan operasi tambah-putar-XOR menghindari peluang serangan pewaktuan dalam penerapan perangkat lunak. Status internalnya terdiri dari 16 kata 32 bit yang disusun dalam matriks 4×4.
| 0 | 1 | 2 | 3 |
| --- | --- | --- | --- |
| 0 | 1 | 2 | 3 |
| 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 |
Status internalnya terdiri dari   delapan kata untuk kunci,   dua kata untuk letak aliran,   dua kata untuk nilai yang dipakai sekali (nonce; intinya bit-bit tambahan untuk letak aliran), dan   empat kata tetapan:
| 0 | 1 | 2 | 3 |
| --- | --- | --- | --- |
"expa": Kunci
| Kunci | "nd 3" | Nonce | Nonce |
| Letak | Letak | "2-by" | Kunci |
| Kunci | Kunci | Kunci | "te k" |
Kata-kata tetapan berbunyi "expand 32-byte k" dalam ASCII (empat kata tersebut adalah "expa", "nd 3", "2-by", dan "te k"). Ini adalah contoh bilangan tanpa tujuan khusus. Inti operasi dalam Salsa20 adalah seperempat ronde QR(a, b, c, d) yang menerima empat kata sebagai masukan dan menghasilkan empat kata:
b ^= (a + d) <<< 7;
c ^= (b + a) <<< 9;
d ^= (c + b) <<< 13;
a ^= (d + c) <<< 18;
Ronde bernomor ganjil menerapkan QR(a, b, c, d) kepada tiap kolom dalam matriks 4×4, sedangkan ronde bernomor genap menerapkannya kepada tiap baris. Dua ronde berturutan (ronde kolom dan ronde baris) disebut sebagai ronde ganda:
// Ronde ganjil
QR( 0,  4,  8, 12)	// kolom 1
QR( 5,  9, 13,  1)	// kolom 2
QR(10, 14,  2,  6)	// kolom 3
QR(15,  3,  7, 11)	// kolom 4
// Ronde genap
QR( 0,  1,  2,  3)	// baris 1
QR( 5,  6,  7,  4)	// baris 2
QR(10, 11,  8,  9)	// baris 3
QR(15, 12, 13, 14)	// baris 4
Berikut penerapan Salsa20 dalam C/C++.
#include <stdint.h>
#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
#define QR(a, b, c, d)(		\
	b ^= ROTL(a + d, 7),	\
	c ^= ROTL(b + a, 9),	\
	d ^= ROTL(c + b,13),	\
	a ^= ROTL(d + c,18))
#define ROUNDS 20
 
void salsa20_block(uint32_t out[16], uint32_t const in[16])
{
	int i;
	uint32_t x[16];

	for (i = 0; i < 16; ++i)
		x[i] = in[i];
	// 10 perulangan × 2 ronde/perulangan = 20 ronde
	for (i = 0; i < ROUNDS; i += 2) {
		// Ronde ganjil
		QR(x[ 0], x[ 4], x[ 8], x[12]);	// kolom 1
		QR(x[ 5], x[ 9], x[13], x[ 1]);	// kolom 2
		QR(x[10], x[14], x[ 2], x[ 6]);	// kolom 3
		QR(x[15], x[ 3], x[ 7], x[11]);	// kolom 4
		// Ronde genap
		QR(x[ 0], x[ 1], x[ 2], x[ 3]);	// baris 1
		QR(x[ 5], x[ 6], x[ 7], x[ 4]);	// baris 2
		QR(x[10], x[11], x[ 8], x[ 9]);	// baris 3
		QR(x[15], x[12], x[13], x[14]);	// baris 4
	}
	for (i = 0; i < 16; ++i)
		out[i] = x[i] + in[i];
}
Pada baris terakhir, larik yang telah tercampur ditambahkan, kata demi kata, ke larik asal untuk mendapatkan blok aliran kunci 64 bita. Hal ini penting karena ronde pencampuran ini dengan sendirinya bisa dibalik (invertible). Dengan kata lain, operasi yang dibalik bisa menghasilkan matriks 4×4 asal, termasuk kuncinya. Penambahan larik yang telah tercampur ke asalnya membuatnya tidak mungkin untuk memulihkan input. (Teknik ini juga dipakai dalam fungsi hash dari MD4 sampai SHA-2.)
Salsa20 melakukan 20 ronde pencampuran dari inputnya. Namun, pengurangan ronde pada varian Salsa20/8 dan Salsa20/12 dengan 8 dan 12 ronde juga dikenalkan.