Skip to content

Instantly share code, notes, and snippets.

@rhaberkorn
Last active November 11, 2023 14:07
Show Gist options
  • Save rhaberkorn/78a982dbd49bc896175607289507cb64 to your computer and use it in GitHub Desktop.
Save rhaberkorn/78a982dbd49bc896175607289507cb64 to your computer and use it in GitHub Desktop.
AES in GNU APL
⍝ 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