DES

The Data Encryption Standard (DES) is an symmetric-key algorithm for the encryption of electronic data. DES works by using the same key to encrypt and decrypt a message, so both the sender and the receiver must know and use the same private key.



									Const ENCRYPT As Integer = 1
Const DECRYPT As Integer = 0

Private Shared Function BITNUM(a As Byte(), b As Integer, c As Integer) As UInteger
	Return CLng(((a(b \ 8) >> (7 - (b Mod 8))) And &H1) << (c)) And UInteger.MaxValue
End Function

Private Shared Function BITNUMINTR(a As UInteger, b As Integer, c As Integer) As Byte
	Return CByte((((a) >> (31 - (b))) And &H1) << (c))
End Function

Private Shared Function BITNUMINTL(a As UInteger, b As Integer, c As Integer) As UInteger
	Return ((((a) << (b)) And &H80000000UI) >> (c))
End Function

Private Shared Function SBOXBIT(a As Byte) As UInteger
	Return CUInt(((a) And &H20) Or (((a) And &H1F) >> 1) Or (((a) And &H1) << 4))
End Function

Private Shared sbox1 As Byte() = {14, 4, 13, 1, 2, 15,
	11, 8, 3, 10, 6, 12,
	5, 9, 0, 7, 0, 15,
	7, 4, 14, 2, 13, 1,
	10, 6, 12, 11, 9, 5,
	3, 8, 4, 1, 14, 8,
	13, 6, 2, 11, 15, 12,
	9, 7, 3, 10, 5, 0,
	15, 12, 8, 2, 4, 9,
	1, 7, 5, 11, 3, 14,
	10, 0, 6, 13}

Private Shared sbox2 As Byte() = {15, 1, 8, 14, 6, 11,
	3, 4, 9, 7, 2, 13,
	12, 0, 5, 10, 3, 13,
	4, 7, 15, 2, 8, 14,
	12, 0, 1, 10, 6, 9,
	11, 5, 0, 14, 7, 11,
	10, 4, 13, 1, 5, 8,
	12, 6, 9, 3, 2, 15,
	13, 8, 10, 1, 3, 15,
	4, 2, 11, 6, 7, 12,
	0, 5, 14, 9}

Private Shared sbox3 As Byte() = {10, 0, 9, 14, 6, 3,
	15, 5, 1, 13, 12, 7,
	11, 4, 2, 8, 13, 7,
	0, 9, 3, 4, 6, 10,
	2, 8, 5, 14, 12, 11,
	15, 1, 13, 6, 4, 9,
	8, 15, 3, 0, 11, 1,
	2, 12, 5, 10, 14, 7,
	1, 10, 13, 0, 6, 9,
	8, 7, 4, 15, 14, 3,
	11, 5, 2, 12}

Private Shared sbox4 As Byte() = {7, 13, 14, 3, 0, 6,
	9, 10, 1, 2, 8, 5,
	11, 12, 4, 15, 13, 8,
	11, 5, 6, 15, 0, 3,
	4, 7, 2, 12, 1, 10,
	14, 9, 10, 6, 9, 0,
	12, 11, 7, 13, 15, 1,
	3, 14, 5, 2, 8, 4,
	3, 15, 0, 6, 10, 1,
	13, 8, 9, 4, 5, 11,
	12, 7, 2, 14}

Private Shared sbox5 As Byte() = {2, 12, 4, 1, 7, 10,
	11, 6, 8, 5, 3, 15,
	13, 0, 14, 9, 14, 11,
	2, 12, 4, 7, 13, 1,
	5, 0, 15, 10, 3, 9,
	8, 6, 4, 2, 1, 11,
	10, 13, 7, 8, 15, 9,
	12, 5, 6, 3, 0, 14,
	11, 8, 12, 7, 1, 14,
	2, 13, 6, 15, 0, 9,
	10, 4, 5, 3}

Private Shared sbox6 As Byte() = {12, 1, 10, 15, 9, 2,
	6, 8, 0, 13, 3, 4,
	14, 7, 5, 11, 10, 15,
	4, 2, 7, 12, 9, 5,
	6, 1, 13, 14, 0, 11,
	3, 8, 9, 14, 15, 5,
	2, 8, 12, 3, 7, 0,
	4, 10, 1, 13, 11, 6,
	4, 3, 2, 12, 9, 5,
	15, 10, 11, 14, 1, 7,
	6, 0, 8, 13}

Private Shared sbox7 As Byte() = {4, 11, 2, 14, 15, 0,
	8, 13, 3, 12, 9, 7,
	5, 10, 6, 1, 13, 0,
	11, 7, 4, 9, 1, 10,
	14, 3, 5, 12, 2, 15,
	8, 6, 1, 4, 11, 13,
	12, 3, 7, 14, 10, 15,
	6, 8, 0, 5, 9, 2,
	6, 11, 13, 8, 1, 4,
	10, 7, 9, 5, 0, 15,
	14, 2, 3, 12}

Private Shared sbox8 As Byte() = {13, 2, 8, 4, 6, 15,
	11, 1, 10, 9, 3, 14,
	5, 0, 12, 7, 1, 15,
	13, 8, 10, 3, 7, 4,
	12, 5, 6, 11, 0, 14,
	9, 2, 7, 11, 4, 1,
	9, 12, 14, 2, 0, 6,
	10, 13, 15, 3, 5, 8,
	2, 1, 14, 7, 4, 10,
	8, 13, 15, 12, 9, 0,
	3, 5, 6, 11}

Public Shared Sub KeySchedule(key As Byte(), schedule As Byte(,), mode As UInteger)
	Dim i As UInteger, j As UInteger, toGen As UInteger, C As UInteger, D As UInteger
	Dim key_rnd_shift As UInteger() = {1, 1, 2, 2, 2, 2,
		2, 2, 1, 2, 2, 2,
		2, 2, 2, 1}
	Dim key_perm_c As UInteger() = {56, 48, 40, 32, 24, 16,
		8, 0, 57, 49, 41, 33,
		25, 17, 9, 1, 58, 50,
		42, 34, 26, 18, 10, 2,
		59, 51, 43, 35}
	Dim key_perm_d As UInteger() = {62, 54, 46, 38, 30, 22,
		14, 6, 61, 53, 45, 37,
		29, 21, 13, 5, 60, 52,
		44, 36, 28, 20, 12, 4,
		27, 19, 11, 3}
	Dim key_compression As UInteger() = {13, 16, 10, 23, 0, 4,
		2, 27, 14, 5, 20, 9,
		22, 18, 11, 3, 25, 7,
		15, 6, 26, 19, 12, 1,
		40, 51, 30, 36, 46, 54,
		29, 39, 50, 44, 32, 47,
		43, 48, 38, 55, 33, 52,
		45, 41, 49, 35, 28, 31}

	i = 0
	j = 31
	C = 0
	While i < 28
		C = C Or BITNUM(key, CInt(key_perm_c(i)), CInt(j))
		i += 1
		j -= 1
	End While

	i = 0
	j = 31
	D = 0
	While i < 28
		D = D Or BITNUM(key, CInt(key_perm_d(i)), CInt(j))
		i += 1
		j -= 1
	End While

	For i = 0 To 15
		C = ((C << CInt(key_rnd_shift(i))) Or (C >> (28 - CInt(key_rnd_shift(i))))) And &HFFFFFFF0UI
		D = ((D << CInt(key_rnd_shift(i))) Or (D >> (28 - CInt(key_rnd_shift(i))))) And &HFFFFFFF0UI

		If mode = DECRYPT Then
			toGen = 15 - i
		Else
			toGen = i
		End If

		For j = 0 To 5
			schedule(toGen, j) = 0
		Next

		For j = 0 To 23
			schedule(toGen, j \ 8) = schedule(toGen, j \ 8) Or BITNUMINTR(C, CInt(key_compression(j)), CInt(7 - (j Mod 8)))
		Next

		While j < 48
			schedule(toGen, j \ 8) = schedule(toGen, j \ 8) Or BITNUMINTR(D, CInt(key_compression(j)) - 28, CInt(7 - (j Mod 8)))
			j += 1
		End While
	Next
End Sub

Private Shared Sub IP(state As UInteger(), input As Byte())
	state(0) = BITNUM(input, 57, 31) Or BITNUM(input, 49, 30) Or BITNUM(input, 41, 29) Or BITNUM(input, 33, 28) Or BITNUM(input, 25, 27) Or BITNUM(input, 17, 26) Or BITNUM(input, 9, 25) Or BITNUM(input, 1, 24) Or BITNUM(input, 59, 23) Or BITNUM(input, 51, 22) Or BITNUM(input, 43, 21) Or BITNUM(input, 35, 20) Or BITNUM(input, 27, 19) Or BITNUM(input, 19, 18) Or BITNUM(input, 11, 17) Or BITNUM(input, 3, 16) Or BITNUM(input, 61, 15) Or BITNUM(input, 53, 14) Or BITNUM(input, 45, 13) Or BITNUM(input, 37, 12) Or BITNUM(input, 29, 11) Or BITNUM(input, 21, 10) Or BITNUM(input, 13, 9) Or BITNUM(input, 5, 8) Or BITNUM(input, 63, 7) Or BITNUM(input, 55, 6) Or BITNUM(input, 47, 5) Or BITNUM(input, 39, 4) Or BITNUM(input, 31, 3) Or BITNUM(input, 23, 2) Or BITNUM(input, 15, 1) Or BITNUM(input, 7, 0)

	state(1) = BITNUM(input, 56, 31) Or BITNUM(input, 48, 30) Or BITNUM(input, 40, 29) Or BITNUM(input, 32, 28) Or BITNUM(input, 24, 27) Or BITNUM(input, 16, 26) Or BITNUM(input, 8, 25) Or BITNUM(input, 0, 24) Or BITNUM(input, 58, 23) Or BITNUM(input, 50, 22) Or BITNUM(input, 42, 21) Or BITNUM(input, 34, 20) Or BITNUM(input, 26, 19) Or BITNUM(input, 18, 18) Or BITNUM(input, 10, 17) Or BITNUM(input, 2, 16) Or BITNUM(input, 60, 15) Or BITNUM(input, 52, 14) Or BITNUM(input, 44, 13) Or BITNUM(input, 36, 12) Or BITNUM(input, 28, 11) Or BITNUM(input, 20, 10) Or BITNUM(input, 12, 9) Or BITNUM(input, 4, 8) Or BITNUM(input, 62, 7) Or BITNUM(input, 54, 6) Or BITNUM(input, 46, 5) Or BITNUM(input, 38, 4) Or BITNUM(input, 30, 3) Or BITNUM(input, 22, 2) Or BITNUM(input, 14, 1) Or BITNUM(input, 6, 0)
End Sub

Private Shared Sub InvIP(state As UInteger(), input As Byte())
	input(0) = CByte(BITNUMINTR(state(1), 7, 7) Or BITNUMINTR(state(0), 7, 6) Or BITNUMINTR(state(1), 15, 5) Or BITNUMINTR(state(0), 15, 4) Or BITNUMINTR(state(1), 23, 3) Or BITNUMINTR(state(0), 23, 2) Or BITNUMINTR(state(1), 31, 1) Or BITNUMINTR(state(0), 31, 0))

	input(1) = CByte(BITNUMINTR(state(1), 6, 7) Or BITNUMINTR(state(0), 6, 6) Or BITNUMINTR(state(1), 14, 5) Or BITNUMINTR(state(0), 14, 4) Or BITNUMINTR(state(1), 22, 3) Or BITNUMINTR(state(0), 22, 2) Or BITNUMINTR(state(1), 30, 1) Or BITNUMINTR(state(0), 30, 0))

	input(2) = CByte(BITNUMINTR(state(1), 5, 7) Or BITNUMINTR(state(0), 5, 6) Or BITNUMINTR(state(1), 13, 5) Or BITNUMINTR(state(0), 13, 4) Or BITNUMINTR(state(1), 21, 3) Or BITNUMINTR(state(0), 21, 2) Or BITNUMINTR(state(1), 29, 1) Or BITNUMINTR(state(0), 29, 0))

	input(3) = CByte(BITNUMINTR(state(1), 4, 7) Or BITNUMINTR(state(0), 4, 6) Or BITNUMINTR(state(1), 12, 5) Or BITNUMINTR(state(0), 12, 4) Or BITNUMINTR(state(1), 20, 3) Or BITNUMINTR(state(0), 20, 2) Or BITNUMINTR(state(1), 28, 1) Or BITNUMINTR(state(0), 28, 0))

	input(4) = CByte(BITNUMINTR(state(1), 3, 7) Or BITNUMINTR(state(0), 3, 6) Or BITNUMINTR(state(1), 11, 5) Or BITNUMINTR(state(0), 11, 4) Or BITNUMINTR(state(1), 19, 3) Or BITNUMINTR(state(0), 19, 2) Or BITNUMINTR(state(1), 27, 1) Or BITNUMINTR(state(0), 27, 0))

	input(5) = CByte(BITNUMINTR(state(1), 2, 7) Or BITNUMINTR(state(0), 2, 6) Or BITNUMINTR(state(1), 10, 5) Or BITNUMINTR(state(0), 10, 4) Or BITNUMINTR(state(1), 18, 3) Or BITNUMINTR(state(0), 18, 2) Or BITNUMINTR(state(1), 26, 1) Or BITNUMINTR(state(0), 26, 0))

	input(6) = CByte(BITNUMINTR(state(1), 1, 7) Or BITNUMINTR(state(0), 1, 6) Or BITNUMINTR(state(1), 9, 5) Or BITNUMINTR(state(0), 9, 4) Or BITNUMINTR(state(1), 17, 3) Or BITNUMINTR(state(0), 17, 2) Or BITNUMINTR(state(1), 25, 1) Or BITNUMINTR(state(0), 25, 0))

	input(7) = CByte(BITNUMINTR(state(1), 0, 7) Or BITNUMINTR(state(0), 0, 6) Or BITNUMINTR(state(1), 8, 5) Or BITNUMINTR(state(0), 8, 4) Or BITNUMINTR(state(1), 16, 3) Or BITNUMINTR(state(0), 16, 2) Or BITNUMINTR(state(1), 24, 1) Or BITNUMINTR(state(0), 24, 0))
End Sub

Private Shared Function F(state As UInteger, key As Byte()) As UInteger
	Dim lrgstate As Byte() = New Byte(5) {}
	Dim t1 As UInteger, t2 As UInteger

	t1 = BITNUMINTL(state, 31, 0) Or ((state And &HF0000000UI) >> 1) Or BITNUMINTL(state, 4, 5) Or BITNUMINTL(state, 3, 6) Or ((state And &HF000000) >> 3) Or BITNUMINTL(state, 8, 11) Or BITNUMINTL(state, 7, 12) Or ((state And &HF00000) >> 5) Or BITNUMINTL(state, 12, 17) Or BITNUMINTL(state, 11, 18) Or ((state And &HF0000) >> 7) Or BITNUMINTL(state, 16, 23)

	t2 = BITNUMINTL(state, 15, 0) Or ((state And &HF000) << 15) Or BITNUMINTL(state, 20, 5) Or BITNUMINTL(state, 19, 6) Or ((state And &HF00) << 13) Or BITNUMINTL(state, 24, 11) Or BITNUMINTL(state, 23, 12) Or ((state And &HF0) << 11) Or BITNUMINTL(state, 28, 17) Or BITNUMINTL(state, 27, 18) Or ((state And &HF) << 9) Or BITNUMINTL(state, 0, 23)

	lrgstate(0) = CByte((t1 >> 24) And &HFF)
	lrgstate(1) = CByte((t1 >> 16) And &HFF)
	lrgstate(2) = CByte((t1 >> 8) And &HFF)
	lrgstate(3) = CByte((t2 >> 24) And &HFF)
	lrgstate(4) = CByte((t2 >> 16) And &HFF)
	lrgstate(5) = CByte((t2 >> 8) And &HFF)

	lrgstate(0) = lrgstate(0) Xor key(0)
	lrgstate(1) = lrgstate(1) Xor key(1)
	lrgstate(2) = lrgstate(2) Xor key(2)
	lrgstate(3) = lrgstate(3) Xor key(3)
	lrgstate(4) = lrgstate(4) Xor key(4)
	lrgstate(5) = lrgstate(5) Xor key(5)

	state = CLng(CInt(CInt(sbox1(SBOXBIT(CByte(lrgstate(0) >> 2)))) << 28) Or (CInt(sbox2(SBOXBIT(CByte(((lrgstate(0) And &H3) << 4) Or (lrgstate(1) >> 4))))) << 24) Or (CInt(sbox3(SBOXBIT(CByte(((lrgstate(1) And &HF) << 2) Or (lrgstate(2) >> 6))))) << 20) Or (CInt(sbox4(SBOXBIT(CByte(lrgstate(2) And &H3F)))) << 16) Or (CInt(sbox5(SBOXBIT(CByte(lrgstate(3) >> 2)))) << 12) Or (CInt(sbox6(SBOXBIT(CByte(((lrgstate(3) And &H3) << 4) Or (lrgstate(4) >> 4))))) << 8) Or (CInt(sbox7(SBOXBIT(CByte(((lrgstate(4) And &HF) << 2) Or (lrgstate(5) >> 6))))) << 4) Or CInt(sbox8(SBOXBIT(CByte(lrgstate(5) And &H3F))))) And UInteger.MaxValue

	state = BITNUMINTL(state, 15, 0) Or BITNUMINTL(state, 6, 1) Or BITNUMINTL(state, 19, 2) Or BITNUMINTL(state, 20, 3) Or BITNUMINTL(state, 28, 4) Or BITNUMINTL(state, 11, 5) Or BITNUMINTL(state, 27, 6) Or BITNUMINTL(state, 16, 7) Or BITNUMINTL(state, 0, 8) Or BITNUMINTL(state, 14, 9) Or BITNUMINTL(state, 22, 10) Or BITNUMINTL(state, 25, 11) Or BITNUMINTL(state, 4, 12) Or BITNUMINTL(state, 17, 13) Or BITNUMINTL(state, 30, 14) Or BITNUMINTL(state, 9, 15) Or BITNUMINTL(state, 1, 16) Or BITNUMINTL(state, 7, 17) Or BITNUMINTL(state, 23, 18) Or BITNUMINTL(state, 13, 19) Or BITNUMINTL(state, 31, 20) Or BITNUMINTL(state, 26, 21) Or BITNUMINTL(state, 2, 22) Or BITNUMINTL(state, 8, 23) Or BITNUMINTL(state, 18, 24) Or BITNUMINTL(state, 12, 25) Or BITNUMINTL(state, 29, 26) Or BITNUMINTL(state, 5, 27) Or BITNUMINTL(state, 21, 28) Or BITNUMINTL(state, 10, 29) Or BITNUMINTL(state, 3, 30) Or BITNUMINTL(state, 24, 31)

	Return (state)
End Function

Public Shared Sub Crypt(input As Byte(), output As Byte(), key As Byte()())
	Dim state As UInteger() = New UInteger(1) {}
	Dim idx As UInteger, t As UInteger

	IP(state, input)

	For idx = 0 To 14
		t = state(1)
		state(1) = F(state(1), key(idx)) Xor state(0)
		state(0) = t
	Next

	state(0) = F(state(1), key(15)) Xor state(0)

	InvIP(state, output)
End Sub
								


Example

									Private Shared Sub PrintText(hash As Byte())
	For i As Integer = 0 To 7
		Console.Write("{0:x2} ", hash(i))
	Next

	Console.WriteLine()
End Sub

Private Shared Function ToJaggedArray(Of T)(twoDimensionalArray As T(,)) As T()()
	Dim rowsFirstIndex As Integer = twoDimensionalArray.GetLowerBound(0)
	Dim rowsLastIndex As Integer = twoDimensionalArray.GetUpperBound(0)
	Dim numberOfRows As Integer = rowsLastIndex + 1

	Dim columnsFirstIndex As Integer = twoDimensionalArray.GetLowerBound(1)
	Dim columnsLastIndex As Integer = twoDimensionalArray.GetUpperBound(1)
	Dim numberOfColumns As Integer = columnsLastIndex + 1

	Dim jaggedArray As T()() = New T(numberOfRows - 1)() {}

	For i As Integer = rowsFirstIndex To rowsLastIndex
		jaggedArray(i) = New T(numberOfColumns - 1) {}

		For j As Integer = columnsFirstIndex To columnsLastIndex
			jaggedArray(i)(j) = twoDimensionalArray(i, j)
		Next
	Next

	Return jaggedArray
End Function
'**********************************************'

'***************Example Code***************'
Dim text As Byte() = {&H1, &H23, &H45, &H67, &H89, &HAB, &HCD, &HE7}
Dim key As Byte() = {&H1, &H23, &H45, &H67, &H89, &HAB, &HCD, &HEF}
Dim output As Byte() = New Byte(7) {}
Dim schedule As Byte(,) = New Byte(15, 5) {}

KeySchedule(key, schedule, ENCRYPT)
Crypt(text, output, ToJaggedArray(schedule))
Console.Write("Encrypt Output: ")
PrintText(output)

KeySchedule(key, schedule, DECRYPT)
Crypt(output, text, ToJaggedArray(schedule))
Console.Write("Decrypt Output: ")
PrintText(text)
'******************************************'
								


Output

									Encrypt Output: c9 57 44 25 6a 5e d3 1d
Decrypt Output: 01 23 45 67 89 ab cd e7