Last active
November 11, 2023 14:07
-
-
Save rhaberkorn/78a982dbd49bc896175607289507cb64 to your computer and use it in GitHub Desktop.
AES in GNU APL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
⍝ Left rotate ⍺ bit | |
Rot8 ← {2⊥⍺⌽(8⍴2)⊤⍵} | |
⍝ 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 ⍺) × ⌽(8⍴2)⊤⍵} | |
⍝ 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 3⍴0 | |
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) 4⍴Key | |
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 | |
→(i≤NR×4)/Loop | |
RoundKeys ← NR 4 4⍴RoundKeys | |
∇ | |
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} | |
∇CipherText←RoundKeys Cipher PlainText; State; Round | |
State ← RoundKeys[Round←1;;] AddRoundKey ⍉4 4⍴PlainText | |
State ← {RoundKeys[Round←Round+1;;] AddRoundKey MixColumns ShiftRows SubBytes ⍵}⍣(2-⍨↑⍴RoundKeys) State | |
CipherText ← ∊⍉RoundKeys[Round+1;;] AddRoundKey ShiftRows SubBytes State | |
∇ | |
Encrypt ← {(KeyExpansion ⍺) Cipher ⍵} | |
∇PlainText←RoundKeys InvCipher CipherText; State; Round | |
State ← RoundKeys[Round←↑⍴RoundKeys;;] AddRoundKey ⍉4 4⍴CipherText | |
State ← {InvMixColumns RoundKeys[Round←Round-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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment