Data Encryption Standard: Difference between revisions
Content added Content deleted
m (→{{header|Perl 6}}: try replacing pack/unpack) |
Thundergnat (talk | contribs) (Rename Perl 6 -> Raku, alphabetize, minor clean-up) |
||
Line 11: | Line 11: | ||
Bonus (optional): add standard padding to match the C#, Java, Modula-2, Kotlin, and Phix entries, so the above encrypted result would instead be 0000000000000000A913F4CB0BD30F97. |
Bonus (optional): add standard padding to match the C#, Java, Modula-2, Kotlin, and Phix entries, so the above encrypted result would instead be 0000000000000000A913F4CB0BD30F97. |
||
=={{header|C}}== |
=={{header|C}}== |
||
Line 531: | Line 530: | ||
Encoded : C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
Encoded : C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
||
Decoded : 596F7572206C6970732061726520736D6F6F74686572207468616E20766173656C696E650D0A</pre> |
Decoded : 596F7572206C6970732061726520736D6F6F74686572207468616E20766173656C696E650D0A</pre> |
||
=={{header|C sharp|C#}}== |
|||
<lang csharp>using System; |
|||
using System.IO; |
|||
using System.Security.Cryptography; |
|||
namespace DES { |
|||
class Program { |
|||
//Taken from https://stackoverflow.com/a/311179 |
|||
static string ByteArrayToString(byte[] ba) { |
|||
return BitConverter.ToString(ba).Replace("-", ""); |
|||
} |
|||
//Modified from https://stackoverflow.com/q/4100996 |
|||
//The passwordBytes parameter must be 8 bytes long |
|||
static byte[] Encrypt(byte[] messageBytes, byte[] passwordBytes) { |
|||
byte[] iv = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
|||
// Set encryption settings -- Use password for both key and init. vector |
|||
DESCryptoServiceProvider provider = new DESCryptoServiceProvider(); |
|||
ICryptoTransform transform = provider.CreateEncryptor(passwordBytes, iv); |
|||
CryptoStreamMode mode = CryptoStreamMode.Write; |
|||
// Set up streams and encrypt |
|||
MemoryStream memStream = new MemoryStream(); |
|||
CryptoStream cryptoStream = new CryptoStream(memStream, transform, mode); |
|||
cryptoStream.Write(messageBytes, 0, messageBytes.Length); |
|||
cryptoStream.FlushFinalBlock(); |
|||
// Read the encrypted message from the memory stream |
|||
byte[] encryptedMessageBytes = new byte[memStream.Length]; |
|||
memStream.Position = 0; |
|||
memStream.Read(encryptedMessageBytes, 0, encryptedMessageBytes.Length); |
|||
return encryptedMessageBytes; |
|||
} |
|||
//Modified from https://stackoverflow.com/q/4100996 |
|||
//The passwordBytes parameter must be 8 bytes long |
|||
static byte[] Decrypt(byte[] encryptedMessageBytes, byte[] passwordBytes) { |
|||
byte[] iv = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
|||
// Set encryption settings -- Use password for both key and init. vector |
|||
DESCryptoServiceProvider provider = new DESCryptoServiceProvider(); |
|||
ICryptoTransform transform = provider.CreateDecryptor(passwordBytes, iv); |
|||
CryptoStreamMode mode = CryptoStreamMode.Write; |
|||
// Set up streams and decrypt |
|||
MemoryStream memStream = new MemoryStream(); |
|||
CryptoStream cryptoStream = new CryptoStream(memStream, transform, mode); |
|||
cryptoStream.Write(encryptedMessageBytes, 0, encryptedMessageBytes.Length); |
|||
cryptoStream.FlushFinalBlock(); |
|||
// Read decrypted message from memory stream |
|||
byte[] decryptedMessageBytes = new byte[memStream.Length]; |
|||
memStream.Position = 0; |
|||
memStream.Read(decryptedMessageBytes, 0, decryptedMessageBytes.Length); |
|||
return decryptedMessageBytes; |
|||
} |
|||
static void Main(string[] args) { |
|||
byte[] keyBytes = new byte[] { 0x0e, 0x32, 0x92, 0x32, 0xea, 0x6d, 0x0d, 0x73 }; |
|||
byte[] plainBytes = new byte[] { 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87 }; |
|||
byte[] encStr = Encrypt(plainBytes, keyBytes); |
|||
Console.WriteLine("Encoded: {0}", ByteArrayToString(encStr)); |
|||
byte[] decBytes = Decrypt(encStr, keyBytes); |
|||
Console.WriteLine("Decoded: {0}", ByteArrayToString(decBytes)); |
|||
} |
|||
} |
|||
}</lang> |
|||
{{out}} |
|||
<pre>Encoded: 0000000000000000A913F4CB0BD30F97 |
|||
Decoded: 8787878787878787</pre> |
|||
=={{header|C++}}== |
=={{header|C++}}== |
||
Line 971: | Line 1,046: | ||
Encoded : C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
Encoded : C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
||
Decoded : 596F7572206C6970732061726520736D6F6F74686572207468616E20766173656C696E650D0A</pre> |
Decoded : 596F7572206C6970732061726520736D6F6F74686572207468616E20766173656C696E650D0A</pre> |
||
=={{header|C#|C sharp}}== |
|||
<lang csharp>using System; |
|||
using System.IO; |
|||
using System.Security.Cryptography; |
|||
namespace DES { |
|||
class Program { |
|||
//Taken from https://stackoverflow.com/a/311179 |
|||
static string ByteArrayToString(byte[] ba) { |
|||
return BitConverter.ToString(ba).Replace("-", ""); |
|||
} |
|||
//Modified from https://stackoverflow.com/q/4100996 |
|||
//The passwordBytes parameter must be 8 bytes long |
|||
static byte[] Encrypt(byte[] messageBytes, byte[] passwordBytes) { |
|||
byte[] iv = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
|||
// Set encryption settings -- Use password for both key and init. vector |
|||
DESCryptoServiceProvider provider = new DESCryptoServiceProvider(); |
|||
ICryptoTransform transform = provider.CreateEncryptor(passwordBytes, iv); |
|||
CryptoStreamMode mode = CryptoStreamMode.Write; |
|||
// Set up streams and encrypt |
|||
MemoryStream memStream = new MemoryStream(); |
|||
CryptoStream cryptoStream = new CryptoStream(memStream, transform, mode); |
|||
cryptoStream.Write(messageBytes, 0, messageBytes.Length); |
|||
cryptoStream.FlushFinalBlock(); |
|||
// Read the encrypted message from the memory stream |
|||
byte[] encryptedMessageBytes = new byte[memStream.Length]; |
|||
memStream.Position = 0; |
|||
memStream.Read(encryptedMessageBytes, 0, encryptedMessageBytes.Length); |
|||
return encryptedMessageBytes; |
|||
} |
|||
//Modified from https://stackoverflow.com/q/4100996 |
|||
//The passwordBytes parameter must be 8 bytes long |
|||
static byte[] Decrypt(byte[] encryptedMessageBytes, byte[] passwordBytes) { |
|||
byte[] iv = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
|||
// Set encryption settings -- Use password for both key and init. vector |
|||
DESCryptoServiceProvider provider = new DESCryptoServiceProvider(); |
|||
ICryptoTransform transform = provider.CreateDecryptor(passwordBytes, iv); |
|||
CryptoStreamMode mode = CryptoStreamMode.Write; |
|||
// Set up streams and decrypt |
|||
MemoryStream memStream = new MemoryStream(); |
|||
CryptoStream cryptoStream = new CryptoStream(memStream, transform, mode); |
|||
cryptoStream.Write(encryptedMessageBytes, 0, encryptedMessageBytes.Length); |
|||
cryptoStream.FlushFinalBlock(); |
|||
// Read decrypted message from memory stream |
|||
byte[] decryptedMessageBytes = new byte[memStream.Length]; |
|||
memStream.Position = 0; |
|||
memStream.Read(decryptedMessageBytes, 0, decryptedMessageBytes.Length); |
|||
return decryptedMessageBytes; |
|||
} |
|||
static void Main(string[] args) { |
|||
byte[] keyBytes = new byte[] { 0x0e, 0x32, 0x92, 0x32, 0xea, 0x6d, 0x0d, 0x73 }; |
|||
byte[] plainBytes = new byte[] { 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87 }; |
|||
byte[] encStr = Encrypt(plainBytes, keyBytes); |
|||
Console.WriteLine("Encoded: {0}", ByteArrayToString(encStr)); |
|||
byte[] decBytes = Decrypt(encStr, keyBytes); |
|||
Console.WriteLine("Decoded: {0}", ByteArrayToString(decBytes)); |
|||
} |
|||
} |
|||
}</lang> |
|||
{{out}} |
|||
<pre>Encoded: 0000000000000000A913F4CB0BD30F97 |
|||
Decoded: 8787878787878787</pre> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
Line 1,506: | Line 1,505: | ||
<pre>Encoded: 0000000000000000A913F4CB0BD30F97 |
<pre>Encoded: 0000000000000000A913F4CB0BD30F97 |
||
Decoded: 8787878787878787</pre> |
Decoded: 8787878787878787</pre> |
||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
<lang freebasic>' version 20-01-2019 |
<lang freebasic>' version 20-01-2019 |
||
Line 1,881: | Line 1,881: | ||
<pre>Encoded: 0000000000000000a913f4cb0bd30f97 |
<pre>Encoded: 0000000000000000a913f4cb0bd30f97 |
||
Decoded: 8787878787878787</pre> |
Decoded: 8787878787878787</pre> |
||
=={{header|Julia}}== |
|||
===Using the MbedTLS library=== |
|||
<lang julia>using MbedTLS |
|||
const testdata = [ |
|||
[[0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1], |
|||
[0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF]], |
|||
[[0x0E, 0x32, 0x92, 0x32, 0xEA, 0x6D, 0x0D, 0x73], |
|||
[0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87]], |
|||
[[0x0E, 0x32, 0x92, 0x32, 0xEA, 0x6D, 0x0D, 0x73], |
|||
[0x59, 0x6F, 0x75, 0x72, 0x20, 0x6C, 0x69, 0x70, 0x73, 0x20, 0x61, 0x72, 0x65, |
|||
0x20, 0x73, 0x6D, 0x6F, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, |
|||
0x6E, 0x20, 0x76, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x0D, 0x0A]] |
|||
] |
|||
for (key, message) in testdata |
|||
println("Key : $(bytes2hex(key))") |
|||
println("Message : $(bytes2hex(message))") |
|||
encoded = encrypt(CIPHER_DES, key, message) |
|||
println("Encoded : $(bytes2hex(encoded))") |
|||
decoded = decrypt(CIPHER_DES, key, encoded) |
|||
println("Decoded : $(bytes2hex(decoded))\n") |
|||
end |
|||
</lang>{{out}} |
|||
<pre> |
|||
Key : 133457799bbcdff1 |
|||
Message : 0123456789abcdef |
|||
Encoded : 85e813540f0ab40577a2a9308f18d27b |
|||
Decoded : 0123456789abcdef |
|||
Key : 0e329232ea6d0d73 |
|||
Message : 8787878787878787 |
|||
Encoded : 0000000000000000a913f4cb0bd30f97 |
|||
Decoded : 8787878787878787 |
|||
Key : 0e329232ea6d0d73 |
|||
Message : 596f7572206c6970732061726520736d6f6f74686572207468616e20766173656c696e650d0a |
|||
Encoded : c0999fdde378d7edcf813f0a8d57a539f61a9b5422a7265495b67b084b57a30700e799f58325c7b6 |
|||
Decoded : 596f7572206c6970732061726520736d6f6f74686572207468616e20766173656c696e650d0a |
|||
</pre> |
|||
===Base Julia only=== |
|||
{{trans|Phix}} |
|||
<lang julia>const PC1 = [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] |
|||
const SHIFTS = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1] |
|||
const PC2 = [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] |
|||
const 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] |
|||
const E = [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] |
|||
const S = [[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], |
|||
[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], |
|||
[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], |
|||
[ 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], |
|||
[ 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], |
|||
[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], |
|||
[ 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], |
|||
[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]] |
|||
const 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] |
|||
const IP_1 = [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] |
|||
function getsubkeys(key::Vector{UInt8}) |
|||
b = mapreduce(x -> reverse(digits(x, base=2, pad=8)), vcat, key) |
|||
kp = [UInt8(b[PC1[i]]) for i in 1:length(PC1)] |
|||
ks = [zeros(UInt8, 48) for _ in 1:16] |
|||
for i in 1:16 |
|||
shift = SHIFTS[i] |
|||
kp = vcat(kp[shift+1:28], kp[1:shift], kp[shift+29:end], kp[29:shift+28]) |
|||
for j in 1:48 |
|||
ks[i][j] = kp[PC2[j]] |
|||
end |
|||
end |
|||
return ks |
|||
end |
|||
function f(r::Vector{UInt8}, kn::Vector{UInt8}) |
|||
er, sr = [r[E[i]] ⊻ kn[i] for i in 1:48], UInt8[] |
|||
# process er six bits at a time, a total of 8 times for 48 values |
|||
for i in 1:8 |
|||
j = (i - 1) * 6 + 1 |
|||
k = sum(er[j:j+5] .* [32, 8, 4, 2, 1, 16]) + 1 |
|||
sr = vcat(sr, UInt8.(reverse(digits(S[i][k], base=2, pad=4)))) |
|||
end |
|||
return [sr[P[i]] for i in 1:32] |
|||
end |
|||
function processblock(messageblock::Vector{UInt8}, subkeys) |
|||
b = mapreduce(x -> reverse(digits(x, base=2, pad=8)), vcat, messageblock) |
|||
mp = [UInt8(b[IP[i]]) for i in 1:length(IP)] |
|||
left, right = mp[1:32], mp[33:end] |
|||
for n in 1:16 |
|||
left, right = right, left .⊻ f(right, subkeys[n]) |
|||
end |
|||
e, result = vcat(right, left), UInt8[] |
|||
for i in 0:8:63 |
|||
byte = 0 |
|||
for bit in 1:8 |
|||
byte = byte * 2 + e[IP_1[i + bit]] |
|||
end |
|||
push!(result, byte) |
|||
end |
|||
return result |
|||
end |
|||
function des(key, message, isdecode) |
|||
k = getsubkeys(key) |
|||
if isdecode |
|||
k = reverse(k) |
|||
if length(message) % 8 != 0 |
|||
throw(InexactError("Message to decode must have length a multiple of 8")) |
|||
end |
|||
else |
|||
# pad message to have a length of a multiple of the 8 byte block size |
|||
p = UInt8(8 - length(message) % 8) |
|||
message = vcat(message, fill(p, p)) |
|||
end |
|||
result = zeros(UInt8, length(message)) |
|||
@Threads.threads for i in 1:8:length(message)-1 |
|||
result[i:i+7] .= processblock(message[i:i+7], k) |
|||
end |
|||
if isdecode |
|||
# truncate based on last byte |
|||
result = result[1:end-result[end]] |
|||
end |
|||
return result |
|||
end |
|||
const testdata = [ |
|||
[[0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1], |
|||
[0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF]], |
|||
[[0x0E, 0x32, 0x92, 0x32, 0xEA, 0x6D, 0x0D, 0x73], |
|||
[0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87]], |
|||
[[0x0E, 0x32, 0x92, 0x32, 0xEA, 0x6D, 0x0D, 0x73], |
|||
[0x59, 0x6F, 0x75, 0x72, 0x20, 0x6C, 0x69, 0x70, 0x73, 0x20, 0x61, 0x72, 0x65, |
|||
0x20, 0x73, 0x6D, 0x6F, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, |
|||
0x6E, 0x20, 0x76, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x0D, 0x0A]] |
|||
] |
|||
for (key, message) in testdata |
|||
println("Key : $(bytes2hex(key))") |
|||
println("Message : $(bytes2hex(message))") |
|||
encoded = des(key, message, false) |
|||
println("Encoded : $(bytes2hex(encoded))") |
|||
decoded = des(key, encoded, true) |
|||
println("Decoded : $(bytes2hex(decoded))\n") |
|||
end |
|||
</lang> |
|||
Output: same as MbedTLS library version above. |
|||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
Line 2,265: | Line 2,475: | ||
Encoded : C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
Encoded : C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
||
Decoded : 596F7572206C6970732061726520736D6F6F74686572207468616E20766173656C696E650D0A</pre> |
Decoded : 596F7572206C6970732061726520736D6F6F74686572207468616E20766173656C696E650D0A</pre> |
||
=={{header|Julia}}== |
|||
===Using the MbedTLS library=== |
|||
<lang julia>using MbedTLS |
|||
const testdata = [ |
|||
[[0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1], |
|||
[0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF]], |
|||
[[0x0E, 0x32, 0x92, 0x32, 0xEA, 0x6D, 0x0D, 0x73], |
|||
[0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87]], |
|||
[[0x0E, 0x32, 0x92, 0x32, 0xEA, 0x6D, 0x0D, 0x73], |
|||
[0x59, 0x6F, 0x75, 0x72, 0x20, 0x6C, 0x69, 0x70, 0x73, 0x20, 0x61, 0x72, 0x65, |
|||
0x20, 0x73, 0x6D, 0x6F, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, |
|||
0x6E, 0x20, 0x76, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x0D, 0x0A]] |
|||
] |
|||
for (key, message) in testdata |
|||
println("Key : $(bytes2hex(key))") |
|||
println("Message : $(bytes2hex(message))") |
|||
encoded = encrypt(CIPHER_DES, key, message) |
|||
println("Encoded : $(bytes2hex(encoded))") |
|||
decoded = decrypt(CIPHER_DES, key, encoded) |
|||
println("Decoded : $(bytes2hex(decoded))\n") |
|||
end |
|||
</lang>{{out}} |
|||
<pre> |
|||
Key : 133457799bbcdff1 |
|||
Message : 0123456789abcdef |
|||
Encoded : 85e813540f0ab40577a2a9308f18d27b |
|||
Decoded : 0123456789abcdef |
|||
Key : 0e329232ea6d0d73 |
|||
Message : 8787878787878787 |
|||
Encoded : 0000000000000000a913f4cb0bd30f97 |
|||
Decoded : 8787878787878787 |
|||
Key : 0e329232ea6d0d73 |
|||
Message : 596f7572206c6970732061726520736d6f6f74686572207468616e20766173656c696e650d0a |
|||
Encoded : c0999fdde378d7edcf813f0a8d57a539f61a9b5422a7265495b67b084b57a30700e799f58325c7b6 |
|||
Decoded : 596f7572206c6970732061726520736d6f6f74686572207468616e20766173656c696e650d0a |
|||
</pre> |
|||
===Base Julia only=== |
|||
{{trans|Phix}} |
|||
<lang julia>const PC1 = [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] |
|||
const SHIFTS = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1] |
|||
const PC2 = [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] |
|||
const 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] |
|||
const E = [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] |
|||
const S = [[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], |
|||
[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], |
|||
[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], |
|||
[ 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], |
|||
[ 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], |
|||
[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], |
|||
[ 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], |
|||
[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]] |
|||
const 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] |
|||
const IP_1 = [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] |
|||
function getsubkeys(key::Vector{UInt8}) |
|||
b = mapreduce(x -> reverse(digits(x, base=2, pad=8)), vcat, key) |
|||
kp = [UInt8(b[PC1[i]]) for i in 1:length(PC1)] |
|||
ks = [zeros(UInt8, 48) for _ in 1:16] |
|||
for i in 1:16 |
|||
shift = SHIFTS[i] |
|||
kp = vcat(kp[shift+1:28], kp[1:shift], kp[shift+29:end], kp[29:shift+28]) |
|||
for j in 1:48 |
|||
ks[i][j] = kp[PC2[j]] |
|||
end |
|||
end |
|||
return ks |
|||
end |
|||
function f(r::Vector{UInt8}, kn::Vector{UInt8}) |
|||
er, sr = [r[E[i]] ⊻ kn[i] for i in 1:48], UInt8[] |
|||
# process er six bits at a time, a total of 8 times for 48 values |
|||
for i in 1:8 |
|||
j = (i - 1) * 6 + 1 |
|||
k = sum(er[j:j+5] .* [32, 8, 4, 2, 1, 16]) + 1 |
|||
sr = vcat(sr, UInt8.(reverse(digits(S[i][k], base=2, pad=4)))) |
|||
end |
|||
return [sr[P[i]] for i in 1:32] |
|||
end |
|||
function processblock(messageblock::Vector{UInt8}, subkeys) |
|||
b = mapreduce(x -> reverse(digits(x, base=2, pad=8)), vcat, messageblock) |
|||
mp = [UInt8(b[IP[i]]) for i in 1:length(IP)] |
|||
left, right = mp[1:32], mp[33:end] |
|||
for n in 1:16 |
|||
left, right = right, left .⊻ f(right, subkeys[n]) |
|||
end |
|||
e, result = vcat(right, left), UInt8[] |
|||
for i in 0:8:63 |
|||
byte = 0 |
|||
for bit in 1:8 |
|||
byte = byte * 2 + e[IP_1[i + bit]] |
|||
end |
|||
push!(result, byte) |
|||
end |
|||
return result |
|||
end |
|||
function des(key, message, isdecode) |
|||
k = getsubkeys(key) |
|||
if isdecode |
|||
k = reverse(k) |
|||
if length(message) % 8 != 0 |
|||
throw(InexactError("Message to decode must have length a multiple of 8")) |
|||
end |
|||
else |
|||
# pad message to have a length of a multiple of the 8 byte block size |
|||
p = UInt8(8 - length(message) % 8) |
|||
message = vcat(message, fill(p, p)) |
|||
end |
|||
result = zeros(UInt8, length(message)) |
|||
@Threads.threads for i in 1:8:length(message)-1 |
|||
result[i:i+7] .= processblock(message[i:i+7], k) |
|||
end |
|||
if isdecode |
|||
# truncate based on last byte |
|||
result = result[1:end-result[end]] |
|||
end |
|||
return result |
|||
end |
|||
const testdata = [ |
|||
[[0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1], |
|||
[0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF]], |
|||
[[0x0E, 0x32, 0x92, 0x32, 0xEA, 0x6D, 0x0D, 0x73], |
|||
[0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87]], |
|||
[[0x0E, 0x32, 0x92, 0x32, 0xEA, 0x6D, 0x0D, 0x73], |
|||
[0x59, 0x6F, 0x75, 0x72, 0x20, 0x6C, 0x69, 0x70, 0x73, 0x20, 0x61, 0x72, 0x65, |
|||
0x20, 0x73, 0x6D, 0x6F, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, |
|||
0x6E, 0x20, 0x76, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x0D, 0x0A]] |
|||
] |
|||
for (key, message) in testdata |
|||
println("Key : $(bytes2hex(key))") |
|||
println("Message : $(bytes2hex(message))") |
|||
encoded = des(key, message, false) |
|||
println("Encoded : $(bytes2hex(encoded))") |
|||
decoded = des(key, encoded, true) |
|||
println("Decoded : $(bytes2hex(decoded))\n") |
|||
end |
|||
</lang> |
|||
Output: same as MbedTLS library version above. |
|||
=={{header|Modula-2}}== |
=={{header|Modula-2}}== |
||
Line 2,536: | Line 2,535: | ||
encrypt: 0000000000000000A913F4CB0BD30F97 |
encrypt: 0000000000000000A913F4CB0BD30F97 |
||
plain: 8787878787878787</pre> |
plain: 8787878787878787</pre> |
||
=={{header|Perl 6}}== |
|||
This is mainly a translation from the Phix entry, with an additional example on UTF-8. Regarding the many conversions among different number/string formats, small (and hopefully reusable ) helper routines are created to serve the purpose. |
|||
Update 20190323: After a bug fixed an example does behave correctly and is now in line with the results from the C, D, Kotlin and Phix entries. By the way it seems ''.comb'' handle "\r\n" inconsistently, why? [https://pastebin.com/d7dBpYkL] |
|||
Update 20190325: Thanks to SqrtNegInf for pointing out that the answer is already in the documentation.[https://docs.perl6.org/type/Str#routine_chomp], [https://docs.perl6.org/language/newline] |
|||
{{trans|Phix}} |
|||
<lang perl6>#!/usr/bin/env perl6 |
|||
use v6.d; |
|||
#use experimental :pack; |
|||
my \PC1 = < |
|||
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 |
|||
>; # Permuted choice 1 (PC-1) - Parity Drop Table |
|||
my \PC2 = < |
|||
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 |
|||
>; # Permuted choice 2 (PC-2) - Key Compression Table |
|||
my \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 |
|||
>; # Initial permutation (IP) |
|||
my \IP2 = < |
|||
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 |
|||
>; # Final permutation (IP⁻¹) |
|||
my \S = ( < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> ); # 8 Substitution boxes, each replaces a 6-bit input with a 4-bit output |
|||
my \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 |
|||
>; # Permutation (P), shuffles the bits of a 32-bit half-block |
|||
# Expansion function (E), expand 32-bit half-block to 48 bits |
|||
my \E = flat 32,1..5,4..9,8..13,12..17,16..21,20..25,24..29,28..32,1; |
|||
my \SHIFTS = < 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1 >; # schedule of left shifts |
|||
## Helper subs |
|||
# convert iso-8859-1 to hexadecimals |
|||
#sub b2h (\b) { [~] map { .encode('iso-8859-1').unpack('H*') }, b.comb }; |
|||
sub b2h (\b) { b.ords.fmt('%02X', '') }; |
|||
# convert UTF8s to bytes |
|||
sub u2b (\u) { [~] map { .chr }, @( [~] map { .encode('utf8') }, u.comb) }; |
|||
# convert hexadecimals to UTF-8 |
|||
#sub h2u (\h) { pack("H" x h.chars/2, h ~~ m:g/../).decode('utf8') }; |
|||
sub h2u (\h) { Blob.new( h.comb(2).map: { :16( $_ ) } ).decode('utf8') }; |
|||
# convert quadbits to hex |
|||
sub q2h (\q) { [~] map { :2($_.Str).fmt('%X') }, q ~~ m:g/..../ }; |
|||
# convert every two quadbits to bytes |
|||
sub q2b (\q) { map { :2($_.Str) }, q ~~ m:g/. ** 8/ }; |
|||
# trun a 16 digit hexadecimal str to a 64 bits list |
|||
sub h2bits (\h) { ([~] map { :16($_).base(2).fmt('%04s') }, h.comb).split("")[1..64] }; |
|||
sub infix:<⥀>(\a is copy, \b) { a.append: a.shift for ^b ; a } # XOR addition |
|||
# convert hexadecimals to bytes |
|||
sub h2bytes (\h) { [~] map { :16($_.Str).chr }, h ~~ m:g/../ }; |
|||
# s is 16 digit hexadecimal str, M is a permuation matrix/vector |
|||
sub map64(\s, \M) { my \b = h2bits s; map { b[$_-1] }, M; } |
|||
## Core subs |
|||
sub get_subkeys(Str \key --> Seq) { # return a Seq with 16 bit vectors |
|||
my \Kₚ = map64 key, PC1; # drop parity bits |
|||
my @C = Kₚ[0..27] ; my @D = Kₚ[28..55]; # perform bits rotation next |
|||
my \CD = map { [ flat @C ⥀= SHIFTS[$_], @D ⥀= SHIFTS[$_] ]}, ^16; |
|||
return map { map { CD[$_][PC2[$^a]-1] }, ^48 }, ^16; # key compression rounds |
|||
} |
|||
sub ƒ (List \R is copy, Seq \Kₙ is copy --> Seq) { |
|||
my @er = map { Kₙ[$_] +^ R[E[$_]-1] }, ^48; |
|||
my @sr = flat map { # Sₙ(Bₙ) loop, process @er six bits at a time |
|||
((S.[$_][([~] @er[$_*6,$_*6+5]).parse-base(2)*16+([~] |
|||
@er[$_*6+1 .. $_*6+4]).parse-base(2)]).fmt('%04b').split(""))[1..4] |
|||
}, ^8; |
|||
return map { @sr[$_-1] }, P; |
|||
} |
|||
sub process_block(Str \message, \K is copy --> Str) { # return 8 quadbits |
|||
my \mp = map64 (b2h message) , IP; # turn message to hex then map to bits |
|||
my @L = mp[0..31]; my @R = mp[32..63]; |
|||
my (@Lₙ , @Rₙ); # then apply 16 iterations with function ƒ |
|||
{ @Lₙ = @R; @Rₙ = @L Z+^ ƒ @R, K[$_]; @L = @Lₙ; @R = @Rₙ } for ^16; |
|||
my \res = flat @R, @L; # reverse and join the final L₁₆ and R₁₆ |
|||
return [~] map { res[$_-1] }, IP2 ; # inverse of the initial permutation |
|||
} |
|||
sub des(Str \key, Str $msg is copy, Bool \DECODE --> Str) { # return hexdecimal |
|||
my @K; my \length = $msg.encode('iso-8859-1').bytes; |
|||
if ( DECODE and length % 8 ) { # early exit, avoid the subkeys computation |
|||
die "Message must be in multiples of 8 bytes" |
|||
} else { |
|||
@K = DECODE ?? reverse get_subkeys key !! get_subkeys key |
|||
} |
|||
{ my \P = 8 - length % 8; # number of pad bytes |
|||
$msg ~= P.chr x P ; # CMS style padding as per RFC 1423 & RFC 5652 |
|||
} unless DECODE; |
|||
my $quad ~= process_block substr($msg,$_,8), @K for |
|||
0, 8 … $msg.encode('iso-8859-1').bytes-8; |
|||
{ my @decrypt = q2b $quad; # quadbits to a byte code point list |
|||
@decrypt.pop xx @decrypt.tail; # remove padding |
|||
return b2h ( [~] map { .chr } , @decrypt ) |
|||
} if DECODE ; |
|||
return q2h $quad |
|||
} |
|||
say "Encryption examples: "; |
|||
say des "133457799BBCDFF1", h2bytes("0123456789ABCDEF"), False; |
|||
say des "0E329232EA6D0D73", h2bytes("8787878787878787"), False; |
|||
say des "0E329232EA6D0D73", "Your lips are smoother than vaseline", False; |
|||
say des "0E329232EA6D0D73", "Your lips are smoother than vaseline\r\n", False; |
|||
say des "0E329232EA6D0D73", u2b("BMP: こんにちは ; Astral plane: 𝒳𝒴𝒵"), False; |
|||
say "Decryption examples: "; |
|||
say des "133457799BBCDFF1", h2bytes("85E813540F0AB405FDF2E174492922F8"), True; |
|||
say des "0E329232EA6D0D73", h2bytes("0000000000000000A913F4CB0BD30F97"), True; |
|||
say h2bytes des "0E329232EA6D0D73", h2bytes("C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F535849980A2E7453703513E"), True; |
|||
say h2bytes des "0E329232EA6D0D73", h2bytes("C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99"), True; |
|||
say h2u des "0E329232EA6D0D73", h2bytes("C040FB6A6E72D7C36D60CA9B9A35EB38D3194468AD808103C28E33AEF0B268D0E0366C160B028DDACF340003DCA8969343EBBD289DB94774"), True;</lang> |
|||
{{out}} |
|||
<pre>Encryption examples: |
|||
85E813540F0AB405FDF2E174492922F8 |
|||
0000000000000000A913F4CB0BD30F97 |
|||
C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F535849980A2E7453703513E |
|||
C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
|||
C040FB6A6E72D7C36D60CA9B9A35EB38D3194468AD808103C28E33AEF0B268D0E0366C160B028DDACF340003DCA8969343EBBD289DB94774 |
|||
Decryption examples: |
|||
0123456789abcdef |
|||
8787878787878787 |
|||
Your lips are smoother than vaseline |
|||
Your lips are smoother than vaseline |
|||
BMP: こんにちは ; Astral plane: 𝒳𝒴𝒵</pre> |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Line 3,193: | Line 3,012: | ||
encrypted: 85e813540f0ab405 |
encrypted: 85e813540f0ab405 |
||
decrypted: 123456789abcdef</pre> |
decrypted: 123456789abcdef</pre> |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
This is mainly a translation from the Phix entry, with an additional example on UTF-8. Regarding the many conversions among different number/string formats, small (and hopefully reusable ) helper routines are created to serve the purpose. |
|||
Update 20190323: After a bug fixed an example does behave correctly and is now in line with the results from the C, D, Kotlin and Phix entries. By the way it seems ''.comb'' handle "\r\n" inconsistently, why? [https://pastebin.com/d7dBpYkL] |
|||
Update 20190325: Thanks to SqrtNegInf for pointing out that the answer is already in the documentation.[https://docs.perl6.org/type/Str#routine_chomp], [https://docs.perl6.org/language/newline] |
|||
{{trans|Phix}} |
|||
<lang perl6>#!/usr/bin/env perl6 |
|||
use v6.d; |
|||
#use experimental :pack; |
|||
my \PC1 = < |
|||
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 |
|||
>; # Permuted choice 1 (PC-1) - Parity Drop Table |
|||
my \PC2 = < |
|||
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 |
|||
>; # Permuted choice 2 (PC-2) - Key Compression Table |
|||
my \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 |
|||
>; # Initial permutation (IP) |
|||
my \IP2 = < |
|||
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 |
|||
>; # Final permutation (IP⁻¹) |
|||
my \S = ( < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> , < |
|||
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 |
|||
> ); # 8 Substitution boxes, each replaces a 6-bit input with a 4-bit output |
|||
my \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 |
|||
>; # Permutation (P), shuffles the bits of a 32-bit half-block |
|||
# Expansion function (E), expand 32-bit half-block to 48 bits |
|||
my \E = flat 32,1..5,4..9,8..13,12..17,16..21,20..25,24..29,28..32,1; |
|||
my \SHIFTS = < 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1 >; # schedule of left shifts |
|||
## Helper subs |
|||
# convert iso-8859-1 to hexadecimals |
|||
#sub b2h (\b) { [~] map { .encode('iso-8859-1').unpack('H*') }, b.comb }; |
|||
sub b2h (\b) { b.ords.fmt('%02X', '') }; |
|||
# convert UTF8s to bytes |
|||
sub u2b (\u) { [~] map { .chr }, @( [~] map { .encode('utf8') }, u.comb) }; |
|||
# convert hexadecimals to UTF-8 |
|||
#sub h2u (\h) { pack("H" x h.chars/2, h ~~ m:g/../).decode('utf8') }; |
|||
sub h2u (\h) { Blob.new( h.comb(2).map: { :16( $_ ) } ).decode('utf8') }; |
|||
# convert quadbits to hex |
|||
sub q2h (\q) { [~] map { :2($_.Str).fmt('%X') }, q ~~ m:g/..../ }; |
|||
# convert every two quadbits to bytes |
|||
sub q2b (\q) { map { :2($_.Str) }, q ~~ m:g/. ** 8/ }; |
|||
# trun a 16 digit hexadecimal str to a 64 bits list |
|||
sub h2bits (\h) { ([~] map { :16($_).base(2).fmt('%04s') }, h.comb).split("")[1..64] }; |
|||
sub infix:<⥀>(\a is copy, \b) { a.append: a.shift for ^b ; a } # XOR addition |
|||
# convert hexadecimals to bytes |
|||
sub h2bytes (\h) { [~] map { :16($_.Str).chr }, h ~~ m:g/../ }; |
|||
# s is 16 digit hexadecimal str, M is a permuation matrix/vector |
|||
sub map64(\s, \M) { my \b = h2bits s; map { b[$_-1] }, M; } |
|||
## Core subs |
|||
sub get_subkeys(Str \key --> Seq) { # return a Seq with 16 bit vectors |
|||
my \Kₚ = map64 key, PC1; # drop parity bits |
|||
my @C = Kₚ[0..27] ; my @D = Kₚ[28..55]; # perform bits rotation next |
|||
my \CD = map { [ flat @C ⥀= SHIFTS[$_], @D ⥀= SHIFTS[$_] ]}, ^16; |
|||
return map { map { CD[$_][PC2[$^a]-1] }, ^48 }, ^16; # key compression rounds |
|||
} |
|||
sub ƒ (List \R is copy, Seq \Kₙ is copy --> Seq) { |
|||
my @er = map { Kₙ[$_] +^ R[E[$_]-1] }, ^48; |
|||
my @sr = flat map { # Sₙ(Bₙ) loop, process @er six bits at a time |
|||
((S.[$_][([~] @er[$_*6,$_*6+5]).parse-base(2)*16+([~] |
|||
@er[$_*6+1 .. $_*6+4]).parse-base(2)]).fmt('%04b').split(""))[1..4] |
|||
}, ^8; |
|||
return map { @sr[$_-1] }, P; |
|||
} |
|||
sub process_block(Str \message, \K is copy --> Str) { # return 8 quadbits |
|||
my \mp = map64 (b2h message) , IP; # turn message to hex then map to bits |
|||
my @L = mp[0..31]; my @R = mp[32..63]; |
|||
my (@Lₙ , @Rₙ); # then apply 16 iterations with function ƒ |
|||
{ @Lₙ = @R; @Rₙ = @L Z+^ ƒ @R, K[$_]; @L = @Lₙ; @R = @Rₙ } for ^16; |
|||
my \res = flat @R, @L; # reverse and join the final L₁₆ and R₁₆ |
|||
return [~] map { res[$_-1] }, IP2 ; # inverse of the initial permutation |
|||
} |
|||
sub des(Str \key, Str $msg is copy, Bool \DECODE --> Str) { # return hexdecimal |
|||
my @K; my \length = $msg.encode('iso-8859-1').bytes; |
|||
if ( DECODE and length % 8 ) { # early exit, avoid the subkeys computation |
|||
die "Message must be in multiples of 8 bytes" |
|||
} else { |
|||
@K = DECODE ?? reverse get_subkeys key !! get_subkeys key |
|||
} |
|||
{ my \P = 8 - length % 8; # number of pad bytes |
|||
$msg ~= P.chr x P ; # CMS style padding as per RFC 1423 & RFC 5652 |
|||
} unless DECODE; |
|||
my $quad ~= process_block substr($msg,$_,8), @K for |
|||
0, 8 … $msg.encode('iso-8859-1').bytes-8; |
|||
{ my @decrypt = q2b $quad; # quadbits to a byte code point list |
|||
@decrypt.pop xx @decrypt.tail; # remove padding |
|||
return b2h ( [~] map { .chr } , @decrypt ) |
|||
} if DECODE ; |
|||
return q2h $quad |
|||
} |
|||
say "Encryption examples: "; |
|||
say des "133457799BBCDFF1", h2bytes("0123456789ABCDEF"), False; |
|||
say des "0E329232EA6D0D73", h2bytes("8787878787878787"), False; |
|||
say des "0E329232EA6D0D73", "Your lips are smoother than vaseline", False; |
|||
say des "0E329232EA6D0D73", "Your lips are smoother than vaseline\r\n", False; |
|||
say des "0E329232EA6D0D73", u2b("BMP: こんにちは ; Astral plane: 𝒳𝒴𝒵"), False; |
|||
say "Decryption examples: "; |
|||
say des "133457799BBCDFF1", h2bytes("85E813540F0AB405FDF2E174492922F8"), True; |
|||
say des "0E329232EA6D0D73", h2bytes("0000000000000000A913F4CB0BD30F97"), True; |
|||
say h2bytes des "0E329232EA6D0D73", h2bytes("C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F535849980A2E7453703513E"), True; |
|||
say h2bytes des "0E329232EA6D0D73", h2bytes("C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99"), True; |
|||
say h2u des "0E329232EA6D0D73", h2bytes("C040FB6A6E72D7C36D60CA9B9A35EB38D3194468AD808103C28E33AEF0B268D0E0366C160B028DDACF340003DCA8969343EBBD289DB94774"), True;</lang> |
|||
{{out}} |
|||
<pre>Encryption examples: |
|||
85E813540F0AB405FDF2E174492922F8 |
|||
0000000000000000A913F4CB0BD30F97 |
|||
C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F535849980A2E7453703513E |
|||
C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
|||
C040FB6A6E72D7C36D60CA9B9A35EB38D3194468AD808103C28E33AEF0B268D0E0366C160B028DDACF340003DCA8969343EBBD289DB94774 |
|||
Decryption examples: |
|||
0123456789abcdef |
|||
8787878787878787 |
|||
Your lips are smoother than vaseline |
|||
Your lips are smoother than vaseline |
|||
BMP: こんにちは ; Astral plane: 𝒳𝒴𝒵</pre> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
Line 3,539: | Line 3,539: | ||
}</lang> |
}</lang> |
||
{{Out}}See it running in your browser by [https://scastie.scala-lang.org/t6nGq1ebShKEA42LSIQ6Hg Scastie (JVM)]. |
{{Out}}See it running in your browser by [https://scastie.scala-lang.org/t6nGq1ebShKEA42LSIQ6Hg Scastie (JVM)]. |
||
=={{header|Symsyn}}== |
=={{header|Symsyn}}== |
||
<lang Symsyn>pc1 : 56 |
<lang Symsyn>pc1 : 56 |