Data Encryption Standard

From Rosetta Code
Data Encryption Standard is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Demonstrate the Data Encryption Standard. For a complete description of the algorithm see: The DES Algorithm Illustrated


Task:

Use the

Key 0e329232ea6d0d73
to encrypt 8787878787878787
and display the result 0000000000000000.

Kotlin[edit]

Version 1 (using library functions)[edit]

Presumably, one can use library functions to demonstrate DES as it would be very tedious to implement it from scratch:

// version 1.1.3
 
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec
 
fun String.toHexByteArray(): ByteArray {
val bytes = ByteArray(this.length / 2)
for (i in 0 until bytes.size) {
bytes[i] = this.substring(i * 2, i * 2 + 2).toInt(16).toByte()
}
return bytes
}
 
fun ByteArray.printHexBytes(label: String) {
print("$label: ")
for (b in this) {
val bb = if (b >= 0) b.toInt() else b + 256
print(bb.toString(16).padStart(2, '0'))
}
println()
}
 
fun main(args: Array<String>) {
val strKey = "0e329232ea6d0d73"
val keyBytes = strKey.toHexByteArray()
val key = SecretKeySpec(keyBytes, "DES")
val encCipher = Cipher.getInstance("DES")
encCipher.init(Cipher.ENCRYPT_MODE, key)
val strPlain = "8787878787878787"
val plainBytes = strPlain.toHexByteArray()
val encBytes = encCipher.doFinal(plainBytes)
encBytes.printHexBytes("Encoded")
 
val decCipher = Cipher.getInstance("DES")
decCipher.init(Cipher.DECRYPT_MODE, key)
val decBytes = decCipher.doFinal(encBytes)
decBytes.printHexBytes("Decoded")
}
Output:

Note that the 'encoded' output includes 8 bytes of padding using the default JVM DES implementation:

Encoded: 0000000000000000a913f4cb0bd30f97
Decoded: 8787878787878787

Version 2 (from scratch)[edit]

It wasn't as tedious as I expected due to the admirably clear article linked to above:

// version 1.1.3
 
import java.util.BitSet
 
object DES {
 
private val PC1 = intArrayOf(
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
)
 
private val PC2 = intArrayOf(
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
)
 
private val IP = intArrayOf(
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
)
 
private val E = intArrayOf(
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
)
 
private val S = arrayOf(
intArrayOf(
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
),
 
intArrayOf(
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
),
 
intArrayOf(
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
),
 
intArrayOf(
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
),
 
intArrayOf(
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
),
 
intArrayOf(
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
),
 
intArrayOf(
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
),
 
intArrayOf(
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
)
)
 
private val P = intArrayOf(
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
)
 
private val IP2 = intArrayOf(
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
)
 
private val SHIFTS = intArrayOf(1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1)
 
fun encrypt(key: String, message: String): String {
val ks = getSubKeys(key)
var m = message
val r = m.length % 16 // check if multiple of 16 hex digits
if (r != 0) {
val len = (1 + m.length / 16) * 16
m = m.padEnd(len, '0') // pad with zeros for simplicity
}
val sb = StringBuilder()
for (i in 0 until m.length / 16) {
val j = i * 16
val enc = processMessage(m.substring(j, j + 16), ks)
sb.append(enc)
}
return sb.toString()
}
 
/* any padding is assumed to be in the form of trailing zeros following 0DOA;
only the zeros will be removed */

fun decrypt(key: String, encoded: String, removePadding: Boolean = false): String {
val ks = getSubKeys(key)
// reverse the subkeys
for (i in 1..8) {
val temp = ks[i]
ks[i] = ks[17 - i]
ks[17 - i] = temp
}
val sb = StringBuilder()
for (i in 0 until encoded.length / 16) {
val j = i * 16
val dec = processMessage(encoded.substring(j, j + 16), ks)
sb.append(dec)
}
var decoded = sb.toString()
if (removePadding && decoded.indexOf("0D0A") > -1) decoded = decoded.trimEnd('0')
return decoded
}
 
private fun getSubKeys(key: String): Array<BitSet> {
val k = key.toLittleEndianBitSet()
 
// permute 'key' using table PC1
val kp = BitSet(56)
for (i in 0..55) kp[i] = k[PC1[i] - 1]
 
// split 'kp' in half and process the resulting series of 'c' and 'd'
val c = Array(17) { BitSet(56) }
val d = Array(17) { BitSet(28) }
for (i in 0..27) c[0][i] = kp[i]
for (i in 0..27) d[0][i] = kp[i + 28]
for (i in 1..16) {
c[i - 1].shiftLeft(SHIFTS[i - 1], 28, c[i])
d[i - 1].shiftLeft(SHIFTS[i - 1], 28, d[i])
}
 
// merge 'd' into 'c'
for (i in 1..16) {
for(j in 28..55) c[i][j] = d[i][j - 28]
}
 
// form the sub-keys and store them in 'ks'
val ks = Array(17) { BitSet(48) }
 
// permute 'c' using table PC2
for (i in 1..16) {
for (j in 0..47) ks[i][j] = c[i][PC2[j] - 1]
}
 
return ks
}
 
private fun processMessage(message: String, ks: Array<BitSet>): String {
val m = message.toLittleEndianBitSet()
 
// permute 'message' using table IP
val mp = BitSet(64)
for (i in 0..63) mp[i] = m[IP[i] - 1]
 
// split 'mp' in half and process the resulting series of 'l' and 'r
val l = Array(17) { BitSet(32) }
val r = Array(17) { BitSet(32) }
for (i in 0..31) l[0][i] = mp[i]
for (i in 0..31) r[0][i] = mp[i + 32]
f(r[0], ks[1])
for (i in 1..16) {
l[i] = r[i - 1]
val fs = f(r[i - 1], ks[i])
l[i - 1].xor(fs)
r[i] = l[i - 1]
}
 
// amalgamate r[16] and l[16] (in that order) into 'e'
val e = BitSet(64)
for (i in 0..31) e[i] = r[16][i]
for (i in 32..63) e[i] = l[16][i - 32]
 
// permute 'e' using table IP2 ad return result as a hex string
val ep = BitSet(64)
for (i in 0..63) ep[i] = e[IP2[i] - 1]
return ep.toHexString(64)
}
 
/* assumes a hex string receiver */
private fun String.toLittleEndianBitSet(): BitSet {
val bs = BitSet(this.length * 4)
for ((i, c) in this.withIndex()) {
val s = c.toString().toByte(16).toString(2).padStart(4, '0')
for (j in 0..3) bs[i * 4 + j] = (s[j] == '1')
}
return bs
}
 
/* assumes a little-endian bitset receiver */
private fun BitSet.toHexString(len: Int): String {
val size = len / 4
val sb = StringBuilder(size)
val ba = ByteArray(4)
for (i in 0 until size) {
for (j in 0..3) ba[j] = if (this[i * 4 + j]) 1 else 0
val c = "%X".format(ba[0] * 8 + ba[1] * 4 + ba[2] * 2 + ba[3])
sb.append(c)
}
return sb.toString()
}
 
private fun BitSet.shiftLeft(times: Int, len: Int, out: BitSet) {
for (i in 0 until len) out[i] = this[i]
for (t in 1..times) {
val temp = out[0]
for (i in 1 until len) out[i - 1] = out[i]
out[len - 1] = temp
}
}
 
private fun f(r: BitSet, ks: BitSet): BitSet {
// permute 'r' using table E
val er = BitSet(48)
for (i in 0..47) er[i] = r[E[i] - 1]
 
// xor 'er' with 'ks' and store back into 'er'
er.xor(ks)
 
// process 'er' six bits at a time and store resulting four bits in 'sr'
val sr = BitSet(32)
for (i in 0..7) {
val j = i * 6
val b = IntArray(6)
for (k in 0..5) b[k] = if (er[j + k]) 1 else 0
val row = 2 * b[0] + b[5]
val col = 8 * b[1] + 4 * b[2] + 2 * b[3] + b[4]
var m = S[i][row * 16 + col] // apply table S
var n = 1
while (m > 0) {
val p = m % 2
sr[(i + 1) * 4 - n] = (p == 1)
m /= 2
n++
}
}
 
// permute sr using table P
val sp = BitSet(32)
for (i in 0..31) sp[i] = sr[P[i] - 1]
return sp
}
}
 
fun main(args: Array<String>) {
val keys = listOf("133457799BBCDFF1", "0E329232EA6D0D73", "0E329232EA6D0D73")
val messages = listOf(
"0123456789ABCDEF",
"8787878787878787",
"596F7572206C6970732061726520736D6F6F74686572207468616E20766173656C696E650D0A"
)
val padding = booleanArrayOf(false, false, true)
for (i in 0..2) {
println("Key  : ${keys[i]}")
println("Message : ${messages[i]}")
val encoded = DES.encrypt(keys[i], messages[i])
println("Encoded : $encoded")
val decoded = DES.decrypt(keys[i], encoded, padding[i])
println("Decoded : $decoded")
println()
}
}
Output:
Key     : 133457799BBCDFF1
Message : 0123456789ABCDEF
Encoded : 85E813540F0AB405
Decoded : 0123456789ABCDEF

Key     : 0E329232EA6D0D73
Message : 8787878787878787
Encoded : 0000000000000000
Decoded : 8787878787878787

Key     : 0E329232EA6D0D73
Message : 596F7572206C6970732061726520736D6F6F74686572207468616E20766173656C696E650D0A
Encoded : C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F5358499828AC9B453E0E653
Decoded : 596F7572206C6970732061726520736D6F6F74686572207468616E20766173656C696E650D0A

REXX[edit]

Implementation of the algorithm desribed in the cited article.
Decryption is now supported as well

Parse Upper Arg action
Select
When action='?' Then Do
Say "REXX des shows how '8787878787878787'X is encoded to"
Say " '000000000000000'X"
Say "REXX des DEC shows how '000000000000000'X is decoded to"
Say " '8787878787878787'X"
Exit
End
When action='' | action='ENC' Then
encode=1
When action='' | action='DEC' Then
encode=0
Otherwise Do
Say 'Invalid argument' action '(must be ENC or DEC or omitted)'
Exit
End
End
o='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.-'
Call init
Call debug 'tr_pc_1='tr_pc_1
Call debug 'tr_ip ='tr_ip
Call debug 'tr_p ='tr_p
Call debug 'tr_ipa ='tr_ipa
 
kx='0e329232ea6d0d73'
If encode Then
mx='8787878787878787'
Else
mx='0000000000000000'
k=x2b(kx)
m=x2b(mx)
Say 'Message:' mx
Say 'Key  :' kx
ka=translate(tr_pc_1,k,o)
Call debug 'ka='ka
Parse Var ka c.0 +28 d.0
shifts='1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1'
Do i=1 To 16
ip=i-1
c.i=shift(c.ip,word(shifts,i))
d.i=shift(d.ip,word(shifts,i))
End
Do i=1 To 16
cd.i=c.i||d.i
k.i=translate(tr_pc_2,cd.i,o)
Call debug 'k.'i'='k.i
End
 
If encode=0 Then Do /*revert the subkeys */
Do i=1 To 16
j=17-i
kd.i=k.j
End
Do i=1 To 16
k.i=kd.i
End
End
 
IP=translate(tr_ip,m,o)
Call debug 'ip='ip
 
Parse Var ip l.0 +32 r.0
 
Call debug 'E(R.0)='E(R.0)
Call debug 'k.1 ='k.1
t=xor(k.1,E(R.0))
Call debug 't ='t
Call debug length(t)
zz=''
Do i=1 To 8
Parse Var t b +6 t
zz=zz||s(i,b)
End
Call debug 'zz='zz
f=translate(tr_p,zz,o)
Call debug 'f='f
r.1=xor(l.0,f)
Call debug 'r.1='r.1
l.1=r.0
Do j=2 To 16
ja=j-1
l.j=r.ja
z=xor(k.j,e(r.ja))
zz=''
Do i=1 To 8
Parse Var z b +6 z
zz=zz||s(i,b)
End
Call debug j zz
f=translate(tr_p,zz,o)
Call debug j f
r.j=xor(l.ja,f)
End
Call debug 'l.16='l.16
Call debug 'r.16='r.16
 
zzz=r.16||l.16
c=translate(tr_ipa,zzz,o)
Call debug c
Say 'Result :' b2x(c)
Exit
 
f: Procedure Expose s. o tr_p
Parse Arg r,k
z=xor(k,e(r))
zz=translate(tr_p,z,o)
Return zz
 
init:
PC_1='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'
tr_pc_1=''
Do i=1 To words(pc_1)
tr_pc_1=tr_pc_1||substr(o,word(pc_1,i),1)
End
tr_pc_1=tr_pc_1
 
kb=translate(tr_pc_1,k,o)
kc=strip(kb,,'*')
 
PC_2='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'
tr_pc_2=''
Do i=1 To words(pc_2)
tr_pc_2=tr_pc_2||substr(o,word(pc_2,i),1)
End
 
Do i=1 To 16
cd.i=c.i||d.i
k.i=translate(ok,cd.i,o)
Call debug 'k.'i'='k.i
End
 
IP='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'
tr_ip=''
Do i=1 To words(IP)
tr_ip=tr_ip||substr(o,word(ip,i),1)
End
 
 
P='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'
tr_p=''
Do i=1 To words(p)
tr_p=tr_p||substr(o,word(p,i),1)
End
 
SM.1='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'
SM.2='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'
SM.3='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'
SM.4=' 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'
SM.5=' 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'
SM.6='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'
SM.7=' 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'
SM.8='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'
Do i=1 To 8
Do r=0 To 3
Do c=0 To 15
Parse Var sm.i s.i.r.c sm.i
End
End
End
 
ipa='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'
tr_ipa=''
Do i=1 To words(ipa)
tr_ipa=tr_ipa||substr(o,word(ipa,i),1)
End
 
Return
 
shift: Procedure
Parse Arg in,s
out=substr(in,s+1)left(in,s)
Return out
 
E: Procedure
Parse Arg s
esel='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'
r=''
Do i=1 To words(esel)
r=r||substr(s,word(esel,i),1)
End
Return r
 
xor: Procedure
Parse Arg u,v
r=''
Do i=1 To length(u)
cc=substr(u,i,1)substr(v,i,1)
r=r||(pos(cc,'01 10')>0)
End
Return r
 
s: Procedure Expose s.
Parse Arg i,b
Parse Var b r1 +1 c +4 r2
r=r1||r2
rb=num(r)
cb=num(c)
result=s.i.rb.cb
Return num2bits(result)
 
num: Procedure
Parse Arg s
res=0
Do i=1 To length(s)
Parse Var s c +1 s
res=2*res+c
End
Return res
 
num2bits: Procedure
Parse Arg n
nx=d2x(n)
r=''
Do i=1 To 4
dig=n//2
r=dig||r
n=n%2
End
Return r
 
debug: /* Say arg(1) */ Return
Output:
I:\>rexx des2
Message: 8787878787878787
Key    : 0e329232ea6d0d73
Result : 0000000000000000

I:\>rexx des2 dec
Message: 0000000000000000
Key    : 0e329232ea6d0d73
Result : 8787878787878787

Symsyn[edit]

 
pc1 : 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
 : 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
Pc2 : 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
P : 15
 : 6
 : 19
 : 20
 : 28
 : 11
 : 27
 : 16
 : 0
 : 14
 : 22
 : 25
 : 4
 : 17
 : 30
 : 9
 : 1
 : 7
 : 23
 : 13
 : 31
 : 26
 : 2
 : 8
 : 18
 : 12
 : 29
 : 5
 : 21
 : 10
 : 3
 : 24
Ebit : 31
 : 0
 : 1
 : 2
 : 3
 : 4
 : 3
 : 4
 : 5
 : 6
 : 7
 : 8
 : 7
 : 8
 : 9
 : 10
 : 11
 : 12
 : 11
 : 12
 : 13
 : 14
 : 15
 : 16
 : 15
 : 16
 : 17
 : 18
 : 19
 : 20
 : 19
 : 20
 : 21
 : 22
 : 23
 : 24
 : 23
 : 24
 : 25
 : 26
 : 27
 : 28
 : 27
 : 28
 : 29
 : 30
 : 31
 : 0
DesIP : 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
 : 56
 : 48
 : 40
 : 32
 : 24
 : 16
 : 8
 : 0
 : 58
 : 50
 : 42
 : 34
 : 26
 : 18
 : 10
 : 2
 : 60
 : 52
 : 44
 : 36
 : 28
 : 20
 : 12
 : 4
 : 62
 : 54
 : 46
 : 38
 : 30
 : 22
 : 14
 : 6
DesIPIV : 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
 : 32
 : 0
 : 40
 : 8
 : 48
 : 16
 : 56
 : 24
DesS1 : 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
S2 : 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
S3 : 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
S4 : 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
S5 : 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
S6 : 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
S7 : 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
S8 : 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
DesShifts : 1
 : 1
 : 2
 : 2
 : 2
 : 2
 : 2
 : 2
 : 1
 : 2
 : 2
 : 2
 : 2
 : 2
 : 2
 : 1
DesHex : 0
 : 0
 : 0
 : 0
 : 0
 : 0
 : 0
 : 1
 : 0
 : 0
 : 1
 : 0
 : 0
 : 0
 : 1
 : 1
 : 0
 : 1
 : 0
 : 0
 : 0
 : 1
 : 0
 : 1
 : 0
 : 1
 : 1
 : 0
 : 0
 : 1
 : 1
 : 1
 : 1
 : 0
 : 0
 : 0
 : 1
 : 0
 : 0
 : 1
 : 1
 : 0
 : 1
 : 0
 : 1
 : 0
 : 1
 : 1
 : 1
 : 1
 : 0
 : 0
 : 1
 : 1
 : 0
 : 1
 : 1
 : 1
 : 1
 : 0
 : 1
 : 1
 : 1
 : 1
 
DesC  : 28 0
DesD  : 28 0
DesL  : 32 0
DesR  : 32 0
DesL1  : 32 0
DesR1  : 32 0
DesEK  : 48 0
DesK  : 768 0
DesWds  : 64 0
 
DesI  : 0
DesJ  : 0
DesJJ  : 0xf000
DesIter  : 0
DesSNum  : 0
OldDesKeyW : -1
DesKeyW  : 0
DesDataW : 0
DesKey = DesKeyW
DesData = DesDataW
K : 0
Kc = K
 
kprime : x'0e329232ea6d0d73'
 
dprime : x'8787878787878787'
 
 
| Program Starts Here
 
 
kprime deskey | Load encryption key
dprime desdata | Load data to be encrypted
call dodeskey | Perform key setup
call encryptdes | Encrypt data
desdata $s | Move encrypted data to string
unpackhex $s | Unpack to display
$s [] | Display
stop
 
 
| End of Program
 
 
Data2Wds
63 DesJJ
7 DesI
if DesI GE 0
DesData.DesI D
DesJ
if DesJ LE 7
and 1 D D1
D1 DesWds.DesJJ
shr D 1
- DesJJ
+ DesJ
goif
endif
- DesI
goif
endif
return
Wds2Data
DesJJ
DesI
if DesI LE 7
DesJ
if DesJ LE 7
shl D 1
if DesWds.DesJJ NE 0
+ D
endif
+ DesJJ
+ DesJ
goif
endif
D DesData.DesI
+ DesI
goif
endif
return
 
Key2Wds
63 DesJJ
7 DesI
if DesI GE 0
DesKey.DesI K
DesJ
if DesJ LE 7
and K 1 K1
K1 DesWds.DesJJ
shr K 1
- DesJJ
+ DesJ
goif
endif
- DesI
goif
endif
return
 
func
DesI
if DesI LE 47
Ebit.DesI rx
DesR.rx DesEK.DesI
+ DesI
goif
endif
* 48 DesIter DesJ
DesI
if DesI LE 47
+ DesI DesJ IJ
xor DesEK.DesI DesK.IJ DesEK.DesI
+ DesI
goif
endif
DesI
DesSNum
if DesSNum LE 7
DesEK.DesI ss
shl ss 1
+ DesI
+ DesEK.DesI ss
shl ss 1
+ DesI
+ DesEK.DesI ss
shl ss 1
+ DesI
+ DesEK.DesI ss
shl ss 1
+ DesI
+ DesEK.DesI ss
shl ss 1
+ DesI
+ DesEK.DesI ss
+ DesI
DesSNum DesS1x
Shl DesS1x 6
+ ss DesS1x
DesS1.DesS1x DesHexx
shl DesHexx 2
DesSNum DesWdsx
shl DesWdsx 2
DesHex.DesHexx DesWds.DesWdsx 4
+ DesSNum
goif
endif
DesI
if DesI LE 31
P.DesI DesJ
DesWds.DesJ DesR.DesI
+ DesI
goif
endif
return
 
DoDesKey
if DesKeyW EQ OldDesKeyW
if DesJJ NE 0xf000
return
endif
endif
DesKeyW OldDesKeyW
call Key2Wds
DesI
if DesI LE 55
Pc1.DesI Pcx
DesWds.Pcx DesC.DesI
+ DesI
goif
endif
DesJJ
DesI
if DesI LE 15
DesC.0 DesWd
DesC.1 DesC 27
DesWd DesC.27
DesD.0 DesWd
DesD.1 DesD 27
DesWd DesD.27
if DesShifts.DesI EQ 2
DesC.0 DesWd
DesC.1 DesC 27
DesWd DesC.27
DesD.0 DesWd
DesD.1 DesD 27
DesWd DesD.27
endif
DesJ
if DesJ LE 47
Pc2.DesJ DesCx
DesC.DesCx DesK.DesJJ
+ DesJJ
+ DesJ
goif
endif
+ DesI
goif
endif
return
 
EncryptDes
Call Data2Wds
DesI
if DesI LE 63
DesIP.DesI DesWdsx
DesWds.DesWdsx DesL.DesI
+ DesI
goif
endif
DesIter
if DesIter LE 15
DesR DesL1 32
call func
DesJ
if DesJ LE 31
xor DesL.DesJ DesR.DesJ
+ DesJ
goif
endif
DesL1 DesL 32
+ DesIter
goif
endif
DesL DesR1 32
DesR DesL1 32
DesI
if DesI LE 63
DesIPIV.DesI DesL1x
DesL1.DesL1x DesWds.DesI
+ DesI
goif
endif
 
call Wds2Data
return
 
DecryptDes
Call Data2Wds
DesI
if DesI LE 63
DesIP.DesI DesWdsx
DesWds.DesWdsx DesL.DesI
+ DesI
goif
endif
15 DesIter
if DesIter GE 0
DesR DesL1 32
call func
DesJ
if DesJ LE 31
xor DesL.DesJ DesR.DesJ
+ DesJ
goif
endif
DesL1 DesL 32
- DesIter
goif
endif
DesL DesR1 32
DesR DesL1 32
DesI
if DesI LE 63
DesIPIV.DesI DesL1x
DesL1.DesL1x DesWds.DesI
+ DesI
goif
endif
call Wds2Data
return
 
 

A trivial solution using the des encryption instruction:

 
 
key : x'0e329232ea6d0d73'
data : x'8787878787878787'
 
edes key data | encrypt data with key
data $s | move data to string
unpackhex $s $s | unpack
$s [] | output result - 0000000000000000
 
 
Output:
0000000000000000