Code archives/Algorithms/Salsa20

This code has been declared by its author to be Public Domain code.

Download source code

Salsa20 by Otus2008
Wikipedia:
Salsa20 is a stream cipher submitted to eSTREAM by Daniel Bernstein. It is built on a pseudorandom function based on 32-bit addition, bitwise addition (XOR) and rotation operations, which maps a 256-bit key, a 64-bit nonce, and a 64-bit stream position to a 512-bit output (a version with a 128-bit key also exists).

This BlitzMax implementation includes functions for both 256-bit and 128-bit keys. The default number of rounds is 20 (ROUNDS=10 for 10 DoubleRounds), which can be modified to the 12 and 8 round faster variants (ROUNDS = 6, 4 respectively). Everything below the Type is test code, with test vectors taken from the Salsa20 specification (exception: encrypt functions compare original to decrypted).

Salsa20 is free of any patents.
SuperStrict

Framework BRL.StandardIO

Import BRL.Retro

Extern "C"
	Function ROL:Int(i:Int, n:Int)="_rotl"
End Extern

Type TSalsa
	
	Const ROUNDS:Int = 10
	
	Function QuarterRound( y0:Int Var, y1:Int Var, y2:Int Var, y3:Int Var )
		y1 :~ ROL( y0 + y3, 7 )
		y2 :~ ROL( y1 + y0, 9 )
		y3 :~ ROL( y2 + y1, 13 )
		y0 :~ ROL( y3 + y2, 18 )
	End Function
	
	Function RowRound( y:Int[] )
		QuarterRound y[0] , y[1] , y[2] , y[3]
		QuarterRound y[5] , y[6] , y[7] , y[4]
		QuarterRound y[10], y[11], y[8] , y[9]
		QuarterRound y[15], y[12], y[13], y[14]
	End Function
	
	Function ColumnRound( y:Int[] )
		QuarterRound y[0] , y[4] , y[8] , y[12]
		QuarterRound y[5] , y[9] , y[13], y[1]
		QuarterRound y[10], y[14], y[2] , y[6]
		QuarterRound y[15], y[3] , y[7] , y[11]
	End Function
	
	Function DoubleRound( y:Int[] )
		ColumnRound y
		RowRound y
	End Function
	
	Function Salsa20( x:Byte[] )
		GCSuspend
		Local y:Int[16]
		MemCopy Varptr y[0], Varptr x[0], 64
		For Local i:Int = 0 Until ROUNDS
			DoubleRound y
		Next
		Local xp:Int Ptr = Int Ptr Varptr x[0]
		Local yp:Int Ptr = Varptr y[0]
		For Local i:Int = 0 Until 16
			xp[i] :+ yp[i]
		Next
		GCResume
	End Function
	
	Function Salsa20K32:Byte[]( k:Byte[], n:Byte[] )
		Assert k.length = 32, "Key must be 32 bytes!"
		Assert n.length = 16, "Nonce must be 16 bytes!"
		Local x:Byte[] = ..
			[101:Byte, 120:Byte, 112:Byte, 97:Byte] +..
			k[..16]+..
			[110:Byte, 100:Byte, 32:Byte, 51:Byte]+..
			n+..
			[50:Byte, 45:Byte, 98:Byte, 121:Byte]+..
			k[16..]+..
			[116:Byte, 101:Byte, 32:Byte, 107:Byte]
		Salsa20 x
		Return x
	End Function
	
	Function Salsa20K16:Byte[]( k:Byte[], n:Byte[] )
		Assert k.length = 16, "Key must be 16 bytes!"
		Assert n.length = 16, "Nonce must be 16 bytes!"
		Local x:Byte[] = ..
			[101:Byte, 120:Byte, 112:Byte, 97:Byte] +..
			k+..
			[110:Byte, 100:Byte, 32:Byte, 49:Byte]+..
			n+..
			[54:Byte, 45:Byte, 98:Byte, 121:Byte]+..
			k+..
			[116:Byte, 101:Byte, 32:Byte, 107:Byte]
		Salsa20 x
		Return x
	End Function
	
	Function Encrypt256( k:Byte[], v:Byte[], m:Byte[] )
		Assert k.length = 32, "Key must be 32 bytes!"
		Assert v.length = 8, "Nonce must be 8 bytes!"
		v = v[..16]
		Local i:Int, j:Long
		While j*64 < m.length
			MemCopy Varptr v[8], Varptr j, 8
			Local c:Byte[] = Salsa20K32(k,v)
			i = 0
			While i<64 And j*64+i < m.length
				m[j*64+i] :~ c[i]
				i :+ 1
			Wend
			j :+ 1
		Wend
	End Function
	
	Function Encrypt128( k:Byte[], v:Byte[], m:Byte[] )
		Assert k.length = 16, "Key must be 16 bytes!"
		Assert v.length = 8, "Nonce must be 8 bytes!"
		v = v[..16]
		Local i:Int, j:Long
		While j*64 < m.length
			MemCopy Varptr v[8], Varptr j, 8
			Local c:Byte[] = Salsa20K16(k,v)
			i = 0
			While i<64 And j*64+i < m.length
				m[j*64+i] :~ c[i]
				i :+ 1
			Wend
			j :+ 1
		Wend
	End Function
	
End Type

Print "QuarterRound..."

Local a:Int[] = [$e7e8c006, $c4f9417d, $6479b4b2, $68c67137]
Local at:Int[] = [$e876d72b, $9361dfd5, $f1460244, $948541a3]
TSalsa.QuarterRound a[0], a[1], a[2], a[3]
For Local i:Int = 0 Until a.length
	If a[i]<>at[i]
		Print Hex( a[i] ) + "!"
	Else
		Print Hex( a[i] )
	End If
Next

Print "RowRound..."

a = [..
	$08521bd6, $1fe88837, $bb2aa576, $3aa26365,..
	$c54c6a5b, $2fc74c2f, $6dd39cc3, $da0a64f6,..
	$90a2f23d, $067f95a6, $06b35f61, $41e4732e,..
	$e859c100, $ea4d84b7, $0f619bff, $bc6e965a ]
at = [..
	$a890d39d, $65d71596, $e9487daa, $c8ca6a86,..
	$949d2192, $764b7754, $e408d9b9, $7a41b4d1,..
	$3402e183, $3c3af432, $50669f96, $d89ef0a8,..
	$0040ede5, $b545fbce, $d257ed4f, $1818882d]
TSalsa.RowRound a
For Local i:Int = 0 Until a.length
	If a[i]<>at[i]
		Print Hex( a[i] ) + "!"
	Else
		Print Hex( a[i] )
	End If
Next

Print "ColumnRound..."

a = [..
	$08521bd6, $1fe88837, $bb2aa576, $3aa26365,..
	$c54c6a5b, $2fc74c2f, $6dd39cc3, $da0a64f6,..
	$90a2f23d, $067f95a6, $06b35f61, $41e4732e,..
	$e859c100, $ea4d84b7, $0f619bff, $bc6e965a ]
at = [..
	$8c9d190a, $ce8e4c90, $1ef8e9d3, $1326a71a,..
	$90a20123, $ead3c4f3, $63a091a0, $f0708d69,..
	$789b010c, $d195a681, $eb7d5504, $a774135c,..
	$481c2027, $53a8e4b5, $4c1f89c5, $3f78c9c8 ]
TSalsa.ColumnRound a
For Local i:Int = 0 Until a.length
	If a[i]<>at[i]
		Print Hex( a[i] ) + "!"
	Else
		Print Hex( a[i] )
	End If
Next

Print "DoubleRound..."

a = [..
	$de501066, $6f9eb8f7, $e4fbbd9b, $454e3f57,..
	$b75540d3, $43e93a4c, $3a6f2aa0, $726d6b36,..
	$9243f484, $9145d1e8, $4fa9d247, $dc8dee11,..
	$054bf545, $254dd653, $d9421b6d, $67b276c1 ]
at = [..
	$ccaaf672, $23d960f7, $9153e63a, $cd9a60d0,..
	$50440492, $f07cad19, $ae344aa0, $df4cfdfc,..
	$ca531c29, $8e7943db, $ac1680cd, $d503ca00,..
	$a74b2ad6, $bc331c5c, $1dda24c7, $ee928277 ]
TSalsa.DoubleRound a
For Local i:Int = 0 Until a.length
	If a[i]<>at[i]
		Print Hex( a[i] ) + "!"
	Else
		Print Hex( a[i] )
	End If
Next

Print "Salsa20..."

Local b:Byte[] = [88:Byte, 118:Byte, 104:Byte, 54:Byte, 79:Byte, 201:Byte, 235:Byte, 79:Byte, 3:Byte, 81:Byte, 156:Byte, 47:Byte, 203:Byte, 26:Byte, 244:Byte, 243:Byte, ..
			191:Byte, 187:Byte, 234:Byte, 136:Byte, 211:Byte, 159:Byte, 13:Byte, 115:Byte, 76:Byte, 55:Byte, 82:Byte, 183:Byte, 3:Byte, 117:Byte, 222:Byte, 37:Byte, ..
			86:Byte, 16:Byte, 179:Byte, 207:Byte, 49:Byte, 237:Byte, 179:Byte, 48:Byte, 1:Byte, 106:Byte, 178:Byte, 219:Byte, 175:Byte, 199:Byte, 166:Byte, 48:Byte, ..
			238:Byte, 55:Byte, 204:Byte, 36:Byte, 31:Byte, 240:Byte, 32:Byte, 63:Byte, 15:Byte, 83:Byte, 93:Byte, 161:Byte, 116:Byte, 147:Byte, 48:Byte, 113:Byte]
Local t:Byte[] = [179:Byte, 19:Byte, 48:Byte, 202:Byte, 219:Byte, 236:Byte, 232:Byte, 135:Byte, 111:Byte, 155:Byte, 110:Byte, 18:Byte, 24:Byte, 232:Byte, 95:Byte, 158:Byte,.. 
			26:Byte, 110:Byte, 170:Byte, 154:Byte, 109:Byte, 42:Byte, 178:Byte, 168:Byte, 156:Byte, 240:Byte, 248:Byte, 238:Byte, 168:Byte, 196:Byte, 190:Byte, 203:Byte, ..
			69:Byte, 144:Byte, 51:Byte, 57:Byte, 29:Byte, 29:Byte, 150:Byte, 26:Byte, 150:Byte, 30:Byte, 235:Byte, 249:Byte, 190:Byte, 163:Byte, 251:Byte, 48:Byte, ..
			27:Byte, 111:Byte, 114:Byte, 114:Byte, 118:Byte, 40:Byte, 152:Byte, 157:Byte, 180:Byte, 57:Byte, 27:Byte, 94:Byte, 107:Byte, 42:Byte, 236:Byte, 35:Byte]
TSalsa.Salsa20 b
For Local i:Int = 0 Until 64
	If b[i] <> t[i]
		Print b[i]+"!"
	Else
		Print b[i]
	End If
Next

Print "Salsa20K32..."

Local k:Byte[] = [1:Byte, 2:Byte, 3:Byte, 4:Byte, 5:Byte, 6:Byte, 7:Byte, 8:Byte, 9:Byte, 10:Byte, 11:Byte, 12:Byte, 13:Byte, 14:Byte, 15:Byte, 16:Byte, ..
	201:Byte, 202:Byte, 203:Byte, 204:Byte, 205:Byte, 206:Byte, 207:Byte, 208:Byte, 209:Byte, 210:Byte, 211:Byte, 212:Byte, 213:Byte, 214:Byte, 215:Byte,216:Byte]
Local n:Byte[] = [101:Byte, 102:Byte, 103:Byte, 104:Byte, 105:Byte, 106:Byte, 107:Byte, 108:Byte, 109:Byte, 110:Byte, 111:Byte, 112:Byte, 113:Byte, 114:Byte, 115:Byte, 116:Byte]
t = [69:Byte, 37:Byte, 68:Byte, 39:Byte, 41:Byte, 15:Byte, 107:Byte, 193:Byte, 255:Byte, 139:Byte, 122:Byte, 6:Byte, 170:Byte, 233:Byte, 217:Byte, 98:Byte, ..
	89:Byte, 144:Byte, 182:Byte, 106:Byte, 21:Byte, 51:Byte, 200:Byte, 65:Byte, 239:Byte, 49:Byte, 222:Byte, 34:Byte, 215:Byte, 114:Byte, 40:Byte, 126:Byte, ..
	104:Byte, 197:Byte, 7:Byte, 225:Byte, 197:Byte, 153:Byte, 31:Byte, 2:Byte, 102:Byte, 78:Byte, 76:Byte, 176:Byte, 84:Byte, 245:Byte, 246:Byte, 184:Byte, ..
	177:Byte, 160:Byte, 133:Byte, 130:Byte, 6:Byte, 72:Byte, 149:Byte, 119:Byte, 192:Byte, 195:Byte, 132:Byte, 236:Byte, 234:Byte, 103:Byte, 246:Byte, 74:Byte]
b = TSalsa.Salsa20K32( k,n )
For Local i:Int = 0 Until 64
	If b[i] <> t[i]
		Print b[i]+"!"
	Else
		Print b[i]
	End If
Next

Print "Encrypt256..."

Local m:Byte[] = t[..]
t = m[..]
TSalsa.Encrypt256 k, n[..8], m
TSalsa.Encrypt256 k, n[..8], m
For Local i:Int = 0 Until m.length
	If m[i] <> t[i]
		Print m[i]+"!"
	Else
		Print m[i]
	End If
Next

Print "Salsa20K16..."
k = k[..16]
t = [39:Byte, 173:Byte, 46:Byte, 248:Byte, 30:Byte, 200:Byte, 82:Byte, 17:Byte, 48:Byte, 67:Byte, 254:Byte, 239:Byte, 37:Byte, 18:Byte, 13:Byte, 247:Byte, ..
	241:Byte, 200:Byte, 61:Byte, 144:Byte, 10:Byte, 55:Byte, 50:Byte, 185:Byte, 6:Byte, 47:Byte, 246:Byte, 253:Byte, 143:Byte, 86:Byte, 187:Byte, 225:Byte, ..
	134:Byte, 85:Byte, 110:Byte, 246:Byte, 161:Byte, 163:Byte, 43:Byte, 235:Byte, 231:Byte, 94:Byte, 171:Byte, 51:Byte, 145:Byte, 214:Byte, 112:Byte, 29:Byte, ..
	14:Byte, 232:Byte, 5:Byte, 16:Byte, 151:Byte, 140:Byte, 183:Byte, 141:Byte, 171:Byte, 9:Byte, 122:Byte, 181:Byte, 104:Byte, 182:Byte, 177:Byte, 193:Byte]
b = TSalsa.Salsa20K16( k,n )
For Local i:Int = 0 Until 64
	If b[i] <> t[i]
		Print b[i]+"!"
	Else
		Print b[i]
	End If
Next

Print "Encrypt128..."

m = t[..]
t = m[..]
TSalsa.Encrypt128 k, n[..8], m
TSalsa.Encrypt128 k, n[..8], m
For Local i:Int = 0 Until m.length
	If m[i] <> t[i]
		Print m[i]+"!"
	Else
		Print m[i]
	End If
Next

Comments

None.

Code Archives Forum