aboutsummaryrefslogtreecommitdiff
path: root/aes.apl
blob: 1edf113a2e1c2d68660c765e7931ad236d95a610 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
⍝ AES in GNU APL

⍝ Left rotate ⍺ bit
Rot8  {2(82)}
⍝ Addition and subtraction in finite field GF(2)
Add2  { ⊤≠ }
⍝ Multiplication in GF(2) [x]/(x8 + x4 + x3 + x + 1)
Mul2  {⊤≠/({,$FF ⊤∧ ($11B×$80¯1) ⊤≠ 2ׯ1}7 ) × (82)}

⍝ Multiplicative inverse, calculated by brute force
Mul2Inv  {$FF ⊤∧ 1 Mul2¨255}
SBox     {⊤≠/$63,(1-5) Rot8¨Mul2Inv }¨1-256
InvSBox  {Mul2Inv ⊤≠/$5,(1 3 6) Rot8¨}¨1-256
⍝ ⎕ ← 16 16⍴6 ⎕CR¨SBox
⍝ ⎕ ← 16 16⍴6 ⎕CR¨InvSBox

⍝ Round constants (in rows)
Rcon  (10 1$01 $02 $04 $08 $10 $20 $40 $80 $1B $36),10 30

RotWord  {1}
SubWord  {SBox[+1]} ⍝ See SubBytes

⍝ Round keys based on Key (array of 8-bit integers)
RoundKeys  KeyExpansion Key; NK; NR; i
  NK  4÷↑⍴Key
  ⍝ Rounds: 11 for AES-128, 13 for AES-192, 15 for AES-256 (see NIST p.18)
  NR  NK+6+1 ⍝ We need one key more than rounds
  RoundKeys  (NR×4) 4Key
  i  1+NK
Loop:
  RoundKeys[i;]  {Rcon[i÷NK;] ⊤≠ SubWord RotWord }(0=NK|i-1) RoundKeys[i-1;]
  RoundKeys[i;]  RoundKeys[i-NK;] ⊤≠ SubWord((NK>6)  4=NK|i-1) RoundKeys[i;]
  i  i+1
(iNR×4)/Loop
  RoundKeys  NR 4 4RoundKeys


AddRoundKey    { ⊤≠ } ⍝ This is also its inverse
SubBytes       {SBox[+1]}
InvSubBytes    {InvSBox[+1]}
ShiftRows      {1-4}
InvShiftRows   {1+-⍳4}
MixColumns     { ⊤≠.Mul2 (-⍳4)(0 1) 3 1 1 2}
InvMixColumns  { ⊤≠.Mul2 (-⍳4)(0 1) $b $d $9 $e}

CipherTextRoundKeys Cipher PlainText; State; Round
  State  RoundKeys[Round1;;] AddRoundKey 4 4PlainText
  State  {RoundKeys[RoundRound+1;;] AddRoundKey MixColumns ShiftRows SubBytes }(2-↑⍴RoundKeys) State
  CipherText  ∊⍉RoundKeys[Round+1;;] AddRoundKey ShiftRows SubBytes State

Encrypt  {(KeyExpansion ) Cipher }

PlainTextRoundKeys InvCipher CipherText; State; Round
  State  RoundKeys[Round↑⍴RoundKeys;;] AddRoundKey 4 4CipherText
  State  {InvMixColumns RoundKeys[RoundRound-1;;] AddRoundKey InvSubBytes InvShiftRows }(2-↑⍴RoundKeys) State
  PlainText  ∊⍉RoundKeys[Round-1;;] AddRoundKey InvSubBytes InvShiftRows State

Decrypt  {(KeyExpansion ) InvCipher }

RoundKeys  KeyExpansion ⎕UCS 13 ⎕CR '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'
⍝ 5 ⎕CR RoundKeys

CipherText  RoundKeys Cipher ⎕UCS 'Hello world!!!!!'
  6 ⎕CR¨CipherText
⍝ To check the cipher text:
⍝ echo -en 'Hello world!!!!!' | openssl enc -aes-256-ecb -nosalt -nopad -K '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' | hexdump -C

PlainText  ⎕UCS RoundKeys InvCipher CipherText
  PlainText