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