Release history:
1.0 - 2014-Jun-02 - initial release
1.0.1 - 2014-Jun-03 - minor fix (incorrect key size for 168 bit 3DES)
1.0.2 - 2014-Jun-04 - bug fix in test and added some more global procedures. Input size in multiples of 8 is now enforced and a result of 0 is returned if not
Code: Select all
; ==========================================================================
; DES/3DES cipher module (native PureBasic x86)
; Module version: 1.0.2 (non-optimised)
; Description:
; Cipher: DES/TripleDES EDE CBC
; Key options: 56, 112 and 168 bit (DES is 56 bit only)
; Block mode: CBC
; Optimisiations:
; - global key schedule
; OS: all (Win/Lin/Mac)
; Developed on: PB 5.22 LTS x64 / Windows 7 x64
; Author: coco2
; Credit: see "further reading" list below
; Created: 30-May-2014
; Modified: 03-Jun-2014
; License: open
; Release history:
; 1.0 - 2014-Jun-02 - initial release
; 1.0.1 - 2014-Jun-03 - minor fix (incorrect key size for 168 bit 3DES)
; 1.0.2 - 2014-Jun-04 - bug fix in test and added some more global
; procedures. Input size in multiples of 8 is now
; enforced and a result of 0 is returned if not
;
; Provided "as is" with no warranty and no liability.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.
;
; Notes:
; 1. The authors/copyright holder(s) of this module are not affiliated with
; the PureBasic software authors/copyright holders.
; 2. This DES/3DES module is intended for educational purposes or for
; legacy applications and not encrypting sensitive data since:
; 2.1. DES is considered outdated and too weak for securing data.
; 2.2. 3DES is still in use but is not recommended due to meet-in-the-middle
; attacks.
; ==========================================================================
;
; Further reading:
;
; - http://en.wikipedia.org/wiki/Data_Encryption_Standard
; - http://en.wikipedia.org/wiki/Triple_DES
; - Implementing SSL / TLS Using Cryptography and PKI
; (ISBN: 978-0-470-92041-1)
; - FIPS PUB 46-3 (http://csrc.nist.gov/publications/fips/fips46-3/
; fips46-3.pdf)
; - Helpful site: http://dhost.info/pasjagor/des/start.php?id=0
;
; ==========================================================================
PurifierGranularity(1,1,1,1)
EnableExplicit
DeclareModule DES
;- Public constants
Enumeration DES_Operation
#DES_ENCRYPT
#DES_DECRYPT
EndEnumeration
#DES_BLOCK_SIZE = 8
#DES_KEY_SIZE = 8
;- Public procedures
Declare MakeIV(*IV)
Declare DESEncryptCBC(*in, length.i, *out, *iv, *key)
Declare DESDecryptCBC(*in, length.i, *out, *iv, *key)
Declare TripleDESEncryptCBC(*in, length.i, *out, *iv, *key, key_length.i)
Declare TripleDESDecryptCBC(*in, length.i, *out, *iv, *key, key_length.i)
Declare TripleDES112EncryptCBC(*in, length.i, *out, *iv, *key)
Declare TripleDES112DecryptCBC(*in, length.i, *out, *iv, *key)
Declare TripleDES168EncryptCBC(*in, length.i, *out, *iv, *key)
Declare TripleDES168DecryptCBC(*in, length.i, *out, *iv, *key)
EndDeclareModule
Module DES
;- Private constants
#DES_EXPANSION_BLOCK_SIZE = 6
#DES_PC1_KEY_SIZE = 7
#DES_SUBKEY_SIZE = 6
;- Private globals
; DES lookup tables
Global Dim IP_Table.a(63)
Global Dim FP_Table.a(63)
Global Dim PC1_Table.a(55)
Global Dim PC2_Table.a(55)
Global Dim Expansion_Table.a(47)
Global Dim sbox.a(7, 63)
Global Dim P_Table.a(31)
Global Dim Precomputed_subkeys.a(7, 15, 2) ; key bytes (0-7), round (0-15), key set (0-2)
; scratch arrays
Global Dim IP_Block.a(#DES_BLOCK_SIZE-1)
Global Dim IP_Block_Low.a(#DES_BLOCK_SIZE/2 - 1)
Global Dim Expansion_Block.a(#DES_EXPANSION_BLOCK_SIZE-1)
Global Dim Substitution_Block.a(#DES_BLOCK_SIZE / 2 - 1)
Global Dim pbox_target.a(#DES_BLOCK_SIZE / 2 - 1)
Global Dim recomb_box.a(#DES_BLOCK_SIZE / 2 - 1)
Global Dim pc1key.a(#DES_PC1_KEY_SIZE-1)
Global Dim subkey.a(#DES_SUBKEY_SIZE-1)
; Private procedures
Procedure XORMem(*Target, *Source, length.i)
; XORs target With source array And places result in target array
Define.i c ; counter
Define.a sv, tv ; source and target value
For c=0 To length-1
tv=PeekA(*Target+c)
sv=PeekA(*Source+c)
tv = tv ! sv
PokeA(*Target+c,tv)
Next
EndProcedure
Procedure Permute(Array Target.a(1), Array Source.a(1), Array permuteTable.a(1), length.i)
Define.a i=0, bit
While i<length*8
bit=permuteTable(i)-1
If Source(bit/8)&(128>>(bit%8)) ; get the state of the bit
Target(i/8)|(128>>(i%8)) ; set the bit
Else
Target(i/8)&~(128>>(i%8)) ; clear the bit
EndIf
i=i+1
Wend
EndProcedure
Procedure RotateKeyLeft(Array Target.a(1))
Define carry_left.a, carry_right.a
carry_left = (Target(0) & $80) >> 3
Target(0) = (Target(0) << 1) | ((Target(1) & $80) >> 7)
Target(1) = (Target(1) << 1) | ((Target(2) & $80) >> 7)
Target(2) = (Target(2) << 1) | ((Target(3) & $80) >> 7)
carry_right = (Target(3) & $08) >> 3
Target(3) = (((Target(3) << 1) | ((Target(4) & $80) >> 7)) & ~$10) | carry_left
Target(4) = (Target(4) << 1) | ((Target(5) & $80) >> 7)
Target(5) = (Target(5) << 1) | ((Target(6) & $80) >> 7)
Target(6) = (Target(6) << 1) | carry_right
EndProcedure
Procedure RotateKeyRight(Array Target.a(1))
Define carry_left.a, carry_right.a
carry_right = (Target(6) & $01) << 3
Target(6) = (Target(6) >> 1) | ((Target(5) & $01) << 7)
Target(5) = (Target(5) >> 1) | ((Target(4) & $01) << 7)
Target(4) = (Target(4) >> 1) | ((Target(3) & $01) << 7)
carry_left = (Target(3) & $10) << 3
Target(3) = (((Target(3) >> 1) | ((Target(2) & $01) << 7)) & ~$08) | carry_right
Target(2) = (Target(2) >> 1) | ((Target(1) & $01) << 7)
Target(1) = (Target(1) >> 1) | ((Target(0) & $01) << 7)
Target(0) = (Target(0) >> 1) | carry_left
EndProcedure
Procedure.i Initialise()
; Called automatically
CopyMemory(?DES_IP_Table,@IP_Table(), 64) ; initial permutation
CopyMemory(?DES_FP_Table,@FP_Table(), 64) ; final permutation
CopyMemory(?DES_PC1_Table,@PC1_Table(), 56) ; key permutation table 1
CopyMemory(?DES_PC2_Table,@PC2_Table(), 56) ; key permutation table 2
CopyMemory(?DES_Expansion_Table,@Expansion_Table(), 48) ; key expansion table
CopyMemory(?DES_sbox1,@sbox(), 512) ; sboxes - lookup tables for scrambling the data
CopyMemory(?DES_p_table,@P_Table(),32) ; final permute of the substitution table built from sboxes
EndProcedure
Procedure MakeIV(*IV)
; Generates 8 random bytes in memory located at *IV
OpenCryptRandom()
CryptRandomData(*IV,8)
CloseCryptRandom()
EndProcedure
Procedure ClearSubkeys()
FillMemory(@Precomputed_subkeys(), 168, 0)
EndProcedure
Procedure MakeSubkeys(*key, length.i, Operation.i=#DES_ENCRYPT)
; Pass a pointer to 8-24 bytes to precompute subkeys in global array Precomputed_subkeys()
; For DES use 8 byte key, for TripleDES 8-24 bytes
; Note: 8 byte key produces the same output for DES and 3DES
; 16 and 24 byte keys only used in 3DES, DES ignores bytes >16
Define R.i, Num_keys.i = 0, Result.i = 0
Define Keyset.i = 0
Define Offset.i = 0 ; the offset in the subkey array to write the next computed subkey to
Dim temp_key.a(7)
If Not (length % 8) Or (length = 8) ; make sure key is valid length
Num_keys = length / 8 - 1
For Keyset = 0 To Num_keys
CopyMemory(*key+Keyset*#DES_KEY_SIZE, @temp_key(),8)
Permute(pc1key(), temp_key(), PC1_table(), #DES_PC1_KEY_SIZE); generate initial subkey value
For R = 0 To 15
If Operation=#DES_ENCRYPT
RotateKeyLeft(pc1key())
If Not (R<=1 Or R=8 Or R=15)
RotateKeyLeft(pc1key())
EndIf
EndIf
Permute(subkey(), pc1key(), pc2_table(), #DES_SUBKEY_SIZE)
If Operation=#DES_DECRYPT
RotateKeyRight(pc1key())
If Not (R=0 Or R=7 Or R>=14)
RotateKeyRight(pc1key())
EndIf
EndIf
CopyMemory(@subkey(), @Precomputed_subkeys() + Offset, #DES_SUBKEY_SIZE) ; store rotated key
Offset+#DES_SUBKEY_SIZE ; move to next subkey slot
Next R
Operation = 1 - Operation
Next Keyset
Result = 1
If Num_keys < 2 ; Keying option 2 - K3=K1
MoveMemory(@Precomputed_subkeys(), @Precomputed_subkeys()+192, 96)
EndIf
If Num_keys=0 ; Keying option 3 - K1=K2=K3 (not recommended but included for backwards compatibility)
MoveMemory(@Precomputed_subkeys(), @Precomputed_subkeys()+96, 96)
EndIf
Else
Debug "DES::MakeSubkeys: ERROR! Key length not a multiple of 8"
Result = 0
EndIf
ProcedureReturn
EndProcedure
Procedure ProcessBlock(Array input_buffer.a(1), Array output_buffer.a(1), keyset.i=0)
; Encrypts or decrypts a 64-bit (8 byte) block of data in DES ECB mode.
; Pre-requisites: MUST have previously called MakeSubkeys() before using.
; Parameters:
; input_buffer(): 64-bit (8 byte) array of input data
; output_buffer(): 64-bit (8 byte) array of output data
; keyset: 0, 1 or 2 to select the 3DES keyset (always 0 for DES)
Define R.i, key_offset.i
key_offset = keyset * 96
Permute(ip_block(), input_buffer(), ip_table(), #DES_BLOCK_SIZE);
For R = 0 To 15
CopyMemory(@IP_Block()+4, @IP_Block_Low(), 4)
Permute(expansion_block(), IP_Block_Low(), expansion_table(), 6)
XORMem(@expansion_block(), @Precomputed_subkeys() + key_offset + (R * #DES_SUBKEY_SIZE), 6)
FillMemory(@Substitution_Block(), 4, 0)
substitution_block(0) = sbox(0,(expansion_block(0) & $FC) >> 2 ) << 4
substitution_block(0) | sbox(1,(expansion_block(0) & $03) << 4 | (Expansion_Block(1) & $F0) >> 4)
substitution_block(1) = sbox(2,(expansion_block(1) & $0F) << 2 | (Expansion_Block(2) & $C0) >> 6 ) << 4
substitution_block(1) | sbox(3,(expansion_block(2) & $3F))
substitution_block(2) = sbox(4,(expansion_block(3) & $FC) >> 2) << 4
substitution_block(2) | sbox(5,(expansion_block(3) & $03) << 4 | (Expansion_Block(4) & $F0) >> 4)
substitution_block(3) = sbox(6,(expansion_block(4) & $0F) << 2 | (Expansion_Block(5) & $C0) >> 6 ) << 4
substitution_block(3) | sbox(7,(expansion_block(5) & $3F))
Permute(pbox_target(), substitution_block(), P_Table(), 4)
CopyMemory(@IP_Block(), @recomb_box(), 4)
CopyMemory(@IP_Block()+4, @IP_Block(), 4)
XORMem(@recomb_box(), @pbox_target(), 4)
CopyMemory(@recomb_box(), @IP_Block()+4, 4)
Next R
CopyMemory(@IP_Block(), @recomb_box(), 4)
CopyMemory(@IP_Block()+4, @IP_Block(), 4)
CopyMemory(@recomb_box(), @IP_Block()+4, 4)
Permute(output_buffer(), ip_block(), fp_table(), 8) ; return processed block
EndProcedure
Procedure.i ProcessBufferCBC(*in, length.i, *out, *iv, operation.i=#DES_ENCRYPT, triple.i=#False)
; Encrypts or decrypts any block of data in CBC mode.
; Pre-requisites: MUST have previously called MakeSubkeys() before using.
; Parameters:
; *in: pointer to input data
; length: size in bytes of input data (MUST be in multiples of 8)
; *out: output buffer (MUST be the same length as input buffer)
; *iv: 8 byte initialisation vector
; operation: #DES_DECRYPT or #DES_ENCRYPT
; triple: #False for DES, #True for 3DES
; Note: padding must be dealt with before calling
;
Define result.i=0
If Not length%8
Dim input_block.a(#DES_BLOCK_SIZE-1)
Dim temp_out.a(#DES_BLOCK_SIZE-1)
Dim temp_iv.a(#DES_KEY_SIZE-1)
Define c.i=0
CopyMemory(*iv, @temp_iv(), #DES_KEY_SIZE)
While c<length
CopyMemory(*in+c, @input_block(), #DES_BLOCK_SIZE)
If Operation=#DES_ENCRYPT
XORMem(@input_block(), @temp_iv(), #DES_BLOCK_SIZE)
ProcessBlock(input_block(), temp_out(), 0) ; DES and 3DES encrypt
If triple ; 3DES encrypt
CopyMemory(@temp_out(), @input_block(), #DES_BLOCK_SIZE)
ProcessBlock(input_block(), temp_out(), 1)
CopyMemory(@temp_out(), @input_block(), #DES_BLOCK_SIZE)
ProcessBlock(input_block(), temp_out(), 2)
EndIf
CopyMemory(@temp_out(), @temp_iv(), #DES_BLOCK_SIZE) ; update IV
Else ; Decrypt
If triple ; 3DES decrypt
ProcessBlock(input_block(), temp_out(), 2)
CopyMemory(@temp_out(), @input_block(), #DES_BLOCK_SIZE)
ProcessBlock(input_block(), temp_out(), 1)
CopyMemory(@temp_out(), @input_block(), #DES_BLOCK_SIZE)
EndIf
ProcessBlock(input_block(), temp_out(), 0)
XORMem(@temp_out(), @temp_iv(), #DES_BLOCK_SIZE)
CopyMemory(*in+c, @temp_iv(), #DES_BLOCK_SIZE) ; update IV
EndIf
CopyMemory(@temp_out(), *out+c, #DES_BLOCK_SIZE)
c=c+#DES_BLOCK_SIZE
Wend
result=1
EndIf
ProcedureReturn result
EndProcedure
Procedure.i TripleDESEncryptCBC(*in, length.i, *out, *iv, *key, key_length.i)
Define result.i=0
MakeSubkeys(*key, key_length, #DES_ENCRYPT)
result = ProcessBufferCBC(*in, length, *out, *iv, #DES_ENCRYPT, #True)
ClearSubkeys()
ProcedureReturn result
EndProcedure
Procedure.i TripleDESDecryptCBC(*in, length.i, *out, *iv, *key, key_length.i)
Define result.i=0
MakeSubkeys(*key, key_length, #DES_DECRYPT)
result = ProcessBufferCBC(*in, length, *out, *iv, #DES_DECRYPT, #True)
ClearSubkeys()
ProcedureReturn result
EndProcedure
;- Encryption suite procedures
Procedure.i DESEncryptCBC(*in, length.i, *out, *iv, *key)
Define result.i=0
MakeSubkeys(*key, 8, #DES_ENCRYPT)
result = ProcessBufferCBC(*in, length, *out, *iv, #DES_ENCRYPT, #False)
ClearSubkeys()
ProcedureReturn result
EndProcedure
Procedure.i DESDecryptCBC(*in, length.i, *out, *iv, *key)
Define result.i=0
MakeSubkeys(*key, 8, #DES_DECRYPT)
result = ProcessBufferCBC(*in, length, *out, *iv, #DES_DECRYPT, #False)
ClearSubkeys()
ProcedureReturn result
EndProcedure
Procedure.i TripleDES112EncryptCBC(*in, length.i, *out, *iv, *key)
Define result.i=0
MakeSubkeys(*key, 16, #DES_ENCRYPT)
result = ProcessBufferCBC(*in, length, *out, *iv, #DES_ENCRYPT, #True)
ClearSubkeys()
ProcedureReturn result
EndProcedure
Procedure.i TripleDES112DecryptCBC(*in, length.i, *out, *iv, *key)
Define result.i=0
MakeSubkeys(*key, 16, #DES_DECRYPT)
result = ProcessBufferCBC(*in, length, *out, *iv, #DES_DECRYPT, #True)
ClearSubkeys()
ProcedureReturn result
EndProcedure
Procedure.i TripleDES168EncryptCBC(*in, length.i, *out, *iv, *key)
Define result.i=0
MakeSubkeys(*key, 24, #DES_ENCRYPT)
result = ProcessBufferCBC(*in, length, *out, *iv, #DES_ENCRYPT, #True)
ClearSubkeys()
ProcedureReturn result
EndProcedure
Procedure.i TripleDES168DecryptCBC(*in, length.i, *out, *iv, *key)
Define result.i=0
MakeSubkeys(*key, 24, #DES_DECRYPT)
result = ProcessBufferCBC(*in, length, *out, *iv, #DES_DECRYPT, #True)
ClearSubkeys()
ProcedureReturn result
EndProcedure
Procedure.i SelfTest()
Dim test_plaintext.a(8)
Dim test_ciphertext.a(8)
Dim test_expected.a(8)
Dim test_key.a(24)
Dim test_IV.a(8)
Define test_s.s
Define *in_test, *out_test
Define test_length.i, result_length.i
Define test_result.i=0
Define result.i=1
; Test basic block operation
Debug "Testing block operation..."
CopyMemory(?Test_Block, @test_plaintext(), 8)
CopyMemory(?test_expected, @test_expected(), 8)
CopyMemory(?Test_Key, @test_key(), 24)
MakeSubkeys(@test_key(), 8, #DES_ENCRYPT)
ProcessBlock(test_plaintext(), test_ciphertext())
If CompareMemory(@test_expected(), @test_ciphertext(), 8):Debug "Block encrypt OK":
Else:Debug "Block encrypt fail":Result=0:EndIf
CopyMemory(?Test_block, @test_expected(), 8)
CopyMemory(@test_ciphertext(), @test_plaintext(), 8)
MakeSubkeys(@test_key(), 8, #DES_DECRYPT)
ProcessBlock(test_plaintext(), test_ciphertext())
If CompareMemory(@test_expected(), @test_ciphertext(), 8):Debug "Block decrypt OK":
Else:Debug "Block decrypt fail":Result=0:EndIf
; Test CBC procedures
MakeIV(@test_IV())
test_s = "In cryptography, Triple DES (3DES) is the common name for the Triple Data Encryption Algorithm (TDEA or Triple DEA) symmetric-key block cipher, which applies the Data Encryption Standard (DES) cipher algorithm three times to each data block."
; Test DES CBC
test_length = StringByteLength(test_s)
result_length = test_length
If result_length % 8
result_length=result_length + 8 - (test_length % 8)
EndIf
*in_test=AllocateMemory(result_length)
*out_test=AllocateMemory(result_length)
CopyMemory(@test_s, *in_test, test_length)
Debug "Testing DES (56-bit) CBC..."
test_result = DESEncryptCBC(*in_test, result_length, *out_test, @test_IV(), @test_key())
CopyMemory(*out_test, *in_test, result_length)
If test_result
test_result = DESDecryptCBC(*in_test, result_length, *out_test, @test_IV(), @test_key())
EndIf
If test_result
test_result = CompareMemory(*out_test, @test_s, test_length)
EndIf
If test_result:Debug "DES CBC OK":
Else: Debug "DES CBC fail": Result=0:EndIf
; Test 3DES CBC
For key_size=1 To 3
Debug "Testing 3DES (" + Str(key_size * 56) + "-bit) CBC..."
FillMemory(*in_test, result_length)
CopyMemory(@test_s, *in_test, test_length)
test_result = TripleDESEncryptCBC(*in_test, result_length, *out_test, @test_IV(), @test_key(), key_size*8)
CopyMemory(*out_test, *in_test, result_length)
If test_result
test_result = TripleDESDecryptCBC(*in_test, result_length, *out_test, @test_IV(), @test_key(), key_size*8)
EndIf
If test_result
test_result = CompareMemory(*out_test, @test_s, test_length)
EndIf
If test_result:Debug "3DES (" + Str(key_size * 56) + "-bit) CBC OK":
Else: Debug "3DES (" + Str(key_size * 56) + "-bit) CBC fail": Result=0:EndIf
Next key_size
If Result:Debug "Self test OK":Else:Debug "Self test FAIL":EndIf
FreeMemory(*in_test)
FreeMemory(*out_test)
ProcedureReturn result
EndProcedure
Initialise()
CompilerIf #PB_Compiler_IsMainFile
SelfTest()
CompilerEndIf
;- Data Section
DataSection
Test_key:
Data.a $5B, $5A, $57, $67, $6A, $56, $67, $6E, $2A, $3A, $11, $37, $6F, $22, $33, $44, $55, $66, $77, $88, $99, $AA, $BB, $CC
Test_block:
Data.a $67, $5A, $69, $67, $5E, $5A, $6B, $5A
test_expected:
Data.a $97, $4A, $FF, $BF, $86, $02, $2D, $1F
DES_IP_Table: ; initial permutation of the data
Data.a 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
DES_FP_Table: ; final permutation of the data
Data.a 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
DES_PC1_Table: ;permuted choice 1
Data.a 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2,
59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6,
61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
DES_PC2_Table: ;permuted choice 2
Data.a 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
DES_expansion_table: ; for expanding 32 bits into 48
Data.a 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1
; Substitution boxes
DES_sbox1:
Data.a 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13
DES_sbox2:
Data.a 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9
DES_sbox3:
Data.a 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12
DES_sbox4:
Data.a 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14
DES_sbox5:
Data.a 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3
DES_sbox6:
Data.a 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13
DES_sbox7:
Data.a 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12
DES_sbox8:
Data.a 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
DES_p_table: ; substitution block permutation table
Data.a 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
EndDataSection
EndModule