Data Encryption Standard: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) m (→{{header|F#|F sharp}}: Regularize header markup to recommended on category page) |
(→{{header|Raku}}: major revision) |
||
Line 3,570: | Line 3,570: | ||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(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] |
|||
⚫ | |||
{{trans|Phix}} |
{{trans|Phix}} |
||
<lang perl6> |
<lang perl6>20220222 Updated Raku programming solution |
||
#use experimental :pack; |
|||
⚫ | |||
my \PC1 = < |
my \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 |
|||
>; # Permuted choice 1 (PC-1) - Parity Drop Table |
>; # Permuted choice 1 (PC-1) - Parity Drop Table |
||
my \PC2 = < |
my \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 |
|||
>; # Permuted choice 2 (PC-2) - Key Compression Table |
>; # Permuted choice 2 (PC-2) - Key Compression Table |
||
my \IP = < |
my \IP = < |
||
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 |
|||
>; # Initial permutation (IP) |
>; # Initial permutation (IP) |
||
my \IP2 = < |
my \IP2 = < |
||
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 |
|||
>; # Final permutation (IP⁻¹) |
>; # Final permutation (IP⁻¹) |
||
Line 3,631: | Line 3,628: | ||
my \P = < |
my \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 |
|||
>; # Permutation (P), shuffles the bits of a 32-bit half-block |
>; # Permutation (P), shuffles the bits of a 32-bit half-block |
||
# Expansion function (E), expand 32-bit half-block to 48 bits |
# Expansion function (E), expand 32-bit half-block to 48 bits |
||
my \E = flat |
my \E = flat 31,0..4,3..8,7..12,11..16,15..20,19..24,23..28,27..31,0; |
||
my \SHIFTS = |
my \SHIFTS = flat 1, 1, 2 xx 6, 1, 2 xx 6, 1 ; # schedule of left shifts |
||
## Helper subs |
## Helper subs |
||
# convert iso-8859-1 to hexadecimals |
# convert iso-8859-1 to hexadecimals(%02X) |
||
sub b2h (\b) { b.ords.fmt('%02X','') } |
|||
⚫ | |||
sub b2h (\b) { b.ords.fmt('%02X', '') }; |
|||
# convert UTF8s to bytes |
# convert UTF8s to bytes |
||
sub u2b (\u) { |
sub u2b (\u) { u.encode.list.chrs } |
||
# convert hexadecimals to UTF-8 |
# convert hexadecimals(%02X) to UTF-8 |
||
sub h2u (\h) { Blob.new( h.comb(2)».&{ :16($_) } ).decode }; |
|||
sub h2u (\h) { Blob.new( h.comb(2).map: { :16( $_ ) } ).decode('utf8') }; |
|||
# convert quadbits to hex |
# convert quadbits to hex |
||
sub q2h (\q) { [~] |
sub q2h (\q) { [~] q.comb(4)».&{ :2($_).fmt('%X') } }; |
||
# convert every two quadbits to bytes |
# convert every two quadbits to bytes |
||
sub q2b (\q) { |
sub q2b (\q) { q.comb(8)».&{ :2($_) } }; |
||
# |
# turn a 16 digit hexadecimal str to a 64 bits list |
||
sub |
sub h2b (\h) { flat h.comb».&{ :16($_).base(2).fmt('%04s').comb } }; |
||
sub infix:<⥀>(\a is copy, \b) { a.append: a.shift for ^b ; a } # XOR addition |
|||
# convert hexadecimals to bytes |
# convert hexadecimals to bytes |
||
sub |
sub h2B (\h) { [~] h.comb(2)».&{ chr "0x$_" } }; |
||
# s is 16 digit hexadecimal str, M is a permuation matrix/vector |
# s is 16 digit hexadecimal str, M is a permuation matrix/vector |
||
sub map64(\s, |
sub map64(\s,\M) { (h2b s)[M] } |
||
## Core subs |
## Core subs |
||
Line 3,675: | Line 3,668: | ||
my \Kₚ = map64 key, PC1; # drop parity bits |
my \Kₚ = map64 key, PC1; # drop parity bits |
||
my @C = Kₚ[0..27] ; my @D = Kₚ[28..55]; # perform bits rotation next |
my @C = Kₚ[0..27] ; my @D = Kₚ[28..55]; # perform bits rotation next |
||
my \CD = |
my \CD = (^16)».&{ [ |@C.=rotate(SHIFTS[$_]), |@D.=rotate(SHIFTS[$_]) ] } |
||
# key compression rounds |
|||
return (^16).map: -> \row { (^48).map: -> \col { CD[row][ PC2[col] ] } } |
|||
} |
} |
||
sub ƒ (List \R |
sub ƒ (List \R, Seq \Kₙ --> List) { |
||
my @er = map { Kₙ[$_] +^ R[E[$_] |
my @er = map { Kₙ[$_] +^ R[E[$_]] }, ^48; |
||
return ( flat (^8)».&{ # Sₙ(Bₙ) loop, process @er six bits at a time |
|||
⚫ | |||
S[$_][ ([~] @er[$_*6 , $_*6+5]).parse-base(2)*16 + # 2 bits |
|||
⚫ | |||
}, ^8; |
|||
.fmt('%04b').comb } # ((S[][] to binary).split)*8.flat |
|||
return map { @sr[$_-1] }, P; |
|||
)[P] |
|||
} |
} |
||
sub process_block(Str \message, \K |
sub process_block(Str \message, Seq \K --> Str) { # return 8 quadbits |
||
my \mp = map64 (b2h message) , IP; # turn message to hex then map to bits |
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 = mp[0..31]; my @R = mp[32..63]; # then apply 16 iterations of ƒ |
||
my |
{ my @Lₙ = @R; my @Rₙ = @L Z+^ ƒ @R, K[$_]; @L = @Lₙ; @R = @Rₙ } for ^16; |
||
{ @Lₙ = @R; @Rₙ = @L Z+^ ƒ @R, K[$_]; @L = @Lₙ; @R = @Rₙ } for ^16; |
|||
return [~] (|@R, |@L)[IP2] # inverse of the initial permutation |
|||
return [~] map { res[$_-1] }, IP2 ; # inverse of the initial permutation |
|||
} |
} |
||
sub des(Str \key, Str $msg is copy, Bool \DECODE --> Str) { # return hexdecimal |
sub des(Str \key, Str $msg is copy, Bool \DECODE --> Str) { # return hexdecimal |
||
⚫ | |||
if ( DECODE and length % 8 ) { # early exit, avoid the subkeys computation |
|||
⚫ | |||
} else { |
|||
@K = DECODE ?? reverse get_subkeys key !! get_subkeys key |
|||
} |
|||
⚫ | |||
⚫ | |||
} unless DECODE; |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} if DECODE ; |
|||
my \K = do given get_subkeys key { DECODE ?? reverse $_ !! $_ } |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
} |
||
say "Encryption examples: "; |
say "Encryption examples: "; |
||
say des "133457799BBCDFF1", |
say des "133457799BBCDFF1", h2B("0123456789ABCDEF"), False; |
||
say des "0E329232EA6D0D73", |
say des "0E329232EA6D0D73", h2B("8787878787878787"), False; |
||
say des "0E329232EA6D0D73", "Your lips are smoother than vaseline", 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", "Your lips are smoother than vaseline\r\n", False; |
||
say des "0E329232EA6D0D73", u2b("BMP: こんにちは ; Astral plane: 𝒳𝒴𝒵"), False; |
say des "0E329232EA6D0D73", u2b("BMP: こんにちは ; Astral plane: 𝒳𝒴𝒵"), False; |
||
say " |
say "\nDecryption examples: "; |
||
say des "133457799BBCDFF1", |
say des "133457799BBCDFF1", h2B("85E813540F0AB405FDF2E174492922F8"), True; |
||
say des "0E329232EA6D0D73", |
say des "0E329232EA6D0D73", h2B("0000000000000000A913F4CB0BD30F97"), True; |
||
say |
say h2B des "0E329232EA6D0D73", h2B("C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F535849980A2E7453703513E"), True; |
||
say |
say h2B des "0E329232EA6D0D73", h2B("C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99"), True; |
||
say h2u des "0E329232EA6D0D73", |
say h2u des "0E329232EA6D0D73", h2B("C040FB6A6E72D7C36D60CA9B9A35EB38D3194468AD808103C28E33AEF0B268D0E0366C160B028DDACF340003DCA8969343EBBD289DB94774"), True; </lang> |
||
{{out}} |
{{out}} |
||
<pre>Encryption examples: |
<pre>Encryption examples: |
||
Line 3,739: | Line 3,731: | ||
C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F53584997F922CCB5B068D99 |
||
C040FB6A6E72D7C36D60CA9B9A35EB38D3194468AD808103C28E33AEF0B268D0E0366C160B028DDACF340003DCA8969343EBBD289DB94774 |
C040FB6A6E72D7C36D60CA9B9A35EB38D3194468AD808103C28E33AEF0B268D0E0366C160B028DDACF340003DCA8969343EBBD289DB94774 |
||
Decryption examples: |
Decryption examples: |
||
0123456789abcdef |
0123456789abcdef |