nixfiles/libs/aes/default.nix
Sebastian Walz 9f7b02e1cd
Tohu vaBohu
2023-04-03 14:38:02 +02:00

148 lines
5.0 KiB
Nix

{
authData ? [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ],
counter ? [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ],
key,
text
}:
let
inherit(builtins) bitAnd bitXor concatStringsSep elemAt foldl' map trace deepSeq stringLength substring;
inherit(import ./ascii.nix) toDWords hex;
encryptAES = import ./aes.nix;
trace'
= x: trace (deepSeq x x);
traceHex
= value:
trace' (map hex value);
key' = toDWords key;
counter' = toDWords counter;
encryptChunk = encryptAES key';
shift1 = 256;
shift2 = 256 * 256;
shift3 = 256 * 256 * 256;
byteAt
= dword:
index:
if index == 0 then bitAnd dword 255
else if index == 1 then bitAnd (dword / shift1) 255
else if index == 2 then bitAnd (dword / shift2) 255
else if index == 3 then dword / shift3
else null;
H = encryptChunk [ 0 0 0 0 ];
max = 256 * 256 * 256 * 256 - 1;
increment
= counter:
let
a = elemAt counter 0;
b = elemAt counter 1;
c = elemAt counter 2;
d = elemAt counter 3;
inc
= value:
let
a = byteAt value 0;
b = byteAt value 1;
c = byteAt value 2;
d = byteAt value 3;
in
if d == 255
then
if c == 255
then
if b == 255
then
if a == 255
then
{ value = 0; carry = true; }
else
{ value = bitAnd value (shift1 - 1) + 1; carry = false; }
else
{ value = bitAnd value (shift2 - 1) + shift1; carry = false; }
else
{ value = bitAnd value (shift3 - 1) + shift2; carry = false; }
else
{ value = value + shift3; carry = false; };
a' = inc a;
b' = inc b;
c' = inc c;
d' = inc d;
in
if !d'.carry then [ a b c d'.value ]
else if !c'.carry then [ a b c'.value 0 ]
else if !b'.carry then [ a b'.value 0 0 ]
else if !a'.carry then [ a'.value 0 0 0 ]
else [ 0 0 0 0 ];
multiply
= authData:
[ 0 0 0 0 ]; # ghash
encrypted
= foldl'
(
{ auth, authData, cipherText, counter, index, key }:
plain:
let
auth'
= if index == 3
then
elemAt (multiply authData)
else
auth;
authData'
= if index == 3
then
[]
else
authData;
counter'
= if index == 3
then
increment counter
else
counter;
index'
= if index == 3
then
0
else
index + 1;
key'
= if index == 3
then
elemAt (encryptChunk counter)
else
key;
cipher = bitXor plain ( key' index' );
in
# trace "${hex plain} ^ ${hex (key' index')} = ${hex cipher}"
{
auth = auth';
authData = authData ++ [ (bitXor cipher (auth' index')) ];
cipherText = cipherText ++ [ cipher ];
counter = counter';
index = index';
key = key';
}
)
{
auth = elemAt (toDWords authData);
authData = [];
cipherText = [];
counter = counter';
index = 3;
key = null;
}
(toDWords text);
in
# traceHex key'
substring 0 (stringLength text) (concatStringsSep "" (map hex encrypted.cipherText))