aboutsummaryrefslogtreecommitdiff
path: root/aes.apl
diff options
context:
space:
mode:
authorRobin Haberkorn <rhaberkorn@fmsbw.de>2025-10-06 00:48:48 +0300
committerRobin Haberkorn <rhaberkorn@fmsbw.de>2025-10-06 00:48:48 +0300
commitad9e7cd5117c965222aae708f660e56d537914fc (patch)
tree580006656ec76513500170e5646e92e7819c6c0b /aes.apl
downloadsnippets-ad9e7cd5117c965222aae708f660e56d537914fc.tar.gz
imported all of my Github gists from https://gist.github.com/rhaberkorn
Diffstat (limited to 'aes.apl')
-rw-r--r--aes.apl69
1 files changed, 69 insertions, 0 deletions
diff --git a/aes.apl b/aes.apl
new file mode 100644
index 0000000..1edf113
--- /dev/null
+++ b/aes.apl
@@ -0,0 +1,69 @@
+⍝ 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