Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Matlab中用AES256加密/解密图像_Matlab - Fatal编程技术网

在Matlab中用AES256加密/解密图像

在Matlab中用AES256加密/解密图像,matlab,Matlab,我必须用AES256加密和解密图像。我正在做下面的程序,它加密明文 AES是一种具有128位固定长度输入的算法。它每轮分四个不同的步骤工作;AES256有14轮,正如程序所示,这是一种不同的算法 我正在寻找适应任何图像,肯定会有一个长度大于128位的主程序。我应该把它分成许多大小相同的区块,还是你有其他建议 function [output] = aes(s, oper, mode, input, iv, sbit) % AES Encrypt/decrypt array of bytes by

我必须用AES256加密和解密图像。我正在做下面的程序,它加密明文

AES是一种具有128位固定长度输入的算法。它每轮分四个不同的步骤工作;AES256有14轮,正如程序所示,这是一种不同的算法

我正在寻找适应任何图像,肯定会有一个长度大于128位的主程序。我应该把它分成许多大小相同的区块,还是你有其他建议

function [output] = aes(s, oper, mode, input, iv, sbit)
% AES Encrypt/decrypt array of bytes by AES.
% output = aes(s, oper, mode, input, iv, sbit)
% Encrypt/decrypt array of bytes by AES-128, AES-192, AES-256.
% All NIST SP800-38A cipher modes supported (e.g. ECB, CBC, OFB, CFB, CTR).
% Usage example:    out = aesdecrypt(s, 'dec', 'ecb', data)
% s:                AES structure (generated by aesinit)
% oper:             operation:
%                   'e', 'enc', 'encrypt', 'E',... = encrypt
%                   'd', 'dec', 'decrypt', 'D',... = decrypt
% mode:             operation mode
%                   'ecb' = Electronic Codebook Mode
%                   'cbc' = Cipher Block Chaining Mode
%                   'cfb' = Cipher Feedback Mode
%                   'ofb' = Output Feedback Mode
%                   'ctr' = Counter Mode
%                   For counter mode you need external AES_GET_COUNTER()
%                   counter function.
% input:            plaintext/ciphertext byte-vector with length
%                   multiple of 16
% iv:               initialize vector - some modes need it
%                   ending initialize vector is stored in s.iv, so you
%                   can use aes() repetitively to encode/decode
%                   large vector:
%                   out = aes(s, 'enc', 'cbc', input1, iv);
%                   out = [out aes(s, 'enc', 'cbc', input1, s.iv)];
%                   ...
% sbit:             bit-width parameter for CFB mode
% output:           ciphertext/plaintext byte-vector
%
% See
% Morris Dworkin, Recommendation for Block Cipher Modes of Operation
% Methods and Techniques
% NIST Special Publication 800-38A, 2001 Edition
% for details.

error(nargchk(4, 6, nargin));
validateattributes(s, {'struct'}, {});
validateattributes(oper, {'char'}, {});
validateattributes(mode, {'char'}, {});
validateattributes(input, {'numeric'}, {'real', 'vector', '>=', 0, '<', 256});
if (nargin >= 5)
    validateattributes(iv, {'numeric'}, {'real', 'vector', '>=', 0, '<', 256});
    if (length(iv) ~= 16)
        error('Length of ''iv'' must be 16.');
    end
end
if (nargin >= 6)
    validateattributes(sbit, {'numeric'}, {'real', 'scalar', '>=', 1, '<=', 128});
end

if (mod(length(input), 16))
    error('Length of ''input'' must be multiple of 16.');
end

switch lower(oper)
    case {'encrypt', 'enc', 'e'}
        oper = 0;
    case {'decrypt', 'dec', 'd'}
        oper = 1;
    otherwise
        error('Bad ''oper'' parameter.');
end

blocks = length(input)/16;
input = input(:);

switch lower(mode)

    case {'ecb'}
        % Electronic Codebook Mode
        % ------------------------
        output = zeros(1,length(input));
        idx = 1:16;
        for i = 1:blocks
            if (oper)
                % decrypt
                output(idx) = aesdecrypt(s,input(idx));
            else
                % encrypt
                output(idx) = aesencrypt(s,input(idx));
            end
            idx = idx + 16;
        end

    case {'cbc'}
        % Cipher Block Chaining Mode
        % --------------------------
        if (nargin < 5)
            error('Missing initialization vector ''iv''.');
        end
        output = zeros(1,length(input));
        ob = iv;
        idx = 1:16;
        for i = 1:blocks
            if (oper)
                % decrypt
                in = input(idx);
                output(idx) = bitxor(ob(:), aesdecrypt(s,in)');
                ob = in;
            else
                % encrypt
                ob = bitxor(ob(:), input(idx));
                ob = aesencrypt(s, ob);
                output(idx) = ob;
            end
            idx = idx + 16;
        end
        % store iv for block passing
        s.iv = ob;

    case {'cfb'}
        % Cipher Feedback Mode
        % --------------------
        % Special mode with bit manipulations
        % sbit = 1..128
        if (nargin < 6)
            error('Missing ''sbit'' parameter.');
        end
        % get number of bits
        bitlen = 8*length(input);
        % loop counter
        rounds = round(bitlen/sbit);
        % check 
        if (rem(bitlen, sbit))
            error('Message length in bits is not multiple of ''sbit''.');
        end
        % convert input to bitstream
        inputb = reshape(de2bi(input,8,2,'left-msb')',1,bitlen);
        % preset init. vector
        ib = iv;
        ibb = reshape(de2bi(ib,8,2,'left-msb')',1,128);
        % preset output binary stream
        outputb = zeros(size(inputb));
        for i = 1:rounds
            iba = aesencrypt(s, ib);
            % convert to bit, MSB first
            ibab = reshape(de2bi(iba,8,2,'left-msb')',1,128);
            % strip only sbit MSB bits
            % this goes to xor
            ibab = ibab(1:sbit);
            % strip bits from input
            inpb = inputb((i - 1)*sbit + (1:sbit));
            % make xor
            outb = bitxor(ibab, inpb);
            % write to output
            outputb((i - 1)*sbit + (1:sbit)) = outb;
            if (oper)
                % decrypt
                % prepare new iv - bit shift
                ibb = [ibb((1 + sbit):end) inpb];
            else
                % encrypt
                % prepare new iv - bit shift
                ibb = [ibb((1 + sbit):end) outb];
            end
            % back to byte ary
            ib = bi2de(vec2mat(ibb,8),'left-msb');
            % loop
        end
        output = bi2de(vec2mat(outputb,8),'left-msb');
        % store iv for block passing
        s.iv = ib;

    case {'ofb'}
        % Output Feedback Mode
        % --------------------
        if (nargin < 5)
            error('Missing initialization vector ''iv''.');
        end
        output = zeros(1,length(input));
        ib = iv;
        idx = 1:16;
        for i = 1:blocks
            % encrypt, decrypt
            ib = aesencrypt(s, ib);
            output(idx) = bitxor(ib(:), input(idx));
            idx = idx + 16;
        end
        % store iv for block passing
        s.iv = ib;

    case {'ctr'}
        % Counter Mode
        % ------------
        if (nargin < 5)
            iv = 1;
        end
        output = zeros(1,length(input));
        idx = 1:16;
        for i = (iv):(iv + blocks - 1)
            ib = AES_GET_COUNTER(i);
            ib = aesencrypt(s, ib);
            output(idx) = bitxor(ib(:), input(idx));
            idx = idx + 16;
        end
        s.iv = iv + blocks;

    otherwise
        error('Bad ''oper'' parameter.');
end
函数aesinit:

function s = aesinit(key)
% AESINIT Generate structure with s-boxes, expanded key, etc.
% Usage:            s = aesinit([23 34 168 ... 39])
% key:              16 (AES-128), 24 (AES-192), and 32 (AES-256)
%                   items array with bytes of key
% s:                AES structure for AES parameters and tables

% Stepan Matejka, 2011, matejka[at]feld.cvut.cz
% $Revision: 1.1.0 $  $Date: 2011/10/12 $

validateattributes(key,...
    {'numeric'},...
    {'real', 'vector', '>=', 0, '<=', 255});

key = key(:);
lengthkey = length(key);

switch (lengthkey)
    case 16
        rounds = 10;
    case 24
        rounds = 12;
    case 32
        rounds = 14;
    otherwise
        error('Only AES-128, AES-192, and AES-256 are supported.');
end

% fill s structure
s = {};
s.key = key;
s.bytes = lengthkey;
s.length = lengthkey * 8;
s.rounds = rounds;
% irreducible polynomial for multiplication in a finite field 0x11b
% bin2dec('100011011');
s.mod_pol = 283;

% s-box method 1 (slow)
% ---------------------

%     % multiplicative inverse table
%     % first is zero, calculate rest
%     inverse = zeros(1,256);
%     for i = 2:256
%         inverse(i) = find_inverse(i - 1, s.mod_pol);
%     end
%     
%     % generate s-box
%     s_box = zeros(1,256);
%     for i = 1:256
%         % affine transformation
%         s_box(i) = aff_trans(inverse(i));
%     end
%     s.s_box = s_box;
%     
%     % generate inverse s-box
%     inv_s_box(s_box(1:256) + 1) = (1:256) - 1;
%     s.inv_s_box = inv_s_box;

% s-box method 2 (faster)
% -----------------------

% first build logarithm lookup table and it's inverse
aes_logt = zeros(1,256);
aes_ilogt = zeros(1,256);
gen = 1;
for i = 0:255
    aes_logt(gen + 1) = i;
    aes_ilogt(i + 1) = gen;
    gen = poly_mult(gen, 3, s.mod_pol);
end
% store log tables
s.aes_logt = aes_logt;
s.aes_ilogt = aes_ilogt;
% build s-box and it's inverse
s_box = zeros(1,256);
loctable = [1 2 4 8 16 32 64 128 1 2 4 8 16 32 64 128];
for i = 0:255
    if (i == 0)
        inv = 0;
    else
        inv = aes_ilogt(255 - aes_logt(i + 1) + 1);
    end
    temp = 0;
    for bi = 0:7
        temp2 = sign(bitand(inv, loctable(bi + 1)));
        temp2 = temp2 + sign(bitand(inv, loctable(bi + 4 + 1)));
        temp2 = temp2 + sign(bitand(inv, loctable(bi + 5 + 1)));
        temp2 = temp2 + sign(bitand(inv, loctable(bi + 6 + 1)));
        temp2 = temp2 + sign(bitand(inv, loctable(bi + 7 + 1)));
        temp2 = temp2 + sign(bitand(99, loctable(bi + 1)));
        if (rem(temp2,2))
            temp = bitor(temp, loctable(bi + 1));
        end
    end
    s_box(i + 1) = temp;
end
inv_s_box(s_box(1:256) + 1) = (0:255);
% table correction (must be)
s_box(1 + 1) = 124;
inv_s_box(124 + 1) = 1;
inv_s_box(99 + 1) = 0;
s.s_box = s_box;
s.inv_s_box = inv_s_box;

% tables for fast MixColumns
mix_col2 = zeros(1,256);
mix_col3 = mix_col2;
mix_col9 = mix_col2;
mix_col11 = mix_col2;
mix_col13 = mix_col2;
mix_col14 = mix_col2;
for i = 1:256
    mix_col2(i) = poly_mult(2, i - 1, s.mod_pol);
    mix_col3(i) = poly_mult(3, i - 1, s.mod_pol);
    mix_col9(i) = poly_mult(9, i - 1, s.mod_pol);
    mix_col11(i) = poly_mult(11, i - 1, s.mod_pol);
    mix_col13(i) = poly_mult(13, i - 1, s.mod_pol);
    mix_col14(i) = poly_mult(14, i - 1, s.mod_pol);
end
s.mix_col2 = mix_col2;
s.mix_col3 = mix_col3;
s.mix_col9 = mix_col9;
s.mix_col11 = mix_col11;
s.mix_col13 = mix_col13;
s.mix_col14 = mix_col14;

% expanded key
s.keyexp = key_expansion(s.key, s.s_box, s.rounds, s.mod_pol, s.aes_logt, s.aes_ilogt);

% poly & invpoly
s.poly_mat = [...
    2 3 1 1;...
    1 2 3 1;...
    1 1 2 3;...
    3 1 1 2];

s.inv_poly_mat =[...
    14 11 13  9;...
    9  14 11 13;...
    13  9 14 11;...
    11 13  9 14];

% end of aesinit.m
% ------------------------------------------------------------------------

function p = poly_mult(a, b, mod_pol)
% Multiplication in a finite field
% For loop multiplication - slower than log/ilog tables
% but must be used for log/ilog tables generation

p = 0;
for counter = 1 : 8
    if (rem(b, 2))
        p = bitxor(p, a);
        b = (b - 1)/2;
    else
        b = b/2;
    end
    a = 2*a;
    if (a > 255)
        a = bitxor(a, mod_pol);
    end
end

% ------------------------------------------------------------------------
function inv = find_inverse(in, mod_pol)
% Multiplicative inverse for an element a of a finite field
% very bad calculate & test method
% Not used in faster version

% loop over all possible bytes
for inv = 1 : 255
    % calculate polynomial multiplication and test to be 1
    if (1 == poly_mult(in, inv, mod_pol))
        % we find it
        break
    end
end
inv = 0;

% ------------------------------------------------------------------------
function out = aff_trans(in)
% Affine transformation over GF(2^8)
% Not used for faster s-box generation

% modulo polynomial for multiplication in a finite field
% bin2dec('100000001');
mod_pol = 257;

% multiplication polynomial
% bin2dec('00011111');
mult_pol = 31;

% addition polynomial
% bin2dec('01100011');
add_pol = 99;

% polynomial multiplication
temp = poly_mult(in, mult_pol, mod_pol);

% xor with addition polynomial
out = bitxor(temp, add_pol);

% ------------------------------------------------------------------------
function expkey = key_expansion(key, s_box, rounds, mod_pol, aes_logt, aes_ilogt)
% Expansion of key

% This is old version for AES-128 (192?, 256? not tested):
% rcon = ones(1,rounds);
% for i = 2:rounds
%     rcon(i) = poly_mult(rcon(i - 1), 2, mod_pol);
% end
% % fill bytes 2, 3, and 4 by 0
% rcon = [rcon(:), zeros(rounds, 3)];
% 
% kcol = length(key)/4;
% expkey = (reshape(key, kcol, 4))';
% for i = (kcol + 1):(4*rounds + 4)
%     % copy the previous row of the expanded key into a buffer
%     temp = expkey(i - 1, :);
%     % each fourth row
%     if (mod(i, 4) == 1)
%         % shift temp
%         temp = temp([2 3 4 1]);
%         % s-box transform
%         temp = s_box(temp + 1);
%         % compute the current round constant
%         r = rcon((i - 1)/4, :);
%         % xor
%         temp = bitxor(temp, r);
%     else
%         if ((kcol > 6) && (mod(i, kcol) == 0))
%             temp = s_box(temp);
%         end
%     end
%     % generate new row of the expanded key
%     expkey(i, :) = bitxor(expkey(i - 4, :), temp);
% end

% This is new faster version for all AES:
rcon = 1;
kcol = length(key)/4;
expkey = (reshape(key,4,kcol))';
% traverse for all rounds
for i = kcol:(4*(rounds + 1) - 1)
    % copy the previous row of the expanded key into a buffer
    temp = expkey(i, :);
    % each kcol row
    if (mod(i, kcol) == 0)
        % rotate word
        temp = temp([2 3 4 1]);
        % s-box transform
        temp = s_box(temp + 1);
        % xor
        temp(1) = bitxor(temp(1), rcon);
        % new rcon
        % 1. classic poly_mult
        % rcon = poly_mult(rcon, 2, mod_pol);
        % 2. or faster version with log/ilog tables
        % note rcon is never zero here
        % rcon = aes_ilogt(mod((aes_logt(rcon + 1) + aes_logt(2 + 1)), 255) + 1);
        rcon = aes_ilogt(mod((aes_logt(rcon + 1) + 25), 255) + 1);
    else
        if ((kcol > 6) && (mod(i, kcol) == 4))
            temp = s_box(temp + 1);
        end
    end
    % generate new row of the expanded key
    expkey(i + 1, :) = bitxor(expkey(i - kcol + 1, :), temp);
end
函数s=aesinit(键)
%AESINIT使用s盒、扩展键等生成结构。
%用法:s=aesinit([23 34 168…39])
%密钥:16(AES-128)、24(AES-192)和32(AES-256)
%包含密钥字节的项数组
%s:AES参数和表的AES结构
%Stepan Matejka,2011,Matejka[at]feld.cvut.cz
%$Revision:1.1.0$$日期:2011/10/12$
验证属性(键,。。。
{'numeric'},。。。
{'real','vector','>='0',6)&(mod(i,kcol)==0))
%温度=s_盒(温度);
%结束
%结束
%%生成扩展键的新行
%expkey(i,:)=bitxor(expkey(i-4,:),temp);
%结束
%这是适用于所有AES的新的更快版本:
rcon=1;
kcol=长度(键)/4;
expkey=(重塑(键,4,kcol));
%遍历所有回合
对于i=kcol:(4*(轮数+1)-1)
%将展开键的上一行复制到缓冲区中
temp=expkey(i,:);
%每kcol行
如果(mod(i,kcol)==0)
%轮换单词
温度=温度([2 3 4 1]);
%s盒变换
温度=s_盒(温度+1);
%异或
温度(1)=位异或(温度(1),rcon);
%新rcon
%1.经典多功能
%rcon=多个(rcon,2,mod_pol);
%2.或更高版本,带有日志/ilog表
%注意rcon在这里永远不为零
%rcon=aes_ilogt(mod((aes_logt(rcon+1)+aes_logt(2+1)),255)+1);
rcon=aes_ilogt(mod((aes_logt(rcon+1)+25),255)+1);
其他的
如果((kcol>6)和&(mod(i,kcol)==4))
温度=s_盒(温度+1);
终止
终止
%生成扩展键的新行
expkey(i+1,:)=bitxor(expkey(i-kcol+1,:),temp);
终止

您被限制为128位,因为您试图使用
aesencrypt
进行加密。如果改用该函数,您可以对任何“长度为16倍的字节向量”进行编码。它将反复为您调用
aesenrypt
,直到处理完所有4x4块。

这里没有给人们很多机会来帮助您,您请求帮助修改您在web上找到的内容,而没有提及您发现了什么?对此我很抱歉。您知道此算法由4个步骤组成。我找到了这些步骤的程序但是它只是用来加密纯文本的。输入是16字节向量,我想问我应该在这个程序中做些什么来适应我的项目,而不需要参考你找到的程序。好的,我会复制你找到的。我看到了@Daniel Thank。那么实现AES来加密JPEG图像或其他格式怎么样!!@Joe.Ou:前两行CTS链接的答案解释了如何将文件读入字节数组。你不需要任何特定于JPEG图像的内容,以相同的方式对待每个文件。嘿,再次@Daniel。我对长度有一个问题,它最多是16的倍数。所以我必须填充!!我如何在加密和解密程序中进行填充。谢谢你必须填充,什么问题是这样做吗?问题是我将处理不同的图像,每个图像都有其长度(这是不可能知道的,因为我的目标是实现一个程序,可以处理matlab可以读取的所有类型的图像)。在所有情况下,长度必须是16的倍数。@Daniel
function s = aesinit(key)
% AESINIT Generate structure with s-boxes, expanded key, etc.
% Usage:            s = aesinit([23 34 168 ... 39])
% key:              16 (AES-128), 24 (AES-192), and 32 (AES-256)
%                   items array with bytes of key
% s:                AES structure for AES parameters and tables

% Stepan Matejka, 2011, matejka[at]feld.cvut.cz
% $Revision: 1.1.0 $  $Date: 2011/10/12 $

validateattributes(key,...
    {'numeric'},...
    {'real', 'vector', '>=', 0, '<=', 255});

key = key(:);
lengthkey = length(key);

switch (lengthkey)
    case 16
        rounds = 10;
    case 24
        rounds = 12;
    case 32
        rounds = 14;
    otherwise
        error('Only AES-128, AES-192, and AES-256 are supported.');
end

% fill s structure
s = {};
s.key = key;
s.bytes = lengthkey;
s.length = lengthkey * 8;
s.rounds = rounds;
% irreducible polynomial for multiplication in a finite field 0x11b
% bin2dec('100011011');
s.mod_pol = 283;

% s-box method 1 (slow)
% ---------------------

%     % multiplicative inverse table
%     % first is zero, calculate rest
%     inverse = zeros(1,256);
%     for i = 2:256
%         inverse(i) = find_inverse(i - 1, s.mod_pol);
%     end
%     
%     % generate s-box
%     s_box = zeros(1,256);
%     for i = 1:256
%         % affine transformation
%         s_box(i) = aff_trans(inverse(i));
%     end
%     s.s_box = s_box;
%     
%     % generate inverse s-box
%     inv_s_box(s_box(1:256) + 1) = (1:256) - 1;
%     s.inv_s_box = inv_s_box;

% s-box method 2 (faster)
% -----------------------

% first build logarithm lookup table and it's inverse
aes_logt = zeros(1,256);
aes_ilogt = zeros(1,256);
gen = 1;
for i = 0:255
    aes_logt(gen + 1) = i;
    aes_ilogt(i + 1) = gen;
    gen = poly_mult(gen, 3, s.mod_pol);
end
% store log tables
s.aes_logt = aes_logt;
s.aes_ilogt = aes_ilogt;
% build s-box and it's inverse
s_box = zeros(1,256);
loctable = [1 2 4 8 16 32 64 128 1 2 4 8 16 32 64 128];
for i = 0:255
    if (i == 0)
        inv = 0;
    else
        inv = aes_ilogt(255 - aes_logt(i + 1) + 1);
    end
    temp = 0;
    for bi = 0:7
        temp2 = sign(bitand(inv, loctable(bi + 1)));
        temp2 = temp2 + sign(bitand(inv, loctable(bi + 4 + 1)));
        temp2 = temp2 + sign(bitand(inv, loctable(bi + 5 + 1)));
        temp2 = temp2 + sign(bitand(inv, loctable(bi + 6 + 1)));
        temp2 = temp2 + sign(bitand(inv, loctable(bi + 7 + 1)));
        temp2 = temp2 + sign(bitand(99, loctable(bi + 1)));
        if (rem(temp2,2))
            temp = bitor(temp, loctable(bi + 1));
        end
    end
    s_box(i + 1) = temp;
end
inv_s_box(s_box(1:256) + 1) = (0:255);
% table correction (must be)
s_box(1 + 1) = 124;
inv_s_box(124 + 1) = 1;
inv_s_box(99 + 1) = 0;
s.s_box = s_box;
s.inv_s_box = inv_s_box;

% tables for fast MixColumns
mix_col2 = zeros(1,256);
mix_col3 = mix_col2;
mix_col9 = mix_col2;
mix_col11 = mix_col2;
mix_col13 = mix_col2;
mix_col14 = mix_col2;
for i = 1:256
    mix_col2(i) = poly_mult(2, i - 1, s.mod_pol);
    mix_col3(i) = poly_mult(3, i - 1, s.mod_pol);
    mix_col9(i) = poly_mult(9, i - 1, s.mod_pol);
    mix_col11(i) = poly_mult(11, i - 1, s.mod_pol);
    mix_col13(i) = poly_mult(13, i - 1, s.mod_pol);
    mix_col14(i) = poly_mult(14, i - 1, s.mod_pol);
end
s.mix_col2 = mix_col2;
s.mix_col3 = mix_col3;
s.mix_col9 = mix_col9;
s.mix_col11 = mix_col11;
s.mix_col13 = mix_col13;
s.mix_col14 = mix_col14;

% expanded key
s.keyexp = key_expansion(s.key, s.s_box, s.rounds, s.mod_pol, s.aes_logt, s.aes_ilogt);

% poly & invpoly
s.poly_mat = [...
    2 3 1 1;...
    1 2 3 1;...
    1 1 2 3;...
    3 1 1 2];

s.inv_poly_mat =[...
    14 11 13  9;...
    9  14 11 13;...
    13  9 14 11;...
    11 13  9 14];

% end of aesinit.m
% ------------------------------------------------------------------------

function p = poly_mult(a, b, mod_pol)
% Multiplication in a finite field
% For loop multiplication - slower than log/ilog tables
% but must be used for log/ilog tables generation

p = 0;
for counter = 1 : 8
    if (rem(b, 2))
        p = bitxor(p, a);
        b = (b - 1)/2;
    else
        b = b/2;
    end
    a = 2*a;
    if (a > 255)
        a = bitxor(a, mod_pol);
    end
end

% ------------------------------------------------------------------------
function inv = find_inverse(in, mod_pol)
% Multiplicative inverse for an element a of a finite field
% very bad calculate & test method
% Not used in faster version

% loop over all possible bytes
for inv = 1 : 255
    % calculate polynomial multiplication and test to be 1
    if (1 == poly_mult(in, inv, mod_pol))
        % we find it
        break
    end
end
inv = 0;

% ------------------------------------------------------------------------
function out = aff_trans(in)
% Affine transformation over GF(2^8)
% Not used for faster s-box generation

% modulo polynomial for multiplication in a finite field
% bin2dec('100000001');
mod_pol = 257;

% multiplication polynomial
% bin2dec('00011111');
mult_pol = 31;

% addition polynomial
% bin2dec('01100011');
add_pol = 99;

% polynomial multiplication
temp = poly_mult(in, mult_pol, mod_pol);

% xor with addition polynomial
out = bitxor(temp, add_pol);

% ------------------------------------------------------------------------
function expkey = key_expansion(key, s_box, rounds, mod_pol, aes_logt, aes_ilogt)
% Expansion of key

% This is old version for AES-128 (192?, 256? not tested):
% rcon = ones(1,rounds);
% for i = 2:rounds
%     rcon(i) = poly_mult(rcon(i - 1), 2, mod_pol);
% end
% % fill bytes 2, 3, and 4 by 0
% rcon = [rcon(:), zeros(rounds, 3)];
% 
% kcol = length(key)/4;
% expkey = (reshape(key, kcol, 4))';
% for i = (kcol + 1):(4*rounds + 4)
%     % copy the previous row of the expanded key into a buffer
%     temp = expkey(i - 1, :);
%     % each fourth row
%     if (mod(i, 4) == 1)
%         % shift temp
%         temp = temp([2 3 4 1]);
%         % s-box transform
%         temp = s_box(temp + 1);
%         % compute the current round constant
%         r = rcon((i - 1)/4, :);
%         % xor
%         temp = bitxor(temp, r);
%     else
%         if ((kcol > 6) && (mod(i, kcol) == 0))
%             temp = s_box(temp);
%         end
%     end
%     % generate new row of the expanded key
%     expkey(i, :) = bitxor(expkey(i - 4, :), temp);
% end

% This is new faster version for all AES:
rcon = 1;
kcol = length(key)/4;
expkey = (reshape(key,4,kcol))';
% traverse for all rounds
for i = kcol:(4*(rounds + 1) - 1)
    % copy the previous row of the expanded key into a buffer
    temp = expkey(i, :);
    % each kcol row
    if (mod(i, kcol) == 0)
        % rotate word
        temp = temp([2 3 4 1]);
        % s-box transform
        temp = s_box(temp + 1);
        % xor
        temp(1) = bitxor(temp(1), rcon);
        % new rcon
        % 1. classic poly_mult
        % rcon = poly_mult(rcon, 2, mod_pol);
        % 2. or faster version with log/ilog tables
        % note rcon is never zero here
        % rcon = aes_ilogt(mod((aes_logt(rcon + 1) + aes_logt(2 + 1)), 255) + 1);
        rcon = aes_ilogt(mod((aes_logt(rcon + 1) + 25), 255) + 1);
    else
        if ((kcol > 6) && (mod(i, kcol) == 4))
            temp = s_box(temp + 1);
        end
    end
    % generate new row of the expanded key
    expkey(i + 1, :) = bitxor(expkey(i - kcol + 1, :), temp);
end